diff --git a/api/proto/activity/v1/activity.pb.go b/api/proto/activity/v1/activity.pb.go index 0eeff0d6..b204fdc8 100644 --- a/api/proto/activity/v1/activity.pb.go +++ b/api/proto/activity/v1/activity.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v5.29.2 +// protoc v7.35.0 // source: proto/activity/v1/activity.proto package activityv1 diff --git a/api/proto/activity/v1/activity_grpc.pb.go b/api/proto/activity/v1/activity_grpc.pb.go index a84580ea..c4af8c40 100644 --- a/api/proto/activity/v1/activity_grpc.pb.go +++ b/api/proto/activity/v1/activity_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.6.2 -// - protoc v5.29.2 +// - protoc v7.35.0 // source: proto/activity/v1/activity.proto package activityv1 diff --git a/api/proto/events/luckygift/v1/events.pb.go b/api/proto/events/luckygift/v1/events.pb.go index 5e46e37c..194c68f0 100644 --- a/api/proto/events/luckygift/v1/events.pb.go +++ b/api/proto/events/luckygift/v1/events.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v5.29.2 +// protoc v7.35.0 // source: proto/events/luckygift/v1/events.proto package luckygifteventsv1 diff --git a/api/proto/events/room/v1/events.pb.go b/api/proto/events/room/v1/events.pb.go index 23a8a872..adb88b4a 100644 --- a/api/proto/events/room/v1/events.pb.go +++ b/api/proto/events/room/v1/events.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v5.29.2 +// protoc v7.35.0 // source: proto/events/room/v1/events.proto package roomeventsv1 diff --git a/api/proto/game/v1/game.pb.go b/api/proto/game/v1/game.pb.go index 358b1668..6ed173eb 100644 --- a/api/proto/game/v1/game.pb.go +++ b/api/proto/game/v1/game.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v5.29.2 +// protoc v7.35.0 // source: proto/game/v1/game.proto package gamev1 diff --git a/api/proto/game/v1/game_grpc.pb.go b/api/proto/game/v1/game_grpc.pb.go index 27c5cf40..cb1b15c4 100644 --- a/api/proto/game/v1/game_grpc.pb.go +++ b/api/proto/game/v1/game_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.6.2 -// - protoc v5.29.2 +// - protoc v7.35.0 // source: proto/game/v1/game.proto package gamev1 diff --git a/api/proto/luckygift/v1/luckygift.pb.go b/api/proto/luckygift/v1/luckygift.pb.go index e98f7e06..4e448bb8 100644 --- a/api/proto/luckygift/v1/luckygift.pb.go +++ b/api/proto/luckygift/v1/luckygift.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.36.11 // protoc v7.35.0 // source: proto/luckygift/v1/luckygift.proto @@ -11,6 +11,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -23,15 +24,14 @@ const ( // RequestMeta 是 lucky-gift-service 的内部追踪元信息。 // request_id 只用于链路排查,不能被任何业务流程当成幂等键使用。 type RequestMeta struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + Caller string `protobuf:"bytes,2,opt,name=caller,proto3" json:"caller,omitempty"` + GatewayNodeId string `protobuf:"bytes,3,opt,name=gateway_node_id,json=gatewayNodeId,proto3" json:"gateway_node_id,omitempty"` + SentAtMs int64 `protobuf:"varint,4,opt,name=sent_at_ms,json=sentAtMs,proto3" json:"sent_at_ms,omitempty"` + AppCode string `protobuf:"bytes,5,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` unknownFields protoimpl.UnknownFields - - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - Caller string `protobuf:"bytes,2,opt,name=caller,proto3" json:"caller,omitempty"` - GatewayNodeId string `protobuf:"bytes,3,opt,name=gateway_node_id,json=gatewayNodeId,proto3" json:"gateway_node_id,omitempty"` - SentAtMs int64 `protobuf:"varint,4,opt,name=sent_at_ms,json=sentAtMs,proto3" json:"sent_at_ms,omitempty"` - AppCode string `protobuf:"bytes,5,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RequestMeta) Reset() { @@ -102,24 +102,21 @@ func (x *RequestMeta) GetAppCode() string { // LuckyGiftMeta 是 HyApp 内部房间送礼扣费成功后的抽奖事实输入。 // 金额、目标用户和 command_id 必须来自 wallet-service 已落账的 receipt,不能从客户端 payload 推导。 type LuckyGiftMeta struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - 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"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - DeviceId string `protobuf:"bytes,4,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` - RoomId string `protobuf:"bytes,5,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - AnchorId string `protobuf:"bytes,6,opt,name=anchor_id,json=anchorId,proto3" json:"anchor_id,omitempty"` - GiftId string `protobuf:"bytes,7,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - CoinSpent int64 `protobuf:"varint,8,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` - PaidAtMs int64 `protobuf:"varint,9,opt,name=paid_at_ms,json=paidAtMs,proto3" json:"paid_at_ms,omitempty"` - PoolId string `protobuf:"bytes,10,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - TargetUserId int64 `protobuf:"varint,11,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - GiftCount int32 `protobuf:"varint,12,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` - VisibleRegionId int64 `protobuf:"varint,13,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - CountryId int64 `protobuf:"varint,14,opt,name=country_id,json=countryId,proto3" json:"country_id,omitempty"` + 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"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + DeviceId string `protobuf:"bytes,4,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` + RoomId string `protobuf:"bytes,5,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + AnchorId string `protobuf:"bytes,6,opt,name=anchor_id,json=anchorId,proto3" json:"anchor_id,omitempty"` + GiftId string `protobuf:"bytes,7,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + CoinSpent int64 `protobuf:"varint,8,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` + PaidAtMs int64 `protobuf:"varint,9,opt,name=paid_at_ms,json=paidAtMs,proto3" json:"paid_at_ms,omitempty"` + PoolId string `protobuf:"bytes,10,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + TargetUserId int64 `protobuf:"varint,11,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + GiftCount int32 `protobuf:"varint,12,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` + VisibleRegionId int64 `protobuf:"varint,13,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + CountryId int64 `protobuf:"varint,14,opt,name=country_id,json=countryId,proto3" json:"country_id,omitempty"` // sender_* 是 room-service 在送礼入口已经确认的展示快照,只进入中奖事实和 IM,不能参与抽奖或账务判断。 SenderName string `protobuf:"bytes,15,opt,name=sender_name,json=senderName,proto3" json:"sender_name,omitempty"` SenderAvatar string `protobuf:"bytes,16,opt,name=sender_avatar,json=senderAvatar,proto3" json:"sender_avatar,omitempty"` @@ -134,6 +131,8 @@ type LuckyGiftMeta struct { // user_registered_at_ms 是 user-service 在送礼入口返回的账号创建事实快照。 // dynamic_v3 只用它判断闭窗时账号是否已满 48 小时;缺失时普通开奖继续,但补偿大奖资格 fail-close。 UserRegisteredAtMs int64 `protobuf:"varint,23,opt,name=user_registered_at_ms,json=userRegisteredAtMs,proto3" json:"user_registered_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *LuckyGiftMeta) Reset() { @@ -328,16 +327,15 @@ func (x *LuckyGiftMeta) GetUserRegisteredAtMs() int64 { } type LuckyGiftRuleTier struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Stage string `protobuf:"bytes,1,opt,name=stage,proto3" json:"stage,omitempty"` + TierId string `protobuf:"bytes,2,opt,name=tier_id,json=tierId,proto3" json:"tier_id,omitempty"` + MultiplierPpm int64 `protobuf:"varint,3,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` + BaseWeightPpm int64 `protobuf:"varint,4,opt,name=base_weight_ppm,json=baseWeightPpm,proto3" json:"base_weight_ppm,omitempty"` + HighWaterOnly bool `protobuf:"varint,5,opt,name=high_water_only,json=highWaterOnly,proto3" json:"high_water_only,omitempty"` + Enabled bool `protobuf:"varint,6,opt,name=enabled,proto3" json:"enabled,omitempty"` unknownFields protoimpl.UnknownFields - - Stage string `protobuf:"bytes,1,opt,name=stage,proto3" json:"stage,omitempty"` - TierId string `protobuf:"bytes,2,opt,name=tier_id,json=tierId,proto3" json:"tier_id,omitempty"` - MultiplierPpm int64 `protobuf:"varint,3,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` - BaseWeightPpm int64 `protobuf:"varint,4,opt,name=base_weight_ppm,json=baseWeightPpm,proto3" json:"base_weight_ppm,omitempty"` - HighWaterOnly bool `protobuf:"varint,5,opt,name=high_water_only,json=highWaterOnly,proto3" json:"high_water_only,omitempty"` - Enabled bool `protobuf:"varint,6,opt,name=enabled,proto3" json:"enabled,omitempty"` + sizeCache protoimpl.SizeCache } func (x *LuckyGiftRuleTier) Reset() { @@ -413,15 +411,14 @@ func (x *LuckyGiftRuleTier) GetEnabled() bool { } type LuckyGiftRuleStage struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Stage string `protobuf:"bytes,1,opt,name=stage,proto3" json:"stage,omitempty"` - Tiers []*LuckyGiftRuleTier `protobuf:"bytes,2,rep,name=tiers,proto3" json:"tiers,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Stage string `protobuf:"bytes,1,opt,name=stage,proto3" json:"stage,omitempty"` + Tiers []*LuckyGiftRuleTier `protobuf:"bytes,2,rep,name=tiers,proto3" json:"tiers,omitempty"` // 两个充值门槛共同决定 dynamic_v3 分层;novice 固定为 0/0,后续阶段逐维单调递增。 MinRecharge_7DCoins int64 `protobuf:"varint,3,opt,name=min_recharge_7d_coins,json=minRecharge7dCoins,proto3" json:"min_recharge_7d_coins,omitempty"` MinRecharge_30DCoins int64 `protobuf:"varint,4,opt,name=min_recharge_30d_coins,json=minRecharge30dCoins,proto3" json:"min_recharge_30d_coins,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *LuckyGiftRuleStage) Reset() { @@ -483,25 +480,22 @@ func (x *LuckyGiftRuleStage) GetMinRecharge_30DCoins() int64 { } type LuckyGiftRuleConfig struct { - 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"` - PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - RuleVersion int64 `protobuf:"varint,3,opt,name=rule_version,json=ruleVersion,proto3" json:"rule_version,omitempty"` - Enabled bool `protobuf:"varint,4,opt,name=enabled,proto3" json:"enabled,omitempty"` - TargetRtpPpm int64 `protobuf:"varint,5,opt,name=target_rtp_ppm,json=targetRtpPpm,proto3" json:"target_rtp_ppm,omitempty"` - PoolRatePpm int64 `protobuf:"varint,6,opt,name=pool_rate_ppm,json=poolRatePpm,proto3" json:"pool_rate_ppm,omitempty"` - SettlementWindowWager int64 `protobuf:"varint,7,opt,name=settlement_window_wager,json=settlementWindowWager,proto3" json:"settlement_window_wager,omitempty"` - ControlBandPpm int64 `protobuf:"varint,8,opt,name=control_band_ppm,json=controlBandPpm,proto3" json:"control_band_ppm,omitempty"` - GiftPriceReference int64 `protobuf:"varint,9,opt,name=gift_price_reference,json=giftPriceReference,proto3" json:"gift_price_reference,omitempty"` - NoviceMaxEquivalentDraws int64 `protobuf:"varint,10,opt,name=novice_max_equivalent_draws,json=noviceMaxEquivalentDraws,proto3" json:"novice_max_equivalent_draws,omitempty"` - NormalMaxEquivalentDraws int64 `protobuf:"varint,11,opt,name=normal_max_equivalent_draws,json=normalMaxEquivalentDraws,proto3" json:"normal_max_equivalent_draws,omitempty"` - EffectiveFromMs int64 `protobuf:"varint,12,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` - CreatedByAdminId int64 `protobuf:"varint,13,opt,name=created_by_admin_id,json=createdByAdminId,proto3" json:"created_by_admin_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,14,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - Stages []*LuckyGiftRuleStage `protobuf:"bytes,15,rep,name=stages,proto3" json:"stages,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + RuleVersion int64 `protobuf:"varint,3,opt,name=rule_version,json=ruleVersion,proto3" json:"rule_version,omitempty"` + Enabled bool `protobuf:"varint,4,opt,name=enabled,proto3" json:"enabled,omitempty"` + TargetRtpPpm int64 `protobuf:"varint,5,opt,name=target_rtp_ppm,json=targetRtpPpm,proto3" json:"target_rtp_ppm,omitempty"` + PoolRatePpm int64 `protobuf:"varint,6,opt,name=pool_rate_ppm,json=poolRatePpm,proto3" json:"pool_rate_ppm,omitempty"` + SettlementWindowWager int64 `protobuf:"varint,7,opt,name=settlement_window_wager,json=settlementWindowWager,proto3" json:"settlement_window_wager,omitempty"` + ControlBandPpm int64 `protobuf:"varint,8,opt,name=control_band_ppm,json=controlBandPpm,proto3" json:"control_band_ppm,omitempty"` + GiftPriceReference int64 `protobuf:"varint,9,opt,name=gift_price_reference,json=giftPriceReference,proto3" json:"gift_price_reference,omitempty"` + NoviceMaxEquivalentDraws int64 `protobuf:"varint,10,opt,name=novice_max_equivalent_draws,json=noviceMaxEquivalentDraws,proto3" json:"novice_max_equivalent_draws,omitempty"` + NormalMaxEquivalentDraws int64 `protobuf:"varint,11,opt,name=normal_max_equivalent_draws,json=normalMaxEquivalentDraws,proto3" json:"normal_max_equivalent_draws,omitempty"` + EffectiveFromMs int64 `protobuf:"varint,12,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` + CreatedByAdminId int64 `protobuf:"varint,13,opt,name=created_by_admin_id,json=createdByAdminId,proto3" json:"created_by_admin_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,14,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + Stages []*LuckyGiftRuleStage `protobuf:"bytes,15,rep,name=stages,proto3" json:"stages,omitempty"` // strategy_version 隔离历史 fixed_v2 与动态算法 dynamic_v3,避免新增约束破坏已经发布的旧规则。 StrategyVersion string `protobuf:"bytes,16,opt,name=strategy_version,json=strategyVersion,proto3" json:"strategy_version,omitempty"` ProfitRatePpm int64 `protobuf:"varint,17,opt,name=profit_rate_ppm,json=profitRatePpm,proto3" json:"profit_rate_ppm,omitempty"` @@ -531,6 +525,8 @@ type LuckyGiftRuleConfig struct { User_24HRtpThresholdPpm int64 `protobuf:"varint,39,opt,name=user_24h_rtp_threshold_ppm,json=user24hRtpThresholdPpm,proto3" json:"user_24h_rtp_threshold_ppm,omitempty"` // 触发用户 24 小时 RTP 降权后保留的普通中奖权重;1000000 表示保持原概率。 User_24HOrdinaryWinFactorPpm int64 `protobuf:"varint,40,opt,name=user_24h_ordinary_win_factor_ppm,json=user24hOrdinaryWinFactorPpm,proto3" json:"user_24h_ordinary_win_factor_ppm,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *LuckyGiftRuleConfig) Reset() { @@ -844,15 +840,14 @@ func (x *LuckyGiftRuleConfig) GetUser_24HOrdinaryWinFactorPpm() int64 { } type CheckLuckyGiftRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + GiftId string `protobuf:"bytes,4,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + PoolId string `protobuf:"bytes,5,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` 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"` - RoomId string `protobuf:"bytes,3,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - GiftId string `protobuf:"bytes,4,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - PoolId string `protobuf:"bytes,5,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CheckLuckyGiftRequest) Reset() { @@ -921,20 +916,19 @@ func (x *CheckLuckyGiftRequest) GetPoolId() string { } type CheckLuckyGiftResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` - Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` - GiftId string `protobuf:"bytes,3,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - GiftPrice int64 `protobuf:"varint,4,opt,name=gift_price,json=giftPrice,proto3" json:"gift_price,omitempty"` - RuleVersion int64 `protobuf:"varint,5,opt,name=rule_version,json=ruleVersion,proto3" json:"rule_version,omitempty"` - TargetRtpPpm int64 `protobuf:"varint,6,opt,name=target_rtp_ppm,json=targetRtpPpm,proto3" json:"target_rtp_ppm,omitempty"` - ExperiencePool string `protobuf:"bytes,7,opt,name=experience_pool,json=experiencePool,proto3" json:"experience_pool,omitempty"` - PoolId string `protobuf:"bytes,8,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + GiftId string `protobuf:"bytes,3,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + GiftPrice int64 `protobuf:"varint,4,opt,name=gift_price,json=giftPrice,proto3" json:"gift_price,omitempty"` + RuleVersion int64 `protobuf:"varint,5,opt,name=rule_version,json=ruleVersion,proto3" json:"rule_version,omitempty"` + TargetRtpPpm int64 `protobuf:"varint,6,opt,name=target_rtp_ppm,json=targetRtpPpm,proto3" json:"target_rtp_ppm,omitempty"` + ExperiencePool string `protobuf:"bytes,7,opt,name=experience_pool,json=experiencePool,proto3" json:"experience_pool,omitempty"` + PoolId string `protobuf:"bytes,8,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` // strategy_version 由 lucky-gift owner 返回并由 room saga 固化,用于滚动发布时区分 fixed_v2 兼容与 dynamic_v3 强校验。 StrategyVersion string `protobuf:"bytes,9,opt,name=strategy_version,json=strategyVersion,proto3" json:"strategy_version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CheckLuckyGiftResponse) Reset() { @@ -1031,34 +1025,33 @@ func (x *CheckLuckyGiftResponse) GetStrategyVersion() string { } type LuckyGiftDrawResult struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - DrawId string `protobuf:"bytes,1,opt,name=draw_id,json=drawId,proto3" json:"draw_id,omitempty"` - CommandId string `protobuf:"bytes,2,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - GiftId string `protobuf:"bytes,3,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - RuleVersion int64 `protobuf:"varint,4,opt,name=rule_version,json=ruleVersion,proto3" json:"rule_version,omitempty"` - ExperiencePool string `protobuf:"bytes,5,opt,name=experience_pool,json=experiencePool,proto3" json:"experience_pool,omitempty"` - SelectedTierId string `protobuf:"bytes,6,opt,name=selected_tier_id,json=selectedTierId,proto3" json:"selected_tier_id,omitempty"` - BaseRewardCoins int64 `protobuf:"varint,7,opt,name=base_reward_coins,json=baseRewardCoins,proto3" json:"base_reward_coins,omitempty"` - EffectiveRewardCoins int64 `protobuf:"varint,8,opt,name=effective_reward_coins,json=effectiveRewardCoins,proto3" json:"effective_reward_coins,omitempty"` - RewardStatus string `protobuf:"bytes,9,opt,name=reward_status,json=rewardStatus,proto3" json:"reward_status,omitempty"` - RtpWindowIndex int64 `protobuf:"varint,10,opt,name=rtp_window_index,json=rtpWindowIndex,proto3" json:"rtp_window_index,omitempty"` - GiftRtpWindowIndex int64 `protobuf:"varint,11,opt,name=gift_rtp_window_index,json=giftRtpWindowIndex,proto3" json:"gift_rtp_window_index,omitempty"` - GlobalBaseRtpPpm int64 `protobuf:"varint,12,opt,name=global_base_rtp_ppm,json=globalBaseRtpPpm,proto3" json:"global_base_rtp_ppm,omitempty"` - GiftBaseRtpPpm int64 `protobuf:"varint,13,opt,name=gift_base_rtp_ppm,json=giftBaseRtpPpm,proto3" json:"gift_base_rtp_ppm,omitempty"` - StageFeedback bool `protobuf:"varint,14,opt,name=stage_feedback,json=stageFeedback,proto3" json:"stage_feedback,omitempty"` - HighMultiplier bool `protobuf:"varint,15,opt,name=high_multiplier,json=highMultiplier,proto3" json:"high_multiplier,omitempty"` - CreatedAtMs int64 `protobuf:"varint,16,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - PoolId string `protobuf:"bytes,17,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - MultiplierPpm int64 `protobuf:"varint,18,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` - WalletTransactionId string `protobuf:"bytes,19,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` - CoinBalanceAfter int64 `protobuf:"varint,20,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` - UserId int64 `protobuf:"varint,21,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - ExternalUserId string `protobuf:"bytes,22,opt,name=external_user_id,json=externalUserId,proto3" json:"external_user_id,omitempty"` - AppCode string `protobuf:"bytes,23,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - Hits []*LuckyGiftHit `protobuf:"bytes,24,rep,name=hits,proto3" json:"hits,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + DrawId string `protobuf:"bytes,1,opt,name=draw_id,json=drawId,proto3" json:"draw_id,omitempty"` + CommandId string `protobuf:"bytes,2,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + GiftId string `protobuf:"bytes,3,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + RuleVersion int64 `protobuf:"varint,4,opt,name=rule_version,json=ruleVersion,proto3" json:"rule_version,omitempty"` + ExperiencePool string `protobuf:"bytes,5,opt,name=experience_pool,json=experiencePool,proto3" json:"experience_pool,omitempty"` + SelectedTierId string `protobuf:"bytes,6,opt,name=selected_tier_id,json=selectedTierId,proto3" json:"selected_tier_id,omitempty"` + BaseRewardCoins int64 `protobuf:"varint,7,opt,name=base_reward_coins,json=baseRewardCoins,proto3" json:"base_reward_coins,omitempty"` + EffectiveRewardCoins int64 `protobuf:"varint,8,opt,name=effective_reward_coins,json=effectiveRewardCoins,proto3" json:"effective_reward_coins,omitempty"` + RewardStatus string `protobuf:"bytes,9,opt,name=reward_status,json=rewardStatus,proto3" json:"reward_status,omitempty"` + RtpWindowIndex int64 `protobuf:"varint,10,opt,name=rtp_window_index,json=rtpWindowIndex,proto3" json:"rtp_window_index,omitempty"` + GiftRtpWindowIndex int64 `protobuf:"varint,11,opt,name=gift_rtp_window_index,json=giftRtpWindowIndex,proto3" json:"gift_rtp_window_index,omitempty"` + GlobalBaseRtpPpm int64 `protobuf:"varint,12,opt,name=global_base_rtp_ppm,json=globalBaseRtpPpm,proto3" json:"global_base_rtp_ppm,omitempty"` + GiftBaseRtpPpm int64 `protobuf:"varint,13,opt,name=gift_base_rtp_ppm,json=giftBaseRtpPpm,proto3" json:"gift_base_rtp_ppm,omitempty"` + StageFeedback bool `protobuf:"varint,14,opt,name=stage_feedback,json=stageFeedback,proto3" json:"stage_feedback,omitempty"` + HighMultiplier bool `protobuf:"varint,15,opt,name=high_multiplier,json=highMultiplier,proto3" json:"high_multiplier,omitempty"` + CreatedAtMs int64 `protobuf:"varint,16,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + PoolId string `protobuf:"bytes,17,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + MultiplierPpm int64 `protobuf:"varint,18,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` + WalletTransactionId string `protobuf:"bytes,19,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` + CoinBalanceAfter int64 `protobuf:"varint,20,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + UserId int64 `protobuf:"varint,21,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + ExternalUserId string `protobuf:"bytes,22,opt,name=external_user_id,json=externalUserId,proto3" json:"external_user_id,omitempty"` + AppCode string `protobuf:"bytes,23,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + Hits []*LuckyGiftHit `protobuf:"bytes,24,rep,name=hits,proto3" json:"hits,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *LuckyGiftDrawResult) Reset() { @@ -1260,11 +1253,10 @@ func (x *LuckyGiftDrawResult) GetHits() []*LuckyGiftHit { } type ExecuteLuckyGiftDrawRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + LuckyGift *LuckyGiftMeta `protobuf:"bytes,1,opt,name=lucky_gift,json=luckyGift,proto3" json:"lucky_gift,omitempty"` unknownFields protoimpl.UnknownFields - - LuckyGift *LuckyGiftMeta `protobuf:"bytes,1,opt,name=lucky_gift,json=luckyGift,proto3" json:"lucky_gift,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ExecuteLuckyGiftDrawRequest) Reset() { @@ -1305,11 +1297,10 @@ func (x *ExecuteLuckyGiftDrawRequest) GetLuckyGift() *LuckyGiftMeta { } type ExecuteLuckyGiftDrawResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Result *LuckyGiftDrawResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` unknownFields protoimpl.UnknownFields - - Result *LuckyGiftDrawResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ExecuteLuckyGiftDrawResponse) Reset() { @@ -1350,11 +1341,10 @@ func (x *ExecuteLuckyGiftDrawResponse) GetResult() *LuckyGiftDrawResult { } type BatchExecuteLuckyGiftDrawRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + LuckyGifts []*LuckyGiftMeta `protobuf:"bytes,1,rep,name=lucky_gifts,json=luckyGifts,proto3" json:"lucky_gifts,omitempty"` unknownFields protoimpl.UnknownFields - - LuckyGifts []*LuckyGiftMeta `protobuf:"bytes,1,rep,name=lucky_gifts,json=luckyGifts,proto3" json:"lucky_gifts,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BatchExecuteLuckyGiftDrawRequest) Reset() { @@ -1395,11 +1385,10 @@ func (x *BatchExecuteLuckyGiftDrawRequest) GetLuckyGifts() []*LuckyGiftMeta { } type BatchExecuteLuckyGiftDrawResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Results []*LuckyGiftDrawResult `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"` unknownFields protoimpl.UnknownFields - - Results []*LuckyGiftDrawResult `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BatchExecuteLuckyGiftDrawResponse) Reset() { @@ -1442,25 +1431,24 @@ func (x *BatchExecuteLuckyGiftDrawResponse) GetResults() []*LuckyGiftDrawResult // ExternalGiftDrawRequest 是外部 App 接入的抽奖输入。 // App 调用前必须已经完成自己的扣费,lucky-gift-service 只校验金额事实并返回中奖结果。 type ExternalGiftDrawRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - AppCode string `protobuf:"bytes,3,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ExternalUserId string `protobuf:"bytes,4,opt,name=external_user_id,json=externalUserId,proto3" json:"external_user_id,omitempty"` - RequestId string `protobuf:"bytes,5,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - GiftCount int64 `protobuf:"varint,6,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` - UnitAmount int64 `protobuf:"varint,7,opt,name=unit_amount,json=unitAmount,proto3" json:"unit_amount,omitempty"` - TotalAmount int64 `protobuf:"varint,8,opt,name=total_amount,json=totalAmount,proto3" json:"total_amount,omitempty"` - Currency string `protobuf:"bytes,9,opt,name=currency,proto3" json:"currency,omitempty"` - PaidAtMs int64 `protobuf:"varint,10,opt,name=paid_at_ms,json=paidAtMs,proto3" json:"paid_at_ms,omitempty"` - MetadataJson string `protobuf:"bytes,11,opt,name=metadata_json,json=metadataJson,proto3" json:"metadata_json,omitempty"` - PoolId string `protobuf:"bytes,12,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + AppCode string `protobuf:"bytes,3,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ExternalUserId string `protobuf:"bytes,4,opt,name=external_user_id,json=externalUserId,proto3" json:"external_user_id,omitempty"` + RequestId string `protobuf:"bytes,5,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + GiftCount int64 `protobuf:"varint,6,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` + UnitAmount int64 `protobuf:"varint,7,opt,name=unit_amount,json=unitAmount,proto3" json:"unit_amount,omitempty"` + TotalAmount int64 `protobuf:"varint,8,opt,name=total_amount,json=totalAmount,proto3" json:"total_amount,omitempty"` + Currency string `protobuf:"bytes,9,opt,name=currency,proto3" json:"currency,omitempty"` + PaidAtMs int64 `protobuf:"varint,10,opt,name=paid_at_ms,json=paidAtMs,proto3" json:"paid_at_ms,omitempty"` + MetadataJson string `protobuf:"bytes,11,opt,name=metadata_json,json=metadataJson,proto3" json:"metadata_json,omitempty"` + PoolId string `protobuf:"bytes,12,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` // dynamic_v3 必填的稳定设备作用域。luck-gateway 不独立证明其真实性,调用方必须在自己的认证/签名边界内绑定该值;fixed_v2 允许缺失。 DeviceId string `protobuf:"bytes,13,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` // user_registered_at_ms 由外部 App 按自己的用户主数据提供;dynamic_v3 缺失或晚于支付时间时补偿大奖资格 fail-close。 UserRegisteredAtMs int64 `protobuf:"varint,14,opt,name=user_registered_at_ms,json=userRegisteredAtMs,proto3" json:"user_registered_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ExternalGiftDrawRequest) Reset() { @@ -1585,22 +1573,21 @@ func (x *ExternalGiftDrawRequest) GetUserRegisteredAtMs() int64 { } type ExternalGiftDrawResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - DrawId string `protobuf:"bytes,1,opt,name=draw_id,json=drawId,proto3" json:"draw_id,omitempty"` - RequestId string `protobuf:"bytes,2,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,4,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ExternalUserId string `protobuf:"bytes,5,opt,name=external_user_id,json=externalUserId,proto3" json:"external_user_id,omitempty"` - GiftCount int64 `protobuf:"varint,6,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` - UnitAmount int64 `protobuf:"varint,7,opt,name=unit_amount,json=unitAmount,proto3" json:"unit_amount,omitempty"` - TotalAmount int64 `protobuf:"varint,8,opt,name=total_amount,json=totalAmount,proto3" json:"total_amount,omitempty"` - RewardAmount int64 `protobuf:"varint,9,opt,name=reward_amount,json=rewardAmount,proto3" json:"reward_amount,omitempty"` - MultiplierPpm int64 `protobuf:"varint,10,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` - RewardStatus string `protobuf:"bytes,11,opt,name=reward_status,json=rewardStatus,proto3" json:"reward_status,omitempty"` - RuleVersion int64 `protobuf:"varint,12,opt,name=rule_version,json=ruleVersion,proto3" json:"rule_version,omitempty"` - CreatedAtMs int64 `protobuf:"varint,13,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + DrawId string `protobuf:"bytes,1,opt,name=draw_id,json=drawId,proto3" json:"draw_id,omitempty"` + RequestId string `protobuf:"bytes,2,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,4,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ExternalUserId string `protobuf:"bytes,5,opt,name=external_user_id,json=externalUserId,proto3" json:"external_user_id,omitempty"` + GiftCount int64 `protobuf:"varint,6,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` + UnitAmount int64 `protobuf:"varint,7,opt,name=unit_amount,json=unitAmount,proto3" json:"unit_amount,omitempty"` + TotalAmount int64 `protobuf:"varint,8,opt,name=total_amount,json=totalAmount,proto3" json:"total_amount,omitempty"` + RewardAmount int64 `protobuf:"varint,9,opt,name=reward_amount,json=rewardAmount,proto3" json:"reward_amount,omitempty"` + MultiplierPpm int64 `protobuf:"varint,10,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` + RewardStatus string `protobuf:"bytes,11,opt,name=reward_status,json=rewardStatus,proto3" json:"reward_status,omitempty"` + RuleVersion int64 `protobuf:"varint,12,opt,name=rule_version,json=ruleVersion,proto3" json:"rule_version,omitempty"` + CreatedAtMs int64 `protobuf:"varint,13,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ExternalGiftDrawResponse) Reset() { @@ -1718,12 +1705,11 @@ func (x *ExternalGiftDrawResponse) GetCreatedAtMs() int64 { } type GetLuckyGiftConfigRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetLuckyGiftConfigRequest) Reset() { @@ -1771,11 +1757,10 @@ func (x *GetLuckyGiftConfigRequest) GetPoolId() string { } type GetLuckyGiftConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Config *LuckyGiftRuleConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` unknownFields protoimpl.UnknownFields - - Config *LuckyGiftRuleConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetLuckyGiftConfigResponse) Reset() { @@ -1816,13 +1801,12 @@ func (x *GetLuckyGiftConfigResponse) GetConfig() *LuckyGiftRuleConfig { } type UpsertLuckyGiftConfigRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Config *LuckyGiftRuleConfig `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` - OperatorAdminId int64 `protobuf:"varint,3,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Config *LuckyGiftRuleConfig `protobuf:"bytes,2,opt,name=config,proto3" json:"config,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 *UpsertLuckyGiftConfigRequest) Reset() { @@ -1877,11 +1861,10 @@ func (x *UpsertLuckyGiftConfigRequest) GetOperatorAdminId() int64 { } type UpsertLuckyGiftConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Config *LuckyGiftRuleConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` unknownFields protoimpl.UnknownFields - - Config *LuckyGiftRuleConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UpsertLuckyGiftConfigResponse) Reset() { @@ -1922,11 +1905,10 @@ func (x *UpsertLuckyGiftConfigResponse) GetConfig() *LuckyGiftRuleConfig { } type ListLuckyGiftConfigsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListLuckyGiftConfigsRequest) Reset() { @@ -1967,11 +1949,10 @@ func (x *ListLuckyGiftConfigsRequest) GetMeta() *RequestMeta { } type ListLuckyGiftConfigsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Configs []*LuckyGiftRuleConfig `protobuf:"bytes,1,rep,name=configs,proto3" json:"configs,omitempty"` unknownFields protoimpl.UnknownFields - - Configs []*LuckyGiftRuleConfig `protobuf:"bytes,1,rep,name=configs,proto3" json:"configs,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListLuckyGiftConfigsResponse) Reset() { @@ -2012,20 +1993,19 @@ func (x *ListLuckyGiftConfigsResponse) GetConfigs() []*LuckyGiftRuleConfig { } type ListLuckyGiftDrawsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - GiftId string `protobuf:"bytes,2,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - RoomId string `protobuf:"bytes,4,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,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"` - PoolId string `protobuf:"bytes,8,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - ExternalUserId string `protobuf:"bytes,10,opt,name=external_user_id,json=externalUserId,proto3" json:"external_user_id,omitempty"` - ExternalOnly bool `protobuf:"varint,11,opt,name=external_only,json=externalOnly,proto3" json:"external_only,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + GiftId string `protobuf:"bytes,2,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + RoomId string `protobuf:"bytes,4,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,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"` + PoolId string `protobuf:"bytes,8,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + ExternalUserId string `protobuf:"bytes,10,opt,name=external_user_id,json=externalUserId,proto3" json:"external_user_id,omitempty"` + ExternalOnly bool `protobuf:"varint,11,opt,name=external_only,json=externalOnly,proto3" json:"external_only,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListLuckyGiftDrawsRequest) Reset() { @@ -2129,12 +2109,11 @@ func (x *ListLuckyGiftDrawsRequest) GetExternalOnly() bool { } type ListLuckyGiftDrawsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Draws []*LuckyGiftDrawResult `protobuf:"bytes,1,rep,name=draws,proto3" json:"draws,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` unknownFields protoimpl.UnknownFields - - Draws []*LuckyGiftDrawResult `protobuf:"bytes,1,rep,name=draws,proto3" json:"draws,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListLuckyGiftDrawsResponse) Reset() { @@ -2182,21 +2161,20 @@ func (x *ListLuckyGiftDrawsResponse) GetTotal() int64 { } type LuckyGiftDrawSummary struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PoolId string `protobuf:"bytes,1,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - TotalDraws int64 `protobuf:"varint,2,opt,name=total_draws,json=totalDraws,proto3" json:"total_draws,omitempty"` - UniqueUsers int64 `protobuf:"varint,3,opt,name=unique_users,json=uniqueUsers,proto3" json:"unique_users,omitempty"` - UniqueRooms int64 `protobuf:"varint,4,opt,name=unique_rooms,json=uniqueRooms,proto3" json:"unique_rooms,omitempty"` - TotalSpentCoins int64 `protobuf:"varint,5,opt,name=total_spent_coins,json=totalSpentCoins,proto3" json:"total_spent_coins,omitempty"` - TotalRewardCoins int64 `protobuf:"varint,6,opt,name=total_reward_coins,json=totalRewardCoins,proto3" json:"total_reward_coins,omitempty"` - BaseRewardCoins int64 `protobuf:"varint,7,opt,name=base_reward_coins,json=baseRewardCoins,proto3" json:"base_reward_coins,omitempty"` - ActualRtpPpm int64 `protobuf:"varint,8,opt,name=actual_rtp_ppm,json=actualRtpPpm,proto3" json:"actual_rtp_ppm,omitempty"` - PendingDraws int64 `protobuf:"varint,9,opt,name=pending_draws,json=pendingDraws,proto3" json:"pending_draws,omitempty"` - GrantedDraws int64 `protobuf:"varint,10,opt,name=granted_draws,json=grantedDraws,proto3" json:"granted_draws,omitempty"` - FailedDraws int64 `protobuf:"varint,11,opt,name=failed_draws,json=failedDraws,proto3" json:"failed_draws,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + PoolId string `protobuf:"bytes,1,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + TotalDraws int64 `protobuf:"varint,2,opt,name=total_draws,json=totalDraws,proto3" json:"total_draws,omitempty"` + UniqueUsers int64 `protobuf:"varint,3,opt,name=unique_users,json=uniqueUsers,proto3" json:"unique_users,omitempty"` + UniqueRooms int64 `protobuf:"varint,4,opt,name=unique_rooms,json=uniqueRooms,proto3" json:"unique_rooms,omitempty"` + TotalSpentCoins int64 `protobuf:"varint,5,opt,name=total_spent_coins,json=totalSpentCoins,proto3" json:"total_spent_coins,omitempty"` + TotalRewardCoins int64 `protobuf:"varint,6,opt,name=total_reward_coins,json=totalRewardCoins,proto3" json:"total_reward_coins,omitempty"` + BaseRewardCoins int64 `protobuf:"varint,7,opt,name=base_reward_coins,json=baseRewardCoins,proto3" json:"base_reward_coins,omitempty"` + ActualRtpPpm int64 `protobuf:"varint,8,opt,name=actual_rtp_ppm,json=actualRtpPpm,proto3" json:"actual_rtp_ppm,omitempty"` + PendingDraws int64 `protobuf:"varint,9,opt,name=pending_draws,json=pendingDraws,proto3" json:"pending_draws,omitempty"` + GrantedDraws int64 `protobuf:"varint,10,opt,name=granted_draws,json=grantedDraws,proto3" json:"granted_draws,omitempty"` + FailedDraws int64 `protobuf:"varint,11,opt,name=failed_draws,json=failedDraws,proto3" json:"failed_draws,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *LuckyGiftDrawSummary) Reset() { @@ -2307,22 +2285,21 @@ func (x *LuckyGiftDrawSummary) GetFailedDraws() int64 { } type LuckyGiftPoolBalance struct { - 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"` - PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - Balance int64 `protobuf:"varint,3,opt,name=balance,proto3" json:"balance,omitempty"` - ReserveFloor int64 `protobuf:"varint,4,opt,name=reserve_floor,json=reserveFloor,proto3" json:"reserve_floor,omitempty"` - AvailableBalance int64 `protobuf:"varint,5,opt,name=available_balance,json=availableBalance,proto3" json:"available_balance,omitempty"` - TotalIn int64 `protobuf:"varint,6,opt,name=total_in,json=totalIn,proto3" json:"total_in,omitempty"` - TotalOut int64 `protobuf:"varint,7,opt,name=total_out,json=totalOut,proto3" json:"total_out,omitempty"` - Materialized bool `protobuf:"varint,8,opt,name=materialized,proto3" json:"materialized,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,9,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - StrategyVersion string `protobuf:"bytes,10,opt,name=strategy_version,json=strategyVersion,proto3" json:"strategy_version,omitempty"` - ManualCreditTotal int64 `protobuf:"varint,11,opt,name=manual_credit_total,json=manualCreditTotal,proto3" json:"manual_credit_total,omitempty"` - ManualDebitTotal int64 `protobuf:"varint,12,opt,name=manual_debit_total,json=manualDebitTotal,proto3" json:"manual_debit_total,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + Balance int64 `protobuf:"varint,3,opt,name=balance,proto3" json:"balance,omitempty"` + ReserveFloor int64 `protobuf:"varint,4,opt,name=reserve_floor,json=reserveFloor,proto3" json:"reserve_floor,omitempty"` + AvailableBalance int64 `protobuf:"varint,5,opt,name=available_balance,json=availableBalance,proto3" json:"available_balance,omitempty"` + TotalIn int64 `protobuf:"varint,6,opt,name=total_in,json=totalIn,proto3" json:"total_in,omitempty"` + TotalOut int64 `protobuf:"varint,7,opt,name=total_out,json=totalOut,proto3" json:"total_out,omitempty"` + Materialized bool `protobuf:"varint,8,opt,name=materialized,proto3" json:"materialized,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,9,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + StrategyVersion string `protobuf:"bytes,10,opt,name=strategy_version,json=strategyVersion,proto3" json:"strategy_version,omitempty"` + ManualCreditTotal int64 `protobuf:"varint,11,opt,name=manual_credit_total,json=manualCreditTotal,proto3" json:"manual_credit_total,omitempty"` + ManualDebitTotal int64 `protobuf:"varint,12,opt,name=manual_debit_total,json=manualDebitTotal,proto3" json:"manual_debit_total,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *LuckyGiftPoolBalance) Reset() { @@ -2440,18 +2417,17 @@ func (x *LuckyGiftPoolBalance) GetManualDebitTotal() int64 { } type GetLuckyGiftDrawSummaryRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - GiftId string `protobuf:"bytes,2,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - RoomId string `protobuf:"bytes,4,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - PoolId string `protobuf:"bytes,6,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - ExternalUserId string `protobuf:"bytes,8,opt,name=external_user_id,json=externalUserId,proto3" json:"external_user_id,omitempty"` - ExternalOnly bool `protobuf:"varint,9,opt,name=external_only,json=externalOnly,proto3" json:"external_only,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + GiftId string `protobuf:"bytes,2,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + RoomId string `protobuf:"bytes,4,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + PoolId string `protobuf:"bytes,6,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + ExternalUserId string `protobuf:"bytes,8,opt,name=external_user_id,json=externalUserId,proto3" json:"external_user_id,omitempty"` + ExternalOnly bool `protobuf:"varint,9,opt,name=external_only,json=externalOnly,proto3" json:"external_only,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GetLuckyGiftDrawSummaryRequest) Reset() { @@ -2541,11 +2517,10 @@ func (x *GetLuckyGiftDrawSummaryRequest) GetExternalOnly() bool { } type GetLuckyGiftDrawSummaryResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Summary *LuckyGiftDrawSummary `protobuf:"bytes,1,opt,name=summary,proto3" json:"summary,omitempty"` unknownFields protoimpl.UnknownFields - - Summary *LuckyGiftDrawSummary `protobuf:"bytes,1,opt,name=summary,proto3" json:"summary,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetLuckyGiftDrawSummaryResponse) Reset() { @@ -2586,13 +2561,12 @@ func (x *GetLuckyGiftDrawSummaryResponse) GetSummary() *LuckyGiftDrawSummary { } type ListLuckyGiftPoolBalancesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - StrategyVersion string `protobuf:"bytes,3,opt,name=strategy_version,json=strategyVersion,proto3" json:"strategy_version,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + StrategyVersion string `protobuf:"bytes,3,opt,name=strategy_version,json=strategyVersion,proto3" json:"strategy_version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListLuckyGiftPoolBalancesRequest) Reset() { @@ -2647,11 +2621,10 @@ func (x *ListLuckyGiftPoolBalancesRequest) GetStrategyVersion() string { } type ListLuckyGiftPoolBalancesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Pools []*LuckyGiftPoolBalance `protobuf:"bytes,1,rep,name=pools,proto3" json:"pools,omitempty"` unknownFields protoimpl.UnknownFields - - Pools []*LuckyGiftPoolBalance `protobuf:"bytes,1,rep,name=pools,proto3" json:"pools,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListLuckyGiftPoolBalancesResponse) Reset() { @@ -2694,15 +2667,14 @@ func (x *ListLuckyGiftPoolBalancesResponse) GetPools() []*LuckyGiftPoolBalance { // LuckyGiftHit 只返回批量逐份开奖中实际中奖的精简位置,不复制全部审计明细。 // 声明追加在文件尾以保持既有 protobuf message index 稳定。 type LuckyGiftHit struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - GiftIndex int32 `protobuf:"varint,1,opt,name=gift_index,json=giftIndex,proto3" json:"gift_index,omitempty"` - DrawId string `protobuf:"bytes,2,opt,name=draw_id,json=drawId,proto3" json:"draw_id,omitempty"` - SelectedTierId string `protobuf:"bytes,3,opt,name=selected_tier_id,json=selectedTierId,proto3" json:"selected_tier_id,omitempty"` - MultiplierPpm int64 `protobuf:"varint,4,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` - RewardCoins int64 `protobuf:"varint,5,opt,name=reward_coins,json=rewardCoins,proto3" json:"reward_coins,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + GiftIndex int32 `protobuf:"varint,1,opt,name=gift_index,json=giftIndex,proto3" json:"gift_index,omitempty"` + DrawId string `protobuf:"bytes,2,opt,name=draw_id,json=drawId,proto3" json:"draw_id,omitempty"` + SelectedTierId string `protobuf:"bytes,3,opt,name=selected_tier_id,json=selectedTierId,proto3" json:"selected_tier_id,omitempty"` + MultiplierPpm int64 `protobuf:"varint,4,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` + RewardCoins int64 `protobuf:"varint,5,opt,name=reward_coins,json=rewardCoins,proto3" json:"reward_coins,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *LuckyGiftHit) Reset() { @@ -2773,18 +2745,17 @@ func (x *LuckyGiftHit) GetRewardCoins() int64 { // 调账消息也只追加在文件尾,保持所有既有 protobuf message index 稳定。 // adjustment_id 是业务幂等键;RequestMeta.request_id 只做链路追踪,不能替代资金幂等语义。 type AdjustLuckyGiftPoolBalanceRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - StrategyVersion string `protobuf:"bytes,3,opt,name=strategy_version,json=strategyVersion,proto3" json:"strategy_version,omitempty"` - AdjustmentId string `protobuf:"bytes,4,opt,name=adjustment_id,json=adjustmentId,proto3" json:"adjustment_id,omitempty"` - Direction string `protobuf:"bytes,5,opt,name=direction,proto3" json:"direction,omitempty"` - AmountCoins int64 `protobuf:"varint,6,opt,name=amount_coins,json=amountCoins,proto3" json:"amount_coins,omitempty"` - Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` - OperatorAdminId int64 `protobuf:"varint,8,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + StrategyVersion string `protobuf:"bytes,3,opt,name=strategy_version,json=strategyVersion,proto3" json:"strategy_version,omitempty"` + AdjustmentId string `protobuf:"bytes,4,opt,name=adjustment_id,json=adjustmentId,proto3" json:"adjustment_id,omitempty"` + Direction string `protobuf:"bytes,5,opt,name=direction,proto3" json:"direction,omitempty"` + AmountCoins int64 `protobuf:"varint,6,opt,name=amount_coins,json=amountCoins,proto3" json:"amount_coins,omitempty"` + Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` + OperatorAdminId int64 `protobuf:"varint,8,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdjustLuckyGiftPoolBalanceRequest) Reset() { @@ -2874,21 +2845,20 @@ func (x *AdjustLuckyGiftPoolBalanceRequest) GetOperatorAdminId() int64 { } type LuckyGiftPoolAdjustment struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AdjustmentId string `protobuf:"bytes,1,opt,name=adjustment_id,json=adjustmentId,proto3" json:"adjustment_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - PoolId string `protobuf:"bytes,3,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - StrategyVersion string `protobuf:"bytes,4,opt,name=strategy_version,json=strategyVersion,proto3" json:"strategy_version,omitempty"` - Direction string `protobuf:"bytes,5,opt,name=direction,proto3" json:"direction,omitempty"` - AmountCoins int64 `protobuf:"varint,6,opt,name=amount_coins,json=amountCoins,proto3" json:"amount_coins,omitempty"` - Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` - OperatorAdminId int64 `protobuf:"varint,8,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` - BalanceBefore int64 `protobuf:"varint,9,opt,name=balance_before,json=balanceBefore,proto3" json:"balance_before,omitempty"` - BalanceAfter int64 `protobuf:"varint,10,opt,name=balance_after,json=balanceAfter,proto3" json:"balance_after,omitempty"` - CreatedAtMs int64 `protobuf:"varint,11,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + AdjustmentId string `protobuf:"bytes,1,opt,name=adjustment_id,json=adjustmentId,proto3" json:"adjustment_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + PoolId string `protobuf:"bytes,3,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + StrategyVersion string `protobuf:"bytes,4,opt,name=strategy_version,json=strategyVersion,proto3" json:"strategy_version,omitempty"` + Direction string `protobuf:"bytes,5,opt,name=direction,proto3" json:"direction,omitempty"` + AmountCoins int64 `protobuf:"varint,6,opt,name=amount_coins,json=amountCoins,proto3" json:"amount_coins,omitempty"` + Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` + OperatorAdminId int64 `protobuf:"varint,8,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + BalanceBefore int64 `protobuf:"varint,9,opt,name=balance_before,json=balanceBefore,proto3" json:"balance_before,omitempty"` + BalanceAfter int64 `protobuf:"varint,10,opt,name=balance_after,json=balanceAfter,proto3" json:"balance_after,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 } func (x *LuckyGiftPoolAdjustment) Reset() { @@ -2999,13 +2969,12 @@ func (x *LuckyGiftPoolAdjustment) GetCreatedAtMs() int64 { } type AdjustLuckyGiftPoolBalanceResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` Adjustment *LuckyGiftPoolAdjustment `protobuf:"bytes,1,opt,name=adjustment,proto3" json:"adjustment,omitempty"` Pool *LuckyGiftPoolBalance `protobuf:"bytes,2,opt,name=pool,proto3" json:"pool,omitempty"` IdempotentReplay bool `protobuf:"varint,3,opt,name=idempotent_replay,json=idempotentReplay,proto3" json:"idempotent_replay,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdjustLuckyGiftPoolBalanceResponse) Reset() { @@ -3062,16 +3031,15 @@ func (x *AdjustLuckyGiftPoolBalanceResponse) GetIdempotentReplay() bool { // 用户画像协议追加在文件尾,避免改变既有 message index。外部策略哈希只存在于 owner 数据库, // 本协议永远只下发 external_user_id,防止运营误把不可逆内部键当成外部用户身份。 type LuckyGiftUserProfileWindow struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Draws int64 `protobuf:"varint,1,opt,name=draws,proto3" json:"draws,omitempty"` + WagerCoins int64 `protobuf:"varint,2,opt,name=wager_coins,json=wagerCoins,proto3" json:"wager_coins,omitempty"` + PayoutCoins int64 `protobuf:"varint,3,opt,name=payout_coins,json=payoutCoins,proto3" json:"payout_coins,omitempty"` + NetCoins int64 `protobuf:"varint,4,opt,name=net_coins,json=netCoins,proto3" json:"net_coins,omitempty"` + RtpPpm int64 `protobuf:"varint,5,opt,name=rtp_ppm,json=rtpPpm,proto3" json:"rtp_ppm,omitempty"` + HasRtp bool `protobuf:"varint,6,opt,name=has_rtp,json=hasRtp,proto3" json:"has_rtp,omitempty"` unknownFields protoimpl.UnknownFields - - Draws int64 `protobuf:"varint,1,opt,name=draws,proto3" json:"draws,omitempty"` - WagerCoins int64 `protobuf:"varint,2,opt,name=wager_coins,json=wagerCoins,proto3" json:"wager_coins,omitempty"` - PayoutCoins int64 `protobuf:"varint,3,opt,name=payout_coins,json=payoutCoins,proto3" json:"payout_coins,omitempty"` - NetCoins int64 `protobuf:"varint,4,opt,name=net_coins,json=netCoins,proto3" json:"net_coins,omitempty"` - RtpPpm int64 `protobuf:"varint,5,opt,name=rtp_ppm,json=rtpPpm,proto3" json:"rtp_ppm,omitempty"` - HasRtp bool `protobuf:"varint,6,opt,name=has_rtp,json=hasRtp,proto3" json:"has_rtp,omitempty"` + sizeCache protoimpl.SizeCache } func (x *LuckyGiftUserProfileWindow) Reset() { @@ -3147,10 +3115,7 @@ func (x *LuckyGiftUserProfileWindow) GetHasRtp() bool { } type LuckyGiftUserProfile struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` IdentityType string `protobuf:"bytes,3,opt,name=identity_type,json=identityType,proto3" json:"identity_type,omitempty"` @@ -3187,6 +3152,8 @@ type LuckyGiftUserProfile struct { AggregatedAtMs int64 `protobuf:"varint,34,opt,name=aggregated_at_ms,json=aggregatedAtMs,proto3" json:"aggregated_at_ms,omitempty"` DataLagMs int64 `protobuf:"varint,35,opt,name=data_lag_ms,json=dataLagMs,proto3" json:"data_lag_ms,omitempty"` User_24HRtpThresholdPpm int64 `protobuf:"varint,36,opt,name=user_24h_rtp_threshold_ppm,json=user24hRtpThresholdPpm,proto3" json:"user_24h_rtp_threshold_ppm,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *LuckyGiftUserProfile) Reset() { @@ -3472,23 +3439,22 @@ func (x *LuckyGiftUserProfile) GetUser_24HRtpThresholdPpm() int64 { } type ListLuckyGiftUserProfilesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - IdentityType string `protobuf:"bytes,3,opt,name=identity_type,json=identityType,proto3" json:"identity_type,omitempty"` - InternalUserId int64 `protobuf:"varint,4,opt,name=internal_user_id,json=internalUserId,proto3" json:"internal_user_id,omitempty"` - ExternalUserId string `protobuf:"bytes,5,opt,name=external_user_id,json=externalUserId,proto3" json:"external_user_id,omitempty"` - Stage string `protobuf:"bytes,6,opt,name=stage,proto3" json:"stage,omitempty"` - Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` - SortBy string `protobuf:"bytes,8,opt,name=sort_by,json=sortBy,proto3" json:"sort_by,omitempty"` - SortDirection string `protobuf:"bytes,9,opt,name=sort_direction,json=sortDirection,proto3" json:"sort_direction,omitempty"` - Page int32 `protobuf:"varint,10,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,11,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + IdentityType string `protobuf:"bytes,3,opt,name=identity_type,json=identityType,proto3" json:"identity_type,omitempty"` + InternalUserId int64 `protobuf:"varint,4,opt,name=internal_user_id,json=internalUserId,proto3" json:"internal_user_id,omitempty"` + ExternalUserId string `protobuf:"bytes,5,opt,name=external_user_id,json=externalUserId,proto3" json:"external_user_id,omitempty"` + Stage string `protobuf:"bytes,6,opt,name=stage,proto3" json:"stage,omitempty"` + Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` + SortBy string `protobuf:"bytes,8,opt,name=sort_by,json=sortBy,proto3" json:"sort_by,omitempty"` + SortDirection string `protobuf:"bytes,9,opt,name=sort_direction,json=sortDirection,proto3" json:"sort_direction,omitempty"` + Page int32 `protobuf:"varint,10,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,11,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` // cursor 是 owner service 生成的不透明 keyset 游标;page 仅保留旧客户端协议兼容,服务端不再执行 OFFSET。 - Cursor string `protobuf:"bytes,12,opt,name=cursor,proto3" json:"cursor,omitempty"` + Cursor string `protobuf:"bytes,12,opt,name=cursor,proto3" json:"cursor,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListLuckyGiftUserProfilesRequest) Reset() { @@ -3606,15 +3572,14 @@ func (x *ListLuckyGiftUserProfilesRequest) GetCursor() string { } type ListLuckyGiftUserProfilesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Profiles []*LuckyGiftUserProfile `protobuf:"bytes,1,rep,name=profiles,proto3" json:"profiles,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + SnapshotAtMs int64 `protobuf:"varint,3,opt,name=snapshot_at_ms,json=snapshotAtMs,proto3" json:"snapshot_at_ms,omitempty"` + NextCursor string `protobuf:"bytes,4,opt,name=next_cursor,json=nextCursor,proto3" json:"next_cursor,omitempty"` + HasMore bool `protobuf:"varint,5,opt,name=has_more,json=hasMore,proto3" json:"has_more,omitempty"` unknownFields protoimpl.UnknownFields - - Profiles []*LuckyGiftUserProfile `protobuf:"bytes,1,rep,name=profiles,proto3" json:"profiles,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - SnapshotAtMs int64 `protobuf:"varint,3,opt,name=snapshot_at_ms,json=snapshotAtMs,proto3" json:"snapshot_at_ms,omitempty"` - NextCursor string `protobuf:"bytes,4,opt,name=next_cursor,json=nextCursor,proto3" json:"next_cursor,omitempty"` - HasMore bool `protobuf:"varint,5,opt,name=has_more,json=hasMore,proto3" json:"has_more,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListLuckyGiftUserProfilesResponse) Reset() { @@ -3683,19 +3648,18 @@ func (x *ListLuckyGiftUserProfilesResponse) GetHasMore() bool { } type GetLuckyGiftUserProfileRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - IdentityType string `protobuf:"bytes,3,opt,name=identity_type,json=identityType,proto3" json:"identity_type,omitempty"` - InternalUserId int64 `protobuf:"varint,4,opt,name=internal_user_id,json=internalUserId,proto3" json:"internal_user_id,omitempty"` - ExternalUserId string `protobuf:"bytes,5,opt,name=external_user_id,json=externalUserId,proto3" json:"external_user_id,omitempty"` - JackpotPage int32 `protobuf:"varint,6,opt,name=jackpot_page,json=jackpotPage,proto3" json:"jackpot_page,omitempty"` - JackpotPageSize int32 `protobuf:"varint,7,opt,name=jackpot_page_size,json=jackpotPageSize,proto3" json:"jackpot_page_size,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + IdentityType string `protobuf:"bytes,3,opt,name=identity_type,json=identityType,proto3" json:"identity_type,omitempty"` + InternalUserId int64 `protobuf:"varint,4,opt,name=internal_user_id,json=internalUserId,proto3" json:"internal_user_id,omitempty"` + ExternalUserId string `protobuf:"bytes,5,opt,name=external_user_id,json=externalUserId,proto3" json:"external_user_id,omitempty"` + JackpotPage int32 `protobuf:"varint,6,opt,name=jackpot_page,json=jackpotPage,proto3" json:"jackpot_page,omitempty"` + JackpotPageSize int32 `protobuf:"varint,7,opt,name=jackpot_page_size,json=jackpotPageSize,proto3" json:"jackpot_page_size,omitempty"` // jackpot_cursor 由上一页 next_jackpot_cursor 原样返回;jackpot_page 仅保留协议兼容。 JackpotCursor string `protobuf:"bytes,8,opt,name=jackpot_cursor,json=jackpotCursor,proto3" json:"jackpot_cursor,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GetLuckyGiftUserProfileRequest) Reset() { @@ -3785,15 +3749,14 @@ func (x *GetLuckyGiftUserProfileRequest) GetJackpotCursor() string { } type LuckyGiftUserMultiplierStat struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + HitType string `protobuf:"bytes,1,opt,name=hit_type,json=hitType,proto3" json:"hit_type,omitempty"` + MultiplierPpm int64 `protobuf:"varint,2,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` + DrawCount int64 `protobuf:"varint,3,opt,name=draw_count,json=drawCount,proto3" json:"draw_count,omitempty"` + WagerCoins int64 `protobuf:"varint,4,opt,name=wager_coins,json=wagerCoins,proto3" json:"wager_coins,omitempty"` + PayoutCoins int64 `protobuf:"varint,5,opt,name=payout_coins,json=payoutCoins,proto3" json:"payout_coins,omitempty"` unknownFields protoimpl.UnknownFields - - HitType string `protobuf:"bytes,1,opt,name=hit_type,json=hitType,proto3" json:"hit_type,omitempty"` - MultiplierPpm int64 `protobuf:"varint,2,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` - DrawCount int64 `protobuf:"varint,3,opt,name=draw_count,json=drawCount,proto3" json:"draw_count,omitempty"` - WagerCoins int64 `protobuf:"varint,4,opt,name=wager_coins,json=wagerCoins,proto3" json:"wager_coins,omitempty"` - PayoutCoins int64 `protobuf:"varint,5,opt,name=payout_coins,json=payoutCoins,proto3" json:"payout_coins,omitempty"` + sizeCache protoimpl.SizeCache } func (x *LuckyGiftUserMultiplierStat) Reset() { @@ -3862,18 +3825,17 @@ func (x *LuckyGiftUserMultiplierStat) GetPayoutCoins() int64 { } type LuckyGiftUserJackpotCondition struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Numerator int64 `protobuf:"varint,2,opt,name=numerator,proto3" json:"numerator,omitempty"` + Denominator int64 `protobuf:"varint,3,opt,name=denominator,proto3" json:"denominator,omitempty"` + RatioPpm int64 `protobuf:"varint,4,opt,name=ratio_ppm,json=ratioPpm,proto3" json:"ratio_ppm,omitempty"` + LimitPpm int64 `protobuf:"varint,5,opt,name=limit_ppm,json=limitPpm,proto3" json:"limit_ppm,omitempty"` + FactorPpm int64 `protobuf:"varint,6,opt,name=factor_ppm,json=factorPpm,proto3" json:"factor_ppm,omitempty"` + Passed bool `protobuf:"varint,7,opt,name=passed,proto3" json:"passed,omitempty"` + Reason string `protobuf:"bytes,8,opt,name=reason,proto3" json:"reason,omitempty"` unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Numerator int64 `protobuf:"varint,2,opt,name=numerator,proto3" json:"numerator,omitempty"` - Denominator int64 `protobuf:"varint,3,opt,name=denominator,proto3" json:"denominator,omitempty"` - RatioPpm int64 `protobuf:"varint,4,opt,name=ratio_ppm,json=ratioPpm,proto3" json:"ratio_ppm,omitempty"` - LimitPpm int64 `protobuf:"varint,5,opt,name=limit_ppm,json=limitPpm,proto3" json:"limit_ppm,omitempty"` - FactorPpm int64 `protobuf:"varint,6,opt,name=factor_ppm,json=factorPpm,proto3" json:"factor_ppm,omitempty"` - Passed bool `protobuf:"varint,7,opt,name=passed,proto3" json:"passed,omitempty"` - Reason string `protobuf:"bytes,8,opt,name=reason,proto3" json:"reason,omitempty"` + sizeCache protoimpl.SizeCache } func (x *LuckyGiftUserJackpotCondition) Reset() { @@ -3963,10 +3925,7 @@ func (x *LuckyGiftUserJackpotCondition) GetReason() string { } type LuckyGiftUserJackpotHit struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` DrawId string `protobuf:"bytes,1,opt,name=draw_id,json=drawId,proto3" json:"draw_id,omitempty"` RequestId string `protobuf:"bytes,2,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` RuleVersion int64 `protobuf:"varint,3,opt,name=rule_version,json=ruleVersion,proto3" json:"rule_version,omitempty"` @@ -3981,7 +3940,9 @@ type LuckyGiftUserJackpotHit struct { OccurredAtMs int64 `protobuf:"varint,12,opt,name=occurred_at_ms,json=occurredAtMs,proto3" json:"occurred_at_ms,omitempty"` Conditions []*LuckyGiftUserJackpotCondition `protobuf:"bytes,13,rep,name=conditions,proto3" json:"conditions,omitempty"` // event_key 只标识这条画像大奖事实,供前端稳定追加去重;不包含用户策略键或用户哈希。 - EventKey string `protobuf:"bytes,14,opt,name=event_key,json=eventKey,proto3" json:"event_key,omitempty"` + EventKey string `protobuf:"bytes,14,opt,name=event_key,json=eventKey,proto3" json:"event_key,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *LuckyGiftUserJackpotHit) Reset() { @@ -4113,10 +4074,7 @@ func (x *LuckyGiftUserJackpotHit) GetEventKey() string { } type GetLuckyGiftUserProfileResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` Profile *LuckyGiftUserProfile `protobuf:"bytes,1,opt,name=profile,proto3" json:"profile,omitempty"` MultiplierDistribution []*LuckyGiftUserMultiplierStat `protobuf:"bytes,2,rep,name=multiplier_distribution,json=multiplierDistribution,proto3" json:"multiplier_distribution,omitempty"` JackpotHits []*LuckyGiftUserJackpotHit `protobuf:"bytes,3,rep,name=jackpot_hits,json=jackpotHits,proto3" json:"jackpot_hits,omitempty"` @@ -4126,6 +4084,8 @@ type GetLuckyGiftUserProfileResponse struct { JackpotPageSize int32 `protobuf:"varint,7,opt,name=jackpot_page_size,json=jackpotPageSize,proto3" json:"jackpot_page_size,omitempty"` NextJackpotCursor string `protobuf:"bytes,8,opt,name=next_jackpot_cursor,json=nextJackpotCursor,proto3" json:"next_jackpot_cursor,omitempty"` JackpotHasMore bool `protobuf:"varint,9,opt,name=jackpot_has_more,json=jackpotHasMore,proto3" json:"jackpot_has_more,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GetLuckyGiftUserProfileResponse) Reset() { @@ -4223,1046 +4183,453 @@ func (x *GetLuckyGiftUserProfileResponse) GetJackpotHasMore() bool { var File_proto_luckygift_v1_luckygift_proto protoreflect.FileDescriptor -var file_proto_luckygift_v1_luckygift_proto_rawDesc = []byte{ - 0x0a, 0x22, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, - 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, - 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x22, 0xa5, 0x01, 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, 0x16, 0x0a, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x65, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x12, - 0x26, 0x0a, 0x0f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x0a, 0x73, 0x65, 0x6e, 0x74, 0x5f, - 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 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, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, - 0x22, 0xf5, 0x06, 0x0a, 0x0d, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x4d, 0x65, - 0x74, 0x61, 0x12, 0x33, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, - 0x66, 0x74, 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, 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, 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, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 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, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, - 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, 0x1d, 0x0a, 0x0a, 0x63, - 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x09, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x0a, 0x70, 0x61, - 0x69, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, - 0x70, 0x61, 0x69, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, - 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, - 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x55, 0x73, 0x65, 0x72, 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, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, - 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0d, 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, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x64, - 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x49, - 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x76, 0x61, - 0x74, 0x61, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, - 0x72, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x33, 0x0a, 0x16, 0x73, 0x65, 0x6e, 0x64, 0x65, - 0x72, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x44, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x40, 0x0a, 0x1d, - 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, 0x64, 0x69, - 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x12, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x19, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x72, 0x65, 0x74, 0x74, - 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2a, - 0x0a, 0x11, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x37, 0x64, 0x5f, 0x63, 0x6f, - 0x69, 0x6e, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, 0x65, 0x63, 0x68, 0x61, - 0x72, 0x67, 0x65, 0x37, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x72, 0x65, - 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x33, 0x30, 0x64, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, - 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, - 0x33, 0x30, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x2f, 0x0a, 0x14, 0x6c, 0x61, 0x73, 0x74, - 0x5f, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, - 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x67, 0x69, 0x66, - 0x74, 0x5f, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x16, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x67, 0x69, 0x66, 0x74, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x65, - 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x72, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x17, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x75, 0x73, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x65, 0x72, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xd3, 0x01, 0x0a, 0x11, 0x4c, 0x75, 0x63, - 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x54, 0x69, 0x65, 0x72, 0x12, 0x14, - 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, - 0x74, 0x61, 0x67, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x69, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, - 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x70, 0x70, 0x6d, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, - 0x72, 0x50, 0x70, 0x6d, 0x12, 0x26, 0x0a, 0x0f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x77, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x62, - 0x61, 0x73, 0x65, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x50, 0x70, 0x6d, 0x12, 0x26, 0x0a, 0x0f, - 0x68, 0x69, 0x67, 0x68, 0x5f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x68, 0x69, 0x67, 0x68, 0x57, 0x61, 0x74, 0x65, 0x72, - 0x4f, 0x6e, 0x6c, 0x79, 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, 0xcf, - 0x01, 0x0a, 0x12, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x52, 0x75, 0x6c, 0x65, - 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x3b, 0x0a, 0x05, 0x74, - 0x69, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x54, 0x69, 0x65, - 0x72, 0x52, 0x05, 0x74, 0x69, 0x65, 0x72, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x6d, 0x69, 0x6e, 0x5f, - 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x37, 0x64, 0x5f, 0x63, 0x6f, 0x69, 0x6e, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x37, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x6d, - 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x33, 0x30, 0x64, 0x5f, - 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x6d, 0x69, 0x6e, - 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x33, 0x30, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, - 0x22, 0x8a, 0x10, 0x0a, 0x13, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x52, 0x75, - 0x6c, 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, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, - 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0b, 0x72, 0x75, 0x6c, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x5f, 0x72, 0x74, 0x70, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x74, 0x70, 0x50, 0x70, 0x6d, 0x12, - 0x22, 0x0a, 0x0d, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x70, 0x6d, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x70, 0x6f, 0x6f, 0x6c, 0x52, 0x61, 0x74, 0x65, - 0x50, 0x70, 0x6d, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x77, 0x61, 0x67, 0x65, 0x72, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x57, 0x61, 0x67, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x62, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x70, 0x6d, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x42, 0x61, - 0x6e, 0x64, 0x50, 0x70, 0x6d, 0x12, 0x30, 0x0a, 0x14, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x70, 0x72, - 0x69, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x12, 0x67, 0x69, 0x66, 0x74, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, - 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x3d, 0x0a, 0x1b, 0x6e, 0x6f, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, - 0x5f, 0x64, 0x72, 0x61, 0x77, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x6e, 0x6f, - 0x76, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x78, 0x45, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, - 0x74, 0x44, 0x72, 0x61, 0x77, 0x73, 0x12, 0x3d, 0x0a, 0x1b, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, - 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x5f, - 0x64, 0x72, 0x61, 0x77, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x6e, 0x6f, 0x72, - 0x6d, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x45, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, - 0x44, 0x72, 0x61, 0x77, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, - 0x76, 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x6d, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x6f, 0x6d, 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, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, - 0x63, 0x72, 0x65, 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, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x41, 0x74, 0x4d, 0x73, 0x12, 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x67, 0x65, 0x73, 0x18, 0x0f, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, - 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, - 0x69, 0x66, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x67, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, - 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x26, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x74, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x70, - 0x70, 0x6d, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x74, - 0x52, 0x61, 0x74, 0x65, 0x50, 0x70, 0x6d, 0x12, 0x26, 0x0a, 0x0f, 0x61, 0x6e, 0x63, 0x68, 0x6f, - 0x72, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0d, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x52, 0x61, 0x74, 0x65, 0x50, 0x70, 0x6d, 0x12, - 0x2c, 0x0a, 0x12, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, - 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x69, 0x6e, 0x69, - 0x74, 0x69, 0x61, 0x6c, 0x50, 0x6f, 0x6f, 0x6c, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x32, 0x0a, - 0x15, 0x6c, 0x6f, 0x73, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6b, 0x5f, 0x67, 0x75, 0x61, - 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x6c, 0x6f, - 0x73, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6b, 0x47, 0x75, 0x61, 0x72, 0x61, 0x6e, 0x74, 0x65, - 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x6c, 0x6f, 0x77, 0x5f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, - 0x72, 0x6b, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, - 0x6c, 0x6f, 0x77, 0x57, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x43, 0x6f, 0x69, 0x6e, - 0x73, 0x12, 0x3e, 0x0a, 0x1c, 0x6c, 0x6f, 0x77, 0x5f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x5f, 0x6e, - 0x6f, 0x6e, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x70, - 0x6d, 0x18, 0x16, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x6c, 0x6f, 0x77, 0x57, 0x61, 0x74, 0x65, - 0x72, 0x4e, 0x6f, 0x6e, 0x7a, 0x65, 0x72, 0x6f, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x50, 0x70, - 0x6d, 0x12, 0x30, 0x0a, 0x14, 0x68, 0x69, 0x67, 0x68, 0x5f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, - 0x61, 0x72, 0x6b, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x17, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x12, 0x68, 0x69, 0x67, 0x68, 0x57, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x72, 0x6b, 0x43, 0x6f, - 0x69, 0x6e, 0x73, 0x12, 0x40, 0x0a, 0x1d, 0x68, 0x69, 0x67, 0x68, 0x5f, 0x77, 0x61, 0x74, 0x65, - 0x72, 0x5f, 0x6e, 0x6f, 0x6e, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, - 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x18, 0x20, 0x01, 0x28, 0x03, 0x52, 0x19, 0x68, 0x69, 0x67, 0x68, - 0x57, 0x61, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x6e, 0x7a, 0x65, 0x72, 0x6f, 0x46, 0x61, 0x63, 0x74, - 0x6f, 0x72, 0x50, 0x70, 0x6d, 0x12, 0x37, 0x0a, 0x18, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, - 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x73, 0x74, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x6d, - 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, - 0x65, 0x42, 0x6f, 0x6f, 0x73, 0x74, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x4d, 0x73, 0x12, 0x39, - 0x0a, 0x19, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x73, 0x74, - 0x5f, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x1a, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x16, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x6f, 0x6f, 0x73, 0x74, - 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x50, 0x70, 0x6d, 0x12, 0x36, 0x0a, 0x17, 0x6a, 0x61, 0x63, - 0x6b, 0x70, 0x6f, 0x74, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x5f, - 0x70, 0x70, 0x6d, 0x73, 0x18, 0x1b, 0x20, 0x03, 0x28, 0x03, 0x52, 0x15, 0x6a, 0x61, 0x63, 0x6b, - 0x70, 0x6f, 0x74, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x50, 0x70, 0x6d, - 0x73, 0x12, 0x3a, 0x0a, 0x1a, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x5f, 0x67, 0x6c, 0x6f, - 0x62, 0x61, 0x6c, 0x5f, 0x72, 0x74, 0x70, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x70, 0x6d, 0x18, - 0x1c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x47, 0x6c, - 0x6f, 0x62, 0x61, 0x6c, 0x52, 0x74, 0x70, 0x4d, 0x61, 0x78, 0x50, 0x70, 0x6d, 0x12, 0x41, 0x0a, - 0x1e, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x72, 0x6f, - 0x75, 0x6e, 0x64, 0x5f, 0x72, 0x74, 0x70, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x70, 0x6d, 0x18, - 0x1d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x19, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x74, 0x70, 0x4d, 0x61, 0x78, 0x50, 0x70, 0x6d, - 0x12, 0x3d, 0x0a, 0x1c, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x34, 0x38, 0x68, 0x5f, 0x72, 0x74, 0x70, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x70, 0x6d, - 0x18, 0x1e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x34, 0x38, 0x68, 0x52, 0x74, 0x70, 0x4d, 0x61, 0x78, 0x50, 0x70, 0x6d, 0x12, - 0x41, 0x0a, 0x1d, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x64, - 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, - 0x18, 0x1f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1a, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x53, - 0x70, 0x65, 0x6e, 0x64, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x43, 0x6f, 0x69, - 0x6e, 0x73, 0x12, 0x3f, 0x0a, 0x1d, 0x6d, 0x61, 0x78, 0x5f, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, - 0x74, 0x5f, 0x68, 0x69, 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x64, 0x61, 0x79, 0x18, 0x20, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x6d, 0x61, 0x78, 0x4a, 0x61, - 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x48, 0x69, 0x74, 0x73, 0x50, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, - 0x44, 0x61, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x69, 0x6e, 0x67, 0x6c, - 0x65, 0x5f, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x18, 0x21, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, - 0x6d, 0x61, 0x78, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x50, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x12, - 0x33, 0x0a, 0x16, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x6c, 0x79, 0x5f, 0x70, - 0x61, 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x63, 0x61, 0x70, 0x18, 0x22, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x13, 0x75, 0x73, 0x65, 0x72, 0x48, 0x6f, 0x75, 0x72, 0x6c, 0x79, 0x50, 0x61, 0x79, 0x6f, 0x75, - 0x74, 0x43, 0x61, 0x70, 0x12, 0x31, 0x0a, 0x15, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x69, - 0x6c, 0x79, 0x5f, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x63, 0x61, 0x70, 0x18, 0x23, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x12, 0x75, 0x73, 0x65, 0x72, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x50, 0x61, - 0x79, 0x6f, 0x75, 0x74, 0x43, 0x61, 0x70, 0x12, 0x35, 0x0a, 0x17, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x63, - 0x61, 0x70, 0x18, 0x24, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x44, 0x61, 0x69, 0x6c, 0x79, 0x50, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x43, 0x61, 0x70, 0x12, 0x33, - 0x0a, 0x16, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x6c, 0x79, 0x5f, 0x70, 0x61, - 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x63, 0x61, 0x70, 0x18, 0x25, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, - 0x72, 0x6f, 0x6f, 0x6d, 0x48, 0x6f, 0x75, 0x72, 0x6c, 0x79, 0x50, 0x61, 0x79, 0x6f, 0x75, 0x74, - 0x43, 0x61, 0x70, 0x12, 0x35, 0x0a, 0x17, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x5f, 0x64, 0x61, - 0x69, 0x6c, 0x79, 0x5f, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x63, 0x61, 0x70, 0x18, 0x26, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x44, 0x61, 0x69, 0x6c, - 0x79, 0x50, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x43, 0x61, 0x70, 0x12, 0x3a, 0x0a, 0x1a, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x32, 0x34, 0x68, 0x5f, 0x72, 0x74, 0x70, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, - 0x68, 0x6f, 0x6c, 0x64, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x27, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, - 0x75, 0x73, 0x65, 0x72, 0x32, 0x34, 0x68, 0x52, 0x74, 0x70, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, - 0x6f, 0x6c, 0x64, 0x50, 0x70, 0x6d, 0x12, 0x45, 0x0a, 0x20, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x32, - 0x34, 0x68, 0x5f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x77, 0x69, 0x6e, 0x5f, - 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x28, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x1b, 0x75, 0x73, 0x65, 0x72, 0x32, 0x34, 0x68, 0x4f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x57, 0x69, 0x6e, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x50, 0x70, 0x6d, 0x22, 0xb0, 0x01, - 0x0a, 0x15, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, - 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 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, 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, 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, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, - 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, - 0x22, 0xb8, 0x02, 0x0a, 0x16, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, - 0x69, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 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, 0x70, - 0x72, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, - 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x75, 0x6c, - 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x5f, 0x72, 0x74, 0x70, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x74, 0x70, 0x50, 0x70, 0x6d, 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, 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, 0x29, 0x0a, 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x5f, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x74, 0x72, 0x61, - 0x74, 0x65, 0x67, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xc4, 0x07, 0x0a, 0x13, - 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, - 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, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 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, 0x21, 0x0a, 0x0c, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 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, 0x05, 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, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x54, 0x69, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x62, 0x61, - 0x73, 0x65, 0x5f, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, - 0x64, 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, 0x08, 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, 0x09, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x74, 0x70, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, 0x74, 0x70, - 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x31, 0x0a, 0x15, 0x67, - 0x69, 0x66, 0x74, 0x5f, 0x72, 0x74, 0x70, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x67, 0x69, 0x66, 0x74, - 0x52, 0x74, 0x70, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2d, - 0x0a, 0x13, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x74, - 0x70, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x67, 0x6c, 0x6f, - 0x62, 0x61, 0x6c, 0x42, 0x61, 0x73, 0x65, 0x52, 0x74, 0x70, 0x50, 0x70, 0x6d, 0x12, 0x29, 0x0a, - 0x11, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x74, 0x70, 0x5f, 0x70, - 0x70, 0x6d, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x67, 0x69, 0x66, 0x74, 0x42, 0x61, - 0x73, 0x65, 0x52, 0x74, 0x70, 0x50, 0x70, 0x6d, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x67, - 0x65, 0x5f, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0e, 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, 0x0f, 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, 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x17, 0x0a, 0x07, - 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, - 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, - 0x69, 0x65, 0x72, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x50, 0x70, 0x6d, 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, 0x13, 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, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x63, 0x6f, - 0x69, 0x6e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x17, - 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x16, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x17, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x34, 0x0a, 0x04, - 0x68, 0x69, 0x74, 0x73, 0x18, 0x18, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x48, 0x69, 0x74, 0x52, 0x04, 0x68, 0x69, - 0x74, 0x73, 0x22, 0x5f, 0x0a, 0x1b, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4c, 0x75, 0x63, - 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x40, 0x0a, 0x0a, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, - 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, - 0x47, 0x69, 0x66, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x09, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x47, - 0x69, 0x66, 0x74, 0x22, 0x5f, 0x0a, 0x1c, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4c, 0x75, - 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, - 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, - 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x22, 0x66, 0x0a, 0x20, 0x42, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x65, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, - 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x0b, 0x6c, 0x75, 0x63, 0x6b, - 0x79, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x4d, 0x65, 0x74, 0x61, - 0x52, 0x0a, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x73, 0x22, 0x66, 0x0a, 0x21, - 0x42, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4c, 0x75, 0x63, 0x6b, - 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x41, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, - 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, - 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x73, 0x22, 0xdd, 0x03, 0x0a, 0x17, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x33, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, - 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, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, - 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, - 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x67, - 0x69, 0x66, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x6e, 0x69, 0x74, - 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x75, - 0x6e, 0x69, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 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, 0x1a, 0x0a, 0x08, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1c, 0x0a, 0x0a, 0x70, 0x61, 0x69, 0x64, - 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x70, 0x61, - 0x69, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x70, - 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, - 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, - 0x64, 0x12, 0x31, 0x0a, 0x15, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x65, 0x72, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x12, 0x75, 0x73, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, - 0x41, 0x74, 0x4d, 0x73, 0x22, 0xb2, 0x03, 0x0a, 0x18, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x64, 0x72, 0x61, 0x77, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 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, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, - 0x43, 0x6f, 0x64, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, - 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, - 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, - 0x0b, 0x75, 0x6e, 0x69, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0a, 0x75, 0x6e, 0x69, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 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, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, - 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, - 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, - 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x50, 0x70, 0x6d, 0x12, 0x23, 0x0a, - 0x0d, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x75, 0x6c, 0x65, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 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, 0x22, 0x69, 0x0a, 0x19, 0x47, 0x65, 0x74, - 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, - 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 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, 0x70, - 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, - 0x6f, 0x6c, 0x49, 0x64, 0x22, 0x5d, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, - 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, - 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, - 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x22, 0xc0, 0x01, 0x0a, 0x1c, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x75, - 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, - 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, - 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x3f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x60, 0x0a, 0x1d, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, - 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, - 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x52, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, - 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, - 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x61, 0x0a, 0x1c, - 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x07, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x52, 0x75, 0x6c, 0x65, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x22, - 0xcc, 0x02, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, - 0x74, 0x44, 0x72, 0x61, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, - 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 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, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 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, 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, 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, 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, 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, - 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x78, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x71, - 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, - 0x72, 0x61, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x05, - 0x64, 0x72, 0x61, 0x77, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x52, 0x05, 0x64, 0x72, 0x61, 0x77, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, - 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, - 0x6c, 0x22, 0xaf, 0x03, 0x0a, 0x14, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, - 0x72, 0x61, 0x77, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6f, - 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, - 0x6c, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x64, 0x72, 0x61, - 0x77, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x44, - 0x72, 0x61, 0x77, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x5f, 0x75, - 0x73, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x6e, 0x69, 0x71, - 0x75, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x6e, 0x69, 0x71, 0x75, - 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, - 0x6e, 0x69, 0x71, 0x75, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x53, 0x70, 0x65, 0x6e, - 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, - 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, - 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x77, - 0x61, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0f, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, - 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x63, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x72, 0x74, 0x70, 0x5f, 0x70, - 0x70, 0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x61, 0x63, 0x74, 0x75, 0x61, 0x6c, - 0x52, 0x74, 0x70, 0x50, 0x70, 0x6d, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x70, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x72, 0x61, 0x77, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x67, - 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x73, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0c, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x44, 0x72, 0x61, 0x77, 0x73, - 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x73, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x44, 0x72, - 0x61, 0x77, 0x73, 0x22, 0xbf, 0x03, 0x0a, 0x14, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, - 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 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, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, - 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x5f, 0x66, 0x6c, 0x6f, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x46, 0x6c, 0x6f, 0x6f, 0x72, 0x12, - 0x2b, 0x0a, 0x11, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x61, 0x76, 0x61, 0x69, - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x19, 0x0a, 0x08, - 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, - 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x49, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, - 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x74, 0x6f, 0x74, 0x61, - 0x6c, 0x4f, 0x75, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x69, 0x7a, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 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, 0x29, 0x0a, 0x10, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x6d, 0x61, 0x6e, 0x75, 0x61, - 0x6c, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x43, 0x72, 0x65, 0x64, - 0x69, 0x74, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x6d, 0x61, 0x6e, 0x75, 0x61, - 0x6c, 0x5f, 0x64, 0x65, 0x62, 0x69, 0x74, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x0c, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x10, 0x6d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x44, 0x65, 0x62, 0x69, 0x74, - 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0xa0, 0x02, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x4c, 0x75, 0x63, - 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, - 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 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, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x67, 0x69, 0x66, 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, - 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, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x55, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, - 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x65, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x65, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x4c, - 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x53, 0x75, 0x6d, 0x6d, - 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x07, 0x73, - 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x53, - 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x22, - 0x9b, 0x01, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, - 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, - 0x67, 0x69, 0x66, 0x74, 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, 0x70, 0x6f, 0x6f, - 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, - 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x5f, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x74, - 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x63, 0x0a, - 0x21, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x50, 0x6f, - 0x6f, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x05, 0x70, 0x6f, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, - 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, - 0x50, 0x6f, 0x6f, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x05, 0x70, 0x6f, 0x6f, - 0x6c, 0x73, 0x22, 0xba, 0x01, 0x0a, 0x0c, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, - 0x48, 0x69, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x49, 0x6e, 0x64, - 0x65, 0x78, 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, 0x28, 0x0a, 0x10, 0x73, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x03, 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, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x50, 0x70, 0x6d, 0x12, 0x21, 0x0a, 0x0c, - 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0b, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x22, - 0xc6, 0x02, 0x0a, 0x21, 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, - 0x69, 0x66, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, - 0x79, 0x67, 0x69, 0x66, 0x74, 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, 0x70, 0x6f, - 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, - 0x6c, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x5f, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, - 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, - 0x0a, 0x0d, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, - 0x74, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x69, 0x6e, - 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x43, - 0x6f, 0x69, 0x6e, 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, 0x2a, 0x0a, 0x11, - 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x92, 0x03, 0x0a, 0x17, 0x4c, 0x75, 0x63, - 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, - 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, - 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x64, 0x6a, - 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 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, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x29, 0x0a, - 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, - 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x6f, 0x69, 0x6e, 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, 0x2a, 0x0a, 0x11, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x25, 0x0a, - 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x42, 0x65, - 0x66, 0x6f, 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, - 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x0a, 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, 0x0b, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xdc, 0x01, - 0x0a, 0x22, 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, - 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0a, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, - 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, - 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x41, 0x64, 0x6a, 0x75, 0x73, - 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, - 0x74, 0x12, 0x3c, 0x0a, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x50, 0x6f, - 0x6f, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 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, 0xc5, 0x01, 0x0a, - 0x1a, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x12, 0x14, 0x0a, 0x05, 0x64, - 0x72, 0x61, 0x77, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x72, 0x61, 0x77, - 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x67, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x77, 0x61, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x69, - 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x63, 0x6f, 0x69, - 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, - 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x69, - 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6e, 0x65, 0x74, 0x43, 0x6f, 0x69, - 0x6e, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x74, 0x70, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x06, 0x72, 0x74, 0x70, 0x50, 0x70, 0x6d, 0x12, 0x17, 0x0a, 0x07, 0x68, - 0x61, 0x73, 0x5f, 0x72, 0x74, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x68, 0x61, - 0x73, 0x52, 0x74, 0x70, 0x22, 0xfd, 0x0d, 0x0a, 0x14, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, - 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 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, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, - 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, - 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 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, 0x29, 0x0a, - 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, - 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, - 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1d, - 0x0a, 0x0a, 0x70, 0x61, 0x69, 0x64, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x73, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x09, 0x70, 0x61, 0x69, 0x64, 0x44, 0x72, 0x61, 0x77, 0x73, 0x12, 0x29, 0x0a, - 0x10, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x72, 0x61, 0x77, - 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c, - 0x65, 0x6e, 0x74, 0x44, 0x72, 0x61, 0x77, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, 0x73, 0x73, - 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6b, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6c, - 0x6f, 0x73, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6b, 0x12, 0x3f, 0x0a, 0x1c, 0x70, 0x65, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x6a, 0x61, 0x63, 0x6b, 0x70, - 0x6f, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x19, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x4a, 0x61, 0x63, - 0x6b, 0x70, 0x6f, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x67, 0x75, - 0x61, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x73, 0x5f, 0x72, 0x65, - 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x67, - 0x75, 0x61, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x44, 0x72, 0x61, 0x77, 0x73, 0x52, 0x65, 0x6d, - 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x64, 0x6f, 0x77, 0x6e, 0x77, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x10, 0x64, 0x6f, 0x77, 0x6e, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x64, 0x6f, 0x77, 0x6e, 0x77, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x5f, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x0f, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x13, 0x64, 0x6f, 0x77, 0x6e, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x46, 0x61, - 0x63, 0x74, 0x6f, 0x72, 0x50, 0x70, 0x6d, 0x12, 0x49, 0x0a, 0x08, 0x6f, 0x6e, 0x65, 0x5f, 0x68, - 0x6f, 0x75, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x52, 0x07, 0x6f, 0x6e, 0x65, 0x48, 0x6f, - 0x75, 0x72, 0x12, 0x5a, 0x0a, 0x11, 0x74, 0x77, 0x65, 0x6e, 0x74, 0x79, 0x5f, 0x66, 0x6f, 0x75, - 0x72, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, - 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x52, 0x0f, 0x74, - 0x77, 0x65, 0x6e, 0x74, 0x79, 0x46, 0x6f, 0x75, 0x72, 0x48, 0x6f, 0x75, 0x72, 0x73, 0x12, 0x5a, - 0x0a, 0x11, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x5f, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x68, 0x6f, - 0x75, 0x72, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x52, 0x0f, 0x66, 0x6f, 0x72, 0x74, 0x79, - 0x45, 0x69, 0x67, 0x68, 0x74, 0x48, 0x6f, 0x75, 0x72, 0x73, 0x12, 0x4a, 0x0a, 0x08, 0x6c, 0x69, - 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x52, 0x08, 0x6c, 0x69, - 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0f, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x69, - 0x6e, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x77, - 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, - 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x57, 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x4a, 0x0a, 0x22, 0x68, 0x69, 0x67, 0x68, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, - 0x69, 0x65, 0x72, 0x5f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x77, 0x69, 0x6e, - 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x16, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1e, 0x68, 0x69, - 0x67, 0x68, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x4f, 0x72, 0x64, 0x69, - 0x6e, 0x61, 0x72, 0x79, 0x57, 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x43, 0x0a, 0x1e, - 0x72, 0x74, 0x70, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x65, 0x6e, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x17, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x72, 0x74, 0x70, 0x43, 0x6f, 0x6d, 0x70, 0x65, 0x6e, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x43, 0x0a, 0x1e, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, - 0x73, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x18, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x63, 0x75, 0x6d, 0x75, 0x6c, - 0x61, 0x74, 0x69, 0x76, 0x65, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x4a, 0x61, 0x63, 0x6b, 0x70, 0x6f, - 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, - 0x74, 0x65, 0x65, 0x5f, 0x68, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x19, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x11, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x48, 0x69, - 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x64, - 0x72, 0x61, 0x77, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0d, 0x7a, 0x65, 0x72, 0x6f, 0x44, 0x72, 0x61, 0x77, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, - 0x0a, 0x12, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x67, 0x72, 0x61, 0x6e, - 0x74, 0x65, 0x64, 0x44, 0x72, 0x61, 0x77, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, - 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x44, 0x72, 0x61, 0x77, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x66, 0x61, - 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x1d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x44, 0x72, 0x61, - 0x77, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x6d, 0x61, 0x78, 0x5f, 0x6d, 0x75, - 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x1e, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, - 0x72, 0x50, 0x70, 0x6d, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x65, 0x77, 0x61, - 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, - 0x6d, 0x61, 0x78, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x27, - 0x0a, 0x10, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x61, 0x74, 0x5f, - 0x6d, 0x73, 0x18, 0x20, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x44, - 0x72, 0x61, 0x77, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x25, 0x0a, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x5f, - 0x64, 0x72, 0x61, 0x77, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x21, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x44, 0x72, 0x61, 0x77, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x28, - 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, - 0x6d, 0x73, 0x18, 0x22, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, - 0x5f, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x73, 0x18, 0x23, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x64, - 0x61, 0x74, 0x61, 0x4c, 0x61, 0x67, 0x4d, 0x73, 0x12, 0x3a, 0x0a, 0x1a, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x32, 0x34, 0x68, 0x5f, 0x72, 0x74, 0x70, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, - 0x6c, 0x64, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x24, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x75, 0x73, - 0x65, 0x72, 0x32, 0x34, 0x68, 0x52, 0x74, 0x70, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, - 0x64, 0x50, 0x70, 0x6d, 0x22, 0xa0, 0x03, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, - 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x6d, 0x65, 0x74, - 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 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, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x10, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, - 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x73, 0x74, 0x61, 0x67, 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, 0x17, - 0x0a, 0x07, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x62, 0x79, 0x18, 0x08, 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, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x73, 0x6f, 0x72, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, - 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, - 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x22, 0xe1, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, - 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, - 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 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, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0c, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x41, 0x74, 0x4d, 0x73, 0x12, - 0x1f, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, - 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, 0x22, 0xdd, 0x02, 0x0a, 0x1e, - 0x47, 0x65, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, - 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, - 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 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, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x28, 0x0a, 0x10, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x65, - 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x55, - 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, - 0x5f, 0x70, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6a, 0x61, 0x63, - 0x6b, 0x70, 0x6f, 0x74, 0x50, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x6a, 0x61, 0x63, 0x6b, - 0x70, 0x6f, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x0f, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x50, 0x61, 0x67, 0x65, - 0x53, 0x69, 0x7a, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x5f, - 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6a, 0x61, - 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x22, 0xc2, 0x01, 0x0a, 0x1b, - 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x75, 0x6c, - 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x68, - 0x69, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x68, - 0x69, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, - 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, - 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x50, 0x70, 0x6d, 0x12, 0x1d, 0x0a, - 0x0a, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x09, 0x64, 0x72, 0x61, 0x77, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, - 0x77, 0x61, 0x67, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0a, 0x77, 0x61, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x21, 0x0a, - 0x0c, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x73, - 0x22, 0xfc, 0x01, 0x0a, 0x1d, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x4a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6e, 0x75, 0x6d, 0x65, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x61, - 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x64, 0x65, 0x6e, 0x6f, 0x6d, - 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x5f, - 0x70, 0x70, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x50, 0x70, 0x6d, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x70, 0x70, 0x6d, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x50, 0x70, 0x6d, - 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x50, 0x70, 0x6d, 0x12, - 0x16, 0x0a, 0x06, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x06, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 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, - 0x8a, 0x04, 0x0a, 0x17, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x4a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x48, 0x69, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x64, - 0x72, 0x61, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x72, - 0x61, 0x77, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x75, 0x6c, 0x65, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, - 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x72, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x53, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 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, 0x1f, 0x0a, 0x0b, 0x77, 0x61, 0x67, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x69, 0x6e, - 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x77, 0x61, 0x67, 0x65, 0x72, 0x43, 0x6f, - 0x69, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x63, 0x6f, - 0x69, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6f, 0x75, - 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, - 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x51, 0x0a, 0x0a, - 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, - 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x4a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x1b, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0e, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x9a, 0x04, 0x0a, - 0x1f, 0x47, 0x65, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x42, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, - 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, - 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x07, 0x70, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x12, 0x68, 0x0a, 0x17, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, - 0x65, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, - 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, - 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, - 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x52, 0x16, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, - 0x65, 0x72, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, - 0x0a, 0x0c, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x5f, 0x68, 0x69, 0x74, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, - 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, - 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x48, 0x69, - 0x74, 0x52, 0x0b, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x48, 0x69, 0x74, 0x73, 0x12, 0x2a, - 0x0a, 0x11, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x5f, 0x68, 0x69, 0x74, 0x5f, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6a, 0x61, 0x63, 0x6b, 0x70, - 0x6f, 0x74, 0x48, 0x69, 0x74, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x6e, - 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0c, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x41, 0x74, 0x4d, 0x73, - 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x50, - 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x5f, 0x70, - 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, - 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x50, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, - 0x2e, 0x0a, 0x13, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x5f, - 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6e, 0x65, - 0x78, 0x74, 0x4a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, - 0x28, 0x0a, 0x10, 0x6a, 0x61, 0x63, 0x6b, 0x70, 0x6f, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x6d, - 0x6f, 0x72, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6a, 0x61, 0x63, 0x6b, 0x70, - 0x6f, 0x74, 0x48, 0x61, 0x73, 0x4d, 0x6f, 0x72, 0x65, 0x32, 0xf7, 0x03, 0x0a, 0x10, 0x4c, 0x75, - 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, - 0x0a, 0x0e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, - 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, - 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4c, 0x75, 0x63, 0x6b, 0x79, - 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x79, 0x0a, 0x14, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x65, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x12, - 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4c, 0x75, 0x63, 0x6b, - 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, - 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4c, 0x75, 0x63, - 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x88, 0x01, 0x0a, 0x19, 0x42, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x65, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, - 0x12, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, - 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x65, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, - 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, - 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, - 0x17, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, - 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x32, 0xa8, 0x09, 0x0a, 0x15, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4c, 0x75, 0x63, - 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x73, 0x0a, - 0x12, 0x47, 0x65, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, - 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x75, 0x63, 0x6b, - 0x79, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, - 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, - 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x15, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x75, 0x63, 0x6b, - 0x79, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, - 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x79, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, - 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x12, 0x4c, - 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, - 0x73, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, - 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, - 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, - 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, - 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x82, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, - 0x74, 0x44, 0x72, 0x61, 0x77, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x32, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, - 0x61, 0x77, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, - 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, - 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x88, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x75, - 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x73, 0x12, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, - 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, - 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x6f, 0x6c, - 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x8b, 0x01, 0x0a, 0x1a, 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, - 0x47, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, - 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, - 0x47, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, - 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6a, 0x75, - 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x42, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x88, - 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, - 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x34, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, - 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x75, 0x63, 0x6b, - 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x17, 0x47, 0x65, - 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x75, - 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x75, - 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x55, 0x73, 0x65, 0x72, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x30, - 0x5a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, - 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x67, 0x69, 0x66, 0x74, 0x76, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +const file_proto_luckygift_v1_luckygift_proto_rawDesc = "" + + "\n" + + "\"proto/luckygift/v1/luckygift.proto\x12\x12hyapp.luckygift.v1\"\xa5\x01\n" + + "\vRequestMeta\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x16\n" + + "\x06caller\x18\x02 \x01(\tR\x06caller\x12&\n" + + "\x0fgateway_node_id\x18\x03 \x01(\tR\rgatewayNodeId\x12\x1c\n" + + "\n" + + "sent_at_ms\x18\x04 \x01(\x03R\bsentAtMs\x12\x19\n" + + "\bapp_code\x18\x05 \x01(\tR\aappCode\"\xf5\x06\n" + + "\rLuckyGiftMeta\x123\n" + + "\x04meta\x18\x01 \x01(\v2\x1f.hyapp.luckygift.v1.RequestMetaR\x04meta\x12\x1d\n" + + "\n" + + "command_id\x18\x02 \x01(\tR\tcommandId\x12\x17\n" + + "\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x1b\n" + + "\tdevice_id\x18\x04 \x01(\tR\bdeviceId\x12\x17\n" + + "\aroom_id\x18\x05 \x01(\tR\x06roomId\x12\x1b\n" + + "\tanchor_id\x18\x06 \x01(\tR\banchorId\x12\x17\n" + + "\agift_id\x18\a \x01(\tR\x06giftId\x12\x1d\n" + + "\n" + + "coin_spent\x18\b \x01(\x03R\tcoinSpent\x12\x1c\n" + + "\n" + + "paid_at_ms\x18\t \x01(\x03R\bpaidAtMs\x12\x17\n" + + "\apool_id\x18\n" + + " \x01(\tR\x06poolId\x12$\n" + + "\x0etarget_user_id\x18\v \x01(\x03R\ftargetUserId\x12\x1d\n" + + "\n" + + "gift_count\x18\f \x01(\x05R\tgiftCount\x12*\n" + + "\x11visible_region_id\x18\r \x01(\x03R\x0fvisibleRegionId\x12\x1d\n" + + "\n" + + "country_id\x18\x0e \x01(\x03R\tcountryId\x12\x1f\n" + + "\vsender_name\x18\x0f \x01(\tR\n" + + "senderName\x12#\n" + + "\rsender_avatar\x18\x10 \x01(\tR\fsenderAvatar\x123\n" + + "\x16sender_display_user_id\x18\x11 \x01(\tR\x13senderDisplayUserId\x12@\n" + + "\x1dsender_pretty_display_user_id\x18\x12 \x01(\tR\x19senderPrettyDisplayUserId\x12*\n" + + "\x11recharge_7d_coins\x18\x13 \x01(\x03R\x0frecharge7dCoins\x12,\n" + + "\x12recharge_30d_coins\x18\x14 \x01(\x03R\x10recharge30dCoins\x12/\n" + + "\x14last_recharged_at_ms\x18\x15 \x01(\x03R\x11lastRechargedAtMs\x12*\n" + + "\x11gift_income_coins\x18\x16 \x01(\x03R\x0fgiftIncomeCoins\x121\n" + + "\x15user_registered_at_ms\x18\x17 \x01(\x03R\x12userRegisteredAtMs\"\xd3\x01\n" + + "\x11LuckyGiftRuleTier\x12\x14\n" + + "\x05stage\x18\x01 \x01(\tR\x05stage\x12\x17\n" + + "\atier_id\x18\x02 \x01(\tR\x06tierId\x12%\n" + + "\x0emultiplier_ppm\x18\x03 \x01(\x03R\rmultiplierPpm\x12&\n" + + "\x0fbase_weight_ppm\x18\x04 \x01(\x03R\rbaseWeightPpm\x12&\n" + + "\x0fhigh_water_only\x18\x05 \x01(\bR\rhighWaterOnly\x12\x18\n" + + "\aenabled\x18\x06 \x01(\bR\aenabled\"\xcf\x01\n" + + "\x12LuckyGiftRuleStage\x12\x14\n" + + "\x05stage\x18\x01 \x01(\tR\x05stage\x12;\n" + + "\x05tiers\x18\x02 \x03(\v2%.hyapp.luckygift.v1.LuckyGiftRuleTierR\x05tiers\x121\n" + + "\x15min_recharge_7d_coins\x18\x03 \x01(\x03R\x12minRecharge7dCoins\x123\n" + + "\x16min_recharge_30d_coins\x18\x04 \x01(\x03R\x13minRecharge30dCoins\"\x8a\x10\n" + + "\x13LuckyGiftRuleConfig\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x17\n" + + "\apool_id\x18\x02 \x01(\tR\x06poolId\x12!\n" + + "\frule_version\x18\x03 \x01(\x03R\vruleVersion\x12\x18\n" + + "\aenabled\x18\x04 \x01(\bR\aenabled\x12$\n" + + "\x0etarget_rtp_ppm\x18\x05 \x01(\x03R\ftargetRtpPpm\x12\"\n" + + "\rpool_rate_ppm\x18\x06 \x01(\x03R\vpoolRatePpm\x126\n" + + "\x17settlement_window_wager\x18\a \x01(\x03R\x15settlementWindowWager\x12(\n" + + "\x10control_band_ppm\x18\b \x01(\x03R\x0econtrolBandPpm\x120\n" + + "\x14gift_price_reference\x18\t \x01(\x03R\x12giftPriceReference\x12=\n" + + "\x1bnovice_max_equivalent_draws\x18\n" + + " \x01(\x03R\x18noviceMaxEquivalentDraws\x12=\n" + + "\x1bnormal_max_equivalent_draws\x18\v \x01(\x03R\x18normalMaxEquivalentDraws\x12*\n" + + "\x11effective_from_ms\x18\f \x01(\x03R\x0feffectiveFromMs\x12-\n" + + "\x13created_by_admin_id\x18\r \x01(\x03R\x10createdByAdminId\x12\"\n" + + "\rcreated_at_ms\x18\x0e \x01(\x03R\vcreatedAtMs\x12>\n" + + "\x06stages\x18\x0f \x03(\v2&.hyapp.luckygift.v1.LuckyGiftRuleStageR\x06stages\x12)\n" + + "\x10strategy_version\x18\x10 \x01(\tR\x0fstrategyVersion\x12&\n" + + "\x0fprofit_rate_ppm\x18\x11 \x01(\x03R\rprofitRatePpm\x12&\n" + + "\x0fanchor_rate_ppm\x18\x12 \x01(\x03R\ranchorRatePpm\x12,\n" + + "\x12initial_pool_coins\x18\x13 \x01(\x03R\x10initialPoolCoins\x122\n" + + "\x15loss_streak_guarantee\x18\x14 \x01(\x03R\x13lossStreakGuarantee\x12.\n" + + "\x13low_watermark_coins\x18\x15 \x01(\x03R\x11lowWatermarkCoins\x12>\n" + + "\x1clow_water_nonzero_factor_ppm\x18\x16 \x01(\x03R\x18lowWaterNonzeroFactorPpm\x120\n" + + "\x14high_watermark_coins\x18\x17 \x01(\x03R\x12highWatermarkCoins\x12@\n" + + "\x1dhigh_water_nonzero_factor_ppm\x18\x18 \x01(\x03R\x19highWaterNonzeroFactorPpm\x127\n" + + "\x18recharge_boost_window_ms\x18\x19 \x01(\x03R\x15rechargeBoostWindowMs\x129\n" + + "\x19recharge_boost_factor_ppm\x18\x1a \x01(\x03R\x16rechargeBoostFactorPpm\x126\n" + + "\x17jackpot_multiplier_ppms\x18\x1b \x03(\x03R\x15jackpotMultiplierPpms\x12:\n" + + "\x1ajackpot_global_rtp_max_ppm\x18\x1c \x01(\x03R\x16jackpotGlobalRtpMaxPpm\x12A\n" + + "\x1ejackpot_user_round_rtp_max_ppm\x18\x1d \x01(\x03R\x19jackpotUserRoundRtpMaxPpm\x12=\n" + + "\x1cjackpot_user_48h_rtp_max_ppm\x18\x1e \x01(\x03R\x17jackpotUser48hRtpMaxPpm\x12A\n" + + "\x1djackpot_spend_threshold_coins\x18\x1f \x01(\x03R\x1ajackpotSpendThresholdCoins\x12?\n" + + "\x1dmax_jackpot_hits_per_user_day\x18 \x01(\x03R\x18maxJackpotHitsPerUserDay\x12*\n" + + "\x11max_single_payout\x18! \x01(\x03R\x0fmaxSinglePayout\x123\n" + + "\x16user_hourly_payout_cap\x18\" \x01(\x03R\x13userHourlyPayoutCap\x121\n" + + "\x15user_daily_payout_cap\x18# \x01(\x03R\x12userDailyPayoutCap\x125\n" + + "\x17device_daily_payout_cap\x18$ \x01(\x03R\x14deviceDailyPayoutCap\x123\n" + + "\x16room_hourly_payout_cap\x18% \x01(\x03R\x13roomHourlyPayoutCap\x125\n" + + "\x17anchor_daily_payout_cap\x18& \x01(\x03R\x14anchorDailyPayoutCap\x12:\n" + + "\x1auser_24h_rtp_threshold_ppm\x18' \x01(\x03R\x16user24hRtpThresholdPpm\x12E\n" + + " user_24h_ordinary_win_factor_ppm\x18( \x01(\x03R\x1buser24hOrdinaryWinFactorPpm\"\xb0\x01\n" + + "\x15CheckLuckyGiftRequest\x123\n" + + "\x04meta\x18\x01 \x01(\v2\x1f.hyapp.luckygift.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x17\n" + + "\aroom_id\x18\x03 \x01(\tR\x06roomId\x12\x17\n" + + "\agift_id\x18\x04 \x01(\tR\x06giftId\x12\x17\n" + + "\apool_id\x18\x05 \x01(\tR\x06poolId\"\xb8\x02\n" + + "\x16CheckLuckyGiftResponse\x12\x18\n" + + "\aenabled\x18\x01 \x01(\bR\aenabled\x12\x16\n" + + "\x06reason\x18\x02 \x01(\tR\x06reason\x12\x17\n" + + "\agift_id\x18\x03 \x01(\tR\x06giftId\x12\x1d\n" + + "\n" + + "gift_price\x18\x04 \x01(\x03R\tgiftPrice\x12!\n" + + "\frule_version\x18\x05 \x01(\x03R\vruleVersion\x12$\n" + + "\x0etarget_rtp_ppm\x18\x06 \x01(\x03R\ftargetRtpPpm\x12'\n" + + "\x0fexperience_pool\x18\a \x01(\tR\x0eexperiencePool\x12\x17\n" + + "\apool_id\x18\b \x01(\tR\x06poolId\x12)\n" + + "\x10strategy_version\x18\t \x01(\tR\x0fstrategyVersion\"\xc4\a\n" + + "\x13LuckyGiftDrawResult\x12\x17\n" + + "\adraw_id\x18\x01 \x01(\tR\x06drawId\x12\x1d\n" + + "\n" + + "command_id\x18\x02 \x01(\tR\tcommandId\x12\x17\n" + + "\agift_id\x18\x03 \x01(\tR\x06giftId\x12!\n" + + "\frule_version\x18\x04 \x01(\x03R\vruleVersion\x12'\n" + + "\x0fexperience_pool\x18\x05 \x01(\tR\x0eexperiencePool\x12(\n" + + "\x10selected_tier_id\x18\x06 \x01(\tR\x0eselectedTierId\x12*\n" + + "\x11base_reward_coins\x18\a \x01(\x03R\x0fbaseRewardCoins\x124\n" + + "\x16effective_reward_coins\x18\b \x01(\x03R\x14effectiveRewardCoins\x12#\n" + + "\rreward_status\x18\t \x01(\tR\frewardStatus\x12(\n" + + "\x10rtp_window_index\x18\n" + + " \x01(\x03R\x0ertpWindowIndex\x121\n" + + "\x15gift_rtp_window_index\x18\v \x01(\x03R\x12giftRtpWindowIndex\x12-\n" + + "\x13global_base_rtp_ppm\x18\f \x01(\x03R\x10globalBaseRtpPpm\x12)\n" + + "\x11gift_base_rtp_ppm\x18\r \x01(\x03R\x0egiftBaseRtpPpm\x12%\n" + + "\x0estage_feedback\x18\x0e \x01(\bR\rstageFeedback\x12'\n" + + "\x0fhigh_multiplier\x18\x0f \x01(\bR\x0ehighMultiplier\x12\"\n" + + "\rcreated_at_ms\x18\x10 \x01(\x03R\vcreatedAtMs\x12\x17\n" + + "\apool_id\x18\x11 \x01(\tR\x06poolId\x12%\n" + + "\x0emultiplier_ppm\x18\x12 \x01(\x03R\rmultiplierPpm\x122\n" + + "\x15wallet_transaction_id\x18\x13 \x01(\tR\x13walletTransactionId\x12,\n" + + "\x12coin_balance_after\x18\x14 \x01(\x03R\x10coinBalanceAfter\x12\x17\n" + + "\auser_id\x18\x15 \x01(\x03R\x06userId\x12(\n" + + "\x10external_user_id\x18\x16 \x01(\tR\x0eexternalUserId\x12\x19\n" + + "\bapp_code\x18\x17 \x01(\tR\aappCode\x124\n" + + "\x04hits\x18\x18 \x03(\v2 .hyapp.luckygift.v1.LuckyGiftHitR\x04hits\"_\n" + + "\x1bExecuteLuckyGiftDrawRequest\x12@\n" + + "\n" + + "lucky_gift\x18\x01 \x01(\v2!.hyapp.luckygift.v1.LuckyGiftMetaR\tluckyGift\"_\n" + + "\x1cExecuteLuckyGiftDrawResponse\x12?\n" + + "\x06result\x18\x01 \x01(\v2'.hyapp.luckygift.v1.LuckyGiftDrawResultR\x06result\"f\n" + + " BatchExecuteLuckyGiftDrawRequest\x12B\n" + + "\vlucky_gifts\x18\x01 \x03(\v2!.hyapp.luckygift.v1.LuckyGiftMetaR\n" + + "luckyGifts\"f\n" + + "!BatchExecuteLuckyGiftDrawResponse\x12A\n" + + "\aresults\x18\x01 \x03(\v2'.hyapp.luckygift.v1.LuckyGiftDrawResultR\aresults\"\xdd\x03\n" + + "\x17ExternalGiftDrawRequest\x123\n" + + "\x04meta\x18\x01 \x01(\v2\x1f.hyapp.luckygift.v1.RequestMetaR\x04meta\x12\x19\n" + + "\bapp_code\x18\x03 \x01(\tR\aappCode\x12(\n" + + "\x10external_user_id\x18\x04 \x01(\tR\x0eexternalUserId\x12\x1d\n" + + "\n" + + "request_id\x18\x05 \x01(\tR\trequestId\x12\x1d\n" + + "\n" + + "gift_count\x18\x06 \x01(\x03R\tgiftCount\x12\x1f\n" + + "\vunit_amount\x18\a \x01(\x03R\n" + + "unitAmount\x12!\n" + + "\ftotal_amount\x18\b \x01(\x03R\vtotalAmount\x12\x1a\n" + + "\bcurrency\x18\t \x01(\tR\bcurrency\x12\x1c\n" + + "\n" + + "paid_at_ms\x18\n" + + " \x01(\x03R\bpaidAtMs\x12#\n" + + "\rmetadata_json\x18\v \x01(\tR\fmetadataJson\x12\x17\n" + + "\apool_id\x18\f \x01(\tR\x06poolId\x12\x1b\n" + + "\tdevice_id\x18\r \x01(\tR\bdeviceId\x121\n" + + "\x15user_registered_at_ms\x18\x0e \x01(\x03R\x12userRegisteredAtMs\"\xb2\x03\n" + + "\x18ExternalGiftDrawResponse\x12\x17\n" + + "\adraw_id\x18\x01 \x01(\tR\x06drawId\x12\x1d\n" + + "\n" + + "request_id\x18\x02 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x04 \x01(\tR\aappCode\x12(\n" + + "\x10external_user_id\x18\x05 \x01(\tR\x0eexternalUserId\x12\x1d\n" + + "\n" + + "gift_count\x18\x06 \x01(\x03R\tgiftCount\x12\x1f\n" + + "\vunit_amount\x18\a \x01(\x03R\n" + + "unitAmount\x12!\n" + + "\ftotal_amount\x18\b \x01(\x03R\vtotalAmount\x12#\n" + + "\rreward_amount\x18\t \x01(\x03R\frewardAmount\x12%\n" + + "\x0emultiplier_ppm\x18\n" + + " \x01(\x03R\rmultiplierPpm\x12#\n" + + "\rreward_status\x18\v \x01(\tR\frewardStatus\x12!\n" + + "\frule_version\x18\f \x01(\x03R\vruleVersion\x12\"\n" + + "\rcreated_at_ms\x18\r \x01(\x03R\vcreatedAtMs\"i\n" + + "\x19GetLuckyGiftConfigRequest\x123\n" + + "\x04meta\x18\x01 \x01(\v2\x1f.hyapp.luckygift.v1.RequestMetaR\x04meta\x12\x17\n" + + "\apool_id\x18\x02 \x01(\tR\x06poolId\"]\n" + + "\x1aGetLuckyGiftConfigResponse\x12?\n" + + "\x06config\x18\x01 \x01(\v2'.hyapp.luckygift.v1.LuckyGiftRuleConfigR\x06config\"\xc0\x01\n" + + "\x1cUpsertLuckyGiftConfigRequest\x123\n" + + "\x04meta\x18\x01 \x01(\v2\x1f.hyapp.luckygift.v1.RequestMetaR\x04meta\x12?\n" + + "\x06config\x18\x02 \x01(\v2'.hyapp.luckygift.v1.LuckyGiftRuleConfigR\x06config\x12*\n" + + "\x11operator_admin_id\x18\x03 \x01(\x03R\x0foperatorAdminId\"`\n" + + "\x1dUpsertLuckyGiftConfigResponse\x12?\n" + + "\x06config\x18\x01 \x01(\v2'.hyapp.luckygift.v1.LuckyGiftRuleConfigR\x06config\"R\n" + + "\x1bListLuckyGiftConfigsRequest\x123\n" + + "\x04meta\x18\x01 \x01(\v2\x1f.hyapp.luckygift.v1.RequestMetaR\x04meta\"a\n" + + "\x1cListLuckyGiftConfigsResponse\x12A\n" + + "\aconfigs\x18\x01 \x03(\v2'.hyapp.luckygift.v1.LuckyGiftRuleConfigR\aconfigs\"\xcc\x02\n" + + "\x19ListLuckyGiftDrawsRequest\x123\n" + + "\x04meta\x18\x01 \x01(\v2\x1f.hyapp.luckygift.v1.RequestMetaR\x04meta\x12\x17\n" + + "\agift_id\x18\x02 \x01(\tR\x06giftId\x12\x17\n" + + "\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x17\n" + + "\aroom_id\x18\x04 \x01(\tR\x06roomId\x12\x16\n" + + "\x06status\x18\x05 \x01(\tR\x06status\x12\x12\n" + + "\x04page\x18\x06 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\a \x01(\x05R\bpageSize\x12\x17\n" + + "\apool_id\x18\b \x01(\tR\x06poolId\x12(\n" + + "\x10external_user_id\x18\n" + + " \x01(\tR\x0eexternalUserId\x12#\n" + + "\rexternal_only\x18\v \x01(\bR\fexternalOnly\"q\n" + + "\x1aListLuckyGiftDrawsResponse\x12=\n" + + "\x05draws\x18\x01 \x03(\v2'.hyapp.luckygift.v1.LuckyGiftDrawResultR\x05draws\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\xaf\x03\n" + + "\x14LuckyGiftDrawSummary\x12\x17\n" + + "\apool_id\x18\x01 \x01(\tR\x06poolId\x12\x1f\n" + + "\vtotal_draws\x18\x02 \x01(\x03R\n" + + "totalDraws\x12!\n" + + "\funique_users\x18\x03 \x01(\x03R\vuniqueUsers\x12!\n" + + "\funique_rooms\x18\x04 \x01(\x03R\vuniqueRooms\x12*\n" + + "\x11total_spent_coins\x18\x05 \x01(\x03R\x0ftotalSpentCoins\x12,\n" + + "\x12total_reward_coins\x18\x06 \x01(\x03R\x10totalRewardCoins\x12*\n" + + "\x11base_reward_coins\x18\a \x01(\x03R\x0fbaseRewardCoins\x12$\n" + + "\x0eactual_rtp_ppm\x18\b \x01(\x03R\factualRtpPpm\x12#\n" + + "\rpending_draws\x18\t \x01(\x03R\fpendingDraws\x12#\n" + + "\rgranted_draws\x18\n" + + " \x01(\x03R\fgrantedDraws\x12!\n" + + "\ffailed_draws\x18\v \x01(\x03R\vfailedDraws\"\xbf\x03\n" + + "\x14LuckyGiftPoolBalance\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x17\n" + + "\apool_id\x18\x02 \x01(\tR\x06poolId\x12\x18\n" + + "\abalance\x18\x03 \x01(\x03R\abalance\x12#\n" + + "\rreserve_floor\x18\x04 \x01(\x03R\freserveFloor\x12+\n" + + "\x11available_balance\x18\x05 \x01(\x03R\x10availableBalance\x12\x19\n" + + "\btotal_in\x18\x06 \x01(\x03R\atotalIn\x12\x1b\n" + + "\ttotal_out\x18\a \x01(\x03R\btotalOut\x12\"\n" + + "\fmaterialized\x18\b \x01(\bR\fmaterialized\x12\"\n" + + "\rupdated_at_ms\x18\t \x01(\x03R\vupdatedAtMs\x12)\n" + + "\x10strategy_version\x18\n" + + " \x01(\tR\x0fstrategyVersion\x12.\n" + + "\x13manual_credit_total\x18\v \x01(\x03R\x11manualCreditTotal\x12,\n" + + "\x12manual_debit_total\x18\f \x01(\x03R\x10manualDebitTotal\"\xa0\x02\n" + + "\x1eGetLuckyGiftDrawSummaryRequest\x123\n" + + "\x04meta\x18\x01 \x01(\v2\x1f.hyapp.luckygift.v1.RequestMetaR\x04meta\x12\x17\n" + + "\agift_id\x18\x02 \x01(\tR\x06giftId\x12\x17\n" + + "\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x17\n" + + "\aroom_id\x18\x04 \x01(\tR\x06roomId\x12\x16\n" + + "\x06status\x18\x05 \x01(\tR\x06status\x12\x17\n" + + "\apool_id\x18\x06 \x01(\tR\x06poolId\x12(\n" + + "\x10external_user_id\x18\b \x01(\tR\x0eexternalUserId\x12#\n" + + "\rexternal_only\x18\t \x01(\bR\fexternalOnly\"e\n" + + "\x1fGetLuckyGiftDrawSummaryResponse\x12B\n" + + "\asummary\x18\x01 \x01(\v2(.hyapp.luckygift.v1.LuckyGiftDrawSummaryR\asummary\"\x9b\x01\n" + + " ListLuckyGiftPoolBalancesRequest\x123\n" + + "\x04meta\x18\x01 \x01(\v2\x1f.hyapp.luckygift.v1.RequestMetaR\x04meta\x12\x17\n" + + "\apool_id\x18\x02 \x01(\tR\x06poolId\x12)\n" + + "\x10strategy_version\x18\x03 \x01(\tR\x0fstrategyVersion\"c\n" + + "!ListLuckyGiftPoolBalancesResponse\x12>\n" + + "\x05pools\x18\x01 \x03(\v2(.hyapp.luckygift.v1.LuckyGiftPoolBalanceR\x05pools\"\xba\x01\n" + + "\fLuckyGiftHit\x12\x1d\n" + + "\n" + + "gift_index\x18\x01 \x01(\x05R\tgiftIndex\x12\x17\n" + + "\adraw_id\x18\x02 \x01(\tR\x06drawId\x12(\n" + + "\x10selected_tier_id\x18\x03 \x01(\tR\x0eselectedTierId\x12%\n" + + "\x0emultiplier_ppm\x18\x04 \x01(\x03R\rmultiplierPpm\x12!\n" + + "\freward_coins\x18\x05 \x01(\x03R\vrewardCoins\"\xc6\x02\n" + + "!AdjustLuckyGiftPoolBalanceRequest\x123\n" + + "\x04meta\x18\x01 \x01(\v2\x1f.hyapp.luckygift.v1.RequestMetaR\x04meta\x12\x17\n" + + "\apool_id\x18\x02 \x01(\tR\x06poolId\x12)\n" + + "\x10strategy_version\x18\x03 \x01(\tR\x0fstrategyVersion\x12#\n" + + "\radjustment_id\x18\x04 \x01(\tR\fadjustmentId\x12\x1c\n" + + "\tdirection\x18\x05 \x01(\tR\tdirection\x12!\n" + + "\famount_coins\x18\x06 \x01(\x03R\vamountCoins\x12\x16\n" + + "\x06reason\x18\a \x01(\tR\x06reason\x12*\n" + + "\x11operator_admin_id\x18\b \x01(\x03R\x0foperatorAdminId\"\x92\x03\n" + + "\x17LuckyGiftPoolAdjustment\x12#\n" + + "\radjustment_id\x18\x01 \x01(\tR\fadjustmentId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + + "\apool_id\x18\x03 \x01(\tR\x06poolId\x12)\n" + + "\x10strategy_version\x18\x04 \x01(\tR\x0fstrategyVersion\x12\x1c\n" + + "\tdirection\x18\x05 \x01(\tR\tdirection\x12!\n" + + "\famount_coins\x18\x06 \x01(\x03R\vamountCoins\x12\x16\n" + + "\x06reason\x18\a \x01(\tR\x06reason\x12*\n" + + "\x11operator_admin_id\x18\b \x01(\x03R\x0foperatorAdminId\x12%\n" + + "\x0ebalance_before\x18\t \x01(\x03R\rbalanceBefore\x12#\n" + + "\rbalance_after\x18\n" + + " \x01(\x03R\fbalanceAfter\x12\"\n" + + "\rcreated_at_ms\x18\v \x01(\x03R\vcreatedAtMs\"\xdc\x01\n" + + "\"AdjustLuckyGiftPoolBalanceResponse\x12K\n" + + "\n" + + "adjustment\x18\x01 \x01(\v2+.hyapp.luckygift.v1.LuckyGiftPoolAdjustmentR\n" + + "adjustment\x12<\n" + + "\x04pool\x18\x02 \x01(\v2(.hyapp.luckygift.v1.LuckyGiftPoolBalanceR\x04pool\x12+\n" + + "\x11idempotent_replay\x18\x03 \x01(\bR\x10idempotentReplay\"\xc5\x01\n" + + "\x1aLuckyGiftUserProfileWindow\x12\x14\n" + + "\x05draws\x18\x01 \x01(\x03R\x05draws\x12\x1f\n" + + "\vwager_coins\x18\x02 \x01(\x03R\n" + + "wagerCoins\x12!\n" + + "\fpayout_coins\x18\x03 \x01(\x03R\vpayoutCoins\x12\x1b\n" + + "\tnet_coins\x18\x04 \x01(\x03R\bnetCoins\x12\x17\n" + + "\artp_ppm\x18\x05 \x01(\x03R\x06rtpPpm\x12\x17\n" + + "\ahas_rtp\x18\x06 \x01(\bR\x06hasRtp\"\xfd\r\n" + + "\x14LuckyGiftUserProfile\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x17\n" + + "\apool_id\x18\x02 \x01(\tR\x06poolId\x12#\n" + + "\ridentity_type\x18\x03 \x01(\tR\fidentityType\x12(\n" + + "\x10internal_user_id\x18\x04 \x01(\x03R\x0einternalUserId\x12(\n" + + "\x10external_user_id\x18\x05 \x01(\tR\x0eexternalUserId\x12!\n" + + "\frule_version\x18\x06 \x01(\x03R\vruleVersion\x12)\n" + + "\x10strategy_version\x18\a \x01(\tR\x0fstrategyVersion\x12\x14\n" + + "\x05stage\x18\b \x01(\tR\x05stage\x12\x1d\n" + + "\n" + + "paid_draws\x18\t \x01(\x03R\tpaidDraws\x12)\n" + + "\x10equivalent_draws\x18\n" + + " \x01(\x03R\x0fequivalentDraws\x12\x1f\n" + + "\vloss_streak\x18\v \x01(\x03R\n" + + "lossStreak\x12?\n" + + "\x1cpending_spend_jackpot_tokens\x18\f \x01(\x03R\x19pendingSpendJackpotTokens\x12:\n" + + "\x19guarantee_draws_remaining\x18\r \x01(\x03R\x17guaranteeDrawsRemaining\x12+\n" + + "\x11downweight_active\x18\x0e \x01(\bR\x10downweightActive\x122\n" + + "\x15downweight_factor_ppm\x18\x0f \x01(\x03R\x13downweightFactorPpm\x12I\n" + + "\bone_hour\x18\x10 \x01(\v2..hyapp.luckygift.v1.LuckyGiftUserProfileWindowR\aoneHour\x12Z\n" + + "\x11twenty_four_hours\x18\x11 \x01(\v2..hyapp.luckygift.v1.LuckyGiftUserProfileWindowR\x0ftwentyFourHours\x12Z\n" + + "\x11forty_eight_hours\x18\x12 \x01(\v2..hyapp.luckygift.v1.LuckyGiftUserProfileWindowR\x0ffortyEightHours\x12J\n" + + "\blifetime\x18\x13 \x01(\v2..hyapp.luckygift.v1.LuckyGiftUserProfileWindowR\blifetime\x12*\n" + + "\x11base_reward_coins\x18\x14 \x01(\x03R\x0fbaseRewardCoins\x12,\n" + + "\x12ordinary_win_count\x18\x15 \x01(\x03R\x10ordinaryWinCount\x12J\n" + + "\"high_multiplier_ordinary_win_count\x18\x16 \x01(\x03R\x1ehighMultiplierOrdinaryWinCount\x12C\n" + + "\x1ertp_compensation_jackpot_count\x18\x17 \x01(\x03R\x1brtpCompensationJackpotCount\x12C\n" + + "\x1ecumulative_spend_jackpot_count\x18\x18 \x01(\x03R\x1bcumulativeSpendJackpotCount\x12.\n" + + "\x13guarantee_hit_count\x18\x19 \x01(\x03R\x11guaranteeHitCount\x12&\n" + + "\x0fzero_draw_count\x18\x1a \x01(\x03R\rzeroDrawCount\x12,\n" + + "\x12granted_draw_count\x18\x1b \x01(\x03R\x10grantedDrawCount\x12,\n" + + "\x12pending_draw_count\x18\x1c \x01(\x03R\x10pendingDrawCount\x12*\n" + + "\x11failed_draw_count\x18\x1d \x01(\x03R\x0ffailedDrawCount\x12,\n" + + "\x12max_multiplier_ppm\x18\x1e \x01(\x03R\x10maxMultiplierPpm\x12(\n" + + "\x10max_reward_coins\x18\x1f \x01(\x03R\x0emaxRewardCoins\x12'\n" + + "\x10first_draw_at_ms\x18 \x01(\x03R\rfirstDrawAtMs\x12%\n" + + "\x0flast_draw_at_ms\x18! \x01(\x03R\flastDrawAtMs\x12(\n" + + "\x10aggregated_at_ms\x18\" \x01(\x03R\x0eaggregatedAtMs\x12\x1e\n" + + "\vdata_lag_ms\x18# \x01(\x03R\tdataLagMs\x12:\n" + + "\x1auser_24h_rtp_threshold_ppm\x18$ \x01(\x03R\x16user24hRtpThresholdPpm\"\xa0\x03\n" + + " ListLuckyGiftUserProfilesRequest\x123\n" + + "\x04meta\x18\x01 \x01(\v2\x1f.hyapp.luckygift.v1.RequestMetaR\x04meta\x12\x17\n" + + "\apool_id\x18\x02 \x01(\tR\x06poolId\x12#\n" + + "\ridentity_type\x18\x03 \x01(\tR\fidentityType\x12(\n" + + "\x10internal_user_id\x18\x04 \x01(\x03R\x0einternalUserId\x12(\n" + + "\x10external_user_id\x18\x05 \x01(\tR\x0eexternalUserId\x12\x14\n" + + "\x05stage\x18\x06 \x01(\tR\x05stage\x12\x16\n" + + "\x06status\x18\a \x01(\tR\x06status\x12\x17\n" + + "\asort_by\x18\b \x01(\tR\x06sortBy\x12%\n" + + "\x0esort_direction\x18\t \x01(\tR\rsortDirection\x12\x12\n" + + "\x04page\x18\n" + + " \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\v \x01(\x05R\bpageSize\x12\x16\n" + + "\x06cursor\x18\f \x01(\tR\x06cursor\"\xe1\x01\n" + + "!ListLuckyGiftUserProfilesResponse\x12D\n" + + "\bprofiles\x18\x01 \x03(\v2(.hyapp.luckygift.v1.LuckyGiftUserProfileR\bprofiles\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\x12$\n" + + "\x0esnapshot_at_ms\x18\x03 \x01(\x03R\fsnapshotAtMs\x12\x1f\n" + + "\vnext_cursor\x18\x04 \x01(\tR\n" + + "nextCursor\x12\x19\n" + + "\bhas_more\x18\x05 \x01(\bR\ahasMore\"\xdd\x02\n" + + "\x1eGetLuckyGiftUserProfileRequest\x123\n" + + "\x04meta\x18\x01 \x01(\v2\x1f.hyapp.luckygift.v1.RequestMetaR\x04meta\x12\x17\n" + + "\apool_id\x18\x02 \x01(\tR\x06poolId\x12#\n" + + "\ridentity_type\x18\x03 \x01(\tR\fidentityType\x12(\n" + + "\x10internal_user_id\x18\x04 \x01(\x03R\x0einternalUserId\x12(\n" + + "\x10external_user_id\x18\x05 \x01(\tR\x0eexternalUserId\x12!\n" + + "\fjackpot_page\x18\x06 \x01(\x05R\vjackpotPage\x12*\n" + + "\x11jackpot_page_size\x18\a \x01(\x05R\x0fjackpotPageSize\x12%\n" + + "\x0ejackpot_cursor\x18\b \x01(\tR\rjackpotCursor\"\xc2\x01\n" + + "\x1bLuckyGiftUserMultiplierStat\x12\x19\n" + + "\bhit_type\x18\x01 \x01(\tR\ahitType\x12%\n" + + "\x0emultiplier_ppm\x18\x02 \x01(\x03R\rmultiplierPpm\x12\x1d\n" + + "\n" + + "draw_count\x18\x03 \x01(\x03R\tdrawCount\x12\x1f\n" + + "\vwager_coins\x18\x04 \x01(\x03R\n" + + "wagerCoins\x12!\n" + + "\fpayout_coins\x18\x05 \x01(\x03R\vpayoutCoins\"\xfc\x01\n" + + "\x1dLuckyGiftUserJackpotCondition\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x1c\n" + + "\tnumerator\x18\x02 \x01(\x03R\tnumerator\x12 \n" + + "\vdenominator\x18\x03 \x01(\x03R\vdenominator\x12\x1b\n" + + "\tratio_ppm\x18\x04 \x01(\x03R\bratioPpm\x12\x1b\n" + + "\tlimit_ppm\x18\x05 \x01(\x03R\blimitPpm\x12\x1d\n" + + "\n" + + "factor_ppm\x18\x06 \x01(\x03R\tfactorPpm\x12\x16\n" + + "\x06passed\x18\a \x01(\bR\x06passed\x12\x16\n" + + "\x06reason\x18\b \x01(\tR\x06reason\"\x8a\x04\n" + + "\x17LuckyGiftUserJackpotHit\x12\x17\n" + + "\adraw_id\x18\x01 \x01(\tR\x06drawId\x12\x1d\n" + + "\n" + + "request_id\x18\x02 \x01(\tR\trequestId\x12!\n" + + "\frule_version\x18\x03 \x01(\x03R\vruleVersion\x12\x14\n" + + "\x05stage\x18\x04 \x01(\tR\x05stage\x12\x1c\n" + + "\tmechanism\x18\x05 \x01(\tR\tmechanism\x12\x1f\n" + + "\vreason_code\x18\x06 \x01(\tR\n" + + "reasonCode\x12%\n" + + "\x0ereason_summary\x18\a \x01(\tR\rreasonSummary\x12\x17\n" + + "\atier_id\x18\b \x01(\tR\x06tierId\x12%\n" + + "\x0emultiplier_ppm\x18\t \x01(\x03R\rmultiplierPpm\x12\x1f\n" + + "\vwager_coins\x18\n" + + " \x01(\x03R\n" + + "wagerCoins\x12!\n" + + "\fpayout_coins\x18\v \x01(\x03R\vpayoutCoins\x12$\n" + + "\x0eoccurred_at_ms\x18\f \x01(\x03R\foccurredAtMs\x12Q\n" + + "\n" + + "conditions\x18\r \x03(\v21.hyapp.luckygift.v1.LuckyGiftUserJackpotConditionR\n" + + "conditions\x12\x1b\n" + + "\tevent_key\x18\x0e \x01(\tR\beventKey\"\x9a\x04\n" + + "\x1fGetLuckyGiftUserProfileResponse\x12B\n" + + "\aprofile\x18\x01 \x01(\v2(.hyapp.luckygift.v1.LuckyGiftUserProfileR\aprofile\x12h\n" + + "\x17multiplier_distribution\x18\x02 \x03(\v2/.hyapp.luckygift.v1.LuckyGiftUserMultiplierStatR\x16multiplierDistribution\x12N\n" + + "\fjackpot_hits\x18\x03 \x03(\v2+.hyapp.luckygift.v1.LuckyGiftUserJackpotHitR\vjackpotHits\x12*\n" + + "\x11jackpot_hit_total\x18\x04 \x01(\x03R\x0fjackpotHitTotal\x12$\n" + + "\x0esnapshot_at_ms\x18\x05 \x01(\x03R\fsnapshotAtMs\x12!\n" + + "\fjackpot_page\x18\x06 \x01(\x05R\vjackpotPage\x12*\n" + + "\x11jackpot_page_size\x18\a \x01(\x05R\x0fjackpotPageSize\x12.\n" + + "\x13next_jackpot_cursor\x18\b \x01(\tR\x11nextJackpotCursor\x12(\n" + + "\x10jackpot_has_more\x18\t \x01(\bR\x0ejackpotHasMore2\xf7\x03\n" + + "\x10LuckyGiftService\x12g\n" + + "\x0eCheckLuckyGift\x12).hyapp.luckygift.v1.CheckLuckyGiftRequest\x1a*.hyapp.luckygift.v1.CheckLuckyGiftResponse\x12y\n" + + "\x14ExecuteLuckyGiftDraw\x12/.hyapp.luckygift.v1.ExecuteLuckyGiftDrawRequest\x1a0.hyapp.luckygift.v1.ExecuteLuckyGiftDrawResponse\x12\x88\x01\n" + + "\x19BatchExecuteLuckyGiftDraw\x124.hyapp.luckygift.v1.BatchExecuteLuckyGiftDrawRequest\x1a5.hyapp.luckygift.v1.BatchExecuteLuckyGiftDrawResponse\x12t\n" + + "\x17ExecuteExternalGiftDraw\x12+.hyapp.luckygift.v1.ExternalGiftDrawRequest\x1a,.hyapp.luckygift.v1.ExternalGiftDrawResponse2\xa8\t\n" + + "\x15AdminLuckyGiftService\x12s\n" + + "\x12GetLuckyGiftConfig\x12-.hyapp.luckygift.v1.GetLuckyGiftConfigRequest\x1a..hyapp.luckygift.v1.GetLuckyGiftConfigResponse\x12|\n" + + "\x15UpsertLuckyGiftConfig\x120.hyapp.luckygift.v1.UpsertLuckyGiftConfigRequest\x1a1.hyapp.luckygift.v1.UpsertLuckyGiftConfigResponse\x12y\n" + + "\x14ListLuckyGiftConfigs\x12/.hyapp.luckygift.v1.ListLuckyGiftConfigsRequest\x1a0.hyapp.luckygift.v1.ListLuckyGiftConfigsResponse\x12s\n" + + "\x12ListLuckyGiftDraws\x12-.hyapp.luckygift.v1.ListLuckyGiftDrawsRequest\x1a..hyapp.luckygift.v1.ListLuckyGiftDrawsResponse\x12\x82\x01\n" + + "\x17GetLuckyGiftDrawSummary\x122.hyapp.luckygift.v1.GetLuckyGiftDrawSummaryRequest\x1a3.hyapp.luckygift.v1.GetLuckyGiftDrawSummaryResponse\x12\x88\x01\n" + + "\x19ListLuckyGiftPoolBalances\x124.hyapp.luckygift.v1.ListLuckyGiftPoolBalancesRequest\x1a5.hyapp.luckygift.v1.ListLuckyGiftPoolBalancesResponse\x12\x8b\x01\n" + + "\x1aAdjustLuckyGiftPoolBalance\x125.hyapp.luckygift.v1.AdjustLuckyGiftPoolBalanceRequest\x1a6.hyapp.luckygift.v1.AdjustLuckyGiftPoolBalanceResponse\x12\x88\x01\n" + + "\x19ListLuckyGiftUserProfiles\x124.hyapp.luckygift.v1.ListLuckyGiftUserProfilesRequest\x1a5.hyapp.luckygift.v1.ListLuckyGiftUserProfilesResponse\x12\x82\x01\n" + + "\x17GetLuckyGiftUserProfile\x122.hyapp.luckygift.v1.GetLuckyGiftUserProfileRequest\x1a3.hyapp.luckygift.v1.GetLuckyGiftUserProfileResponseB0Z.hyapp.local/api/proto/luckygift/v1;luckygiftv1b\x06proto3" var ( file_proto_luckygift_v1_luckygift_proto_rawDescOnce sync.Once - file_proto_luckygift_v1_luckygift_proto_rawDescData = file_proto_luckygift_v1_luckygift_proto_rawDesc + file_proto_luckygift_v1_luckygift_proto_rawDescData []byte ) func file_proto_luckygift_v1_luckygift_proto_rawDescGZIP() []byte { file_proto_luckygift_v1_luckygift_proto_rawDescOnce.Do(func() { - file_proto_luckygift_v1_luckygift_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_luckygift_v1_luckygift_proto_rawDescData) + file_proto_luckygift_v1_luckygift_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_luckygift_v1_luckygift_proto_rawDesc), len(file_proto_luckygift_v1_luckygift_proto_rawDesc))) }) return file_proto_luckygift_v1_luckygift_proto_rawDescData } @@ -5391,7 +4758,7 @@ func file_proto_luckygift_v1_luckygift_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_luckygift_v1_luckygift_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_luckygift_v1_luckygift_proto_rawDesc), len(file_proto_luckygift_v1_luckygift_proto_rawDesc)), NumEnums: 0, NumMessages: 41, NumExtensions: 0, @@ -5402,7 +4769,6 @@ func file_proto_luckygift_v1_luckygift_proto_init() { MessageInfos: file_proto_luckygift_v1_luckygift_proto_msgTypes, }.Build() File_proto_luckygift_v1_luckygift_proto = out.File - file_proto_luckygift_v1_luckygift_proto_rawDesc = nil file_proto_luckygift_v1_luckygift_proto_goTypes = nil file_proto_luckygift_v1_luckygift_proto_depIdxs = nil } diff --git a/api/proto/robot/v1/robot.pb.go b/api/proto/robot/v1/robot.pb.go index becc325c..a5f2f5de 100644 --- a/api/proto/robot/v1/robot.pb.go +++ b/api/proto/robot/v1/robot.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v5.29.2 +// protoc v7.35.0 // source: proto/robot/v1/robot.proto package robotv1 diff --git a/api/proto/robot/v1/robot_grpc.pb.go b/api/proto/robot/v1/robot_grpc.pb.go index c1bb2b2e..3cf9ceb8 100644 --- a/api/proto/robot/v1/robot_grpc.pb.go +++ b/api/proto/robot/v1/robot_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.6.2 -// - protoc v5.29.2 +// - protoc v7.35.0 // source: proto/robot/v1/robot.proto package robotv1 diff --git a/api/proto/room/v1/room.pb.go b/api/proto/room/v1/room.pb.go index 9543b57c..628a8aa9 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.35.1 +// protoc-gen-go v1.36.11 // protoc v7.35.0 // source: proto/room/v1/room.proto @@ -11,6 +11,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -23,13 +24,10 @@ const ( // RequestMeta 固定承载所有命令的调用元信息。 // room-service 用它串起幂等、追踪、路由和业务操作者身份。 type RequestMeta struct { - 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"` + 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"` // 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"` @@ -38,7 +36,9 @@ type RequestMeta struct { 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"` // device_id 只能来自 gateway 已验签 access JWT 的同名 claim;旧 JWT 缺字段时保持空值,不得用 session_id/command_id 伪造。 - DeviceId string `protobuf:"bytes,9,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` + DeviceId string `protobuf:"bytes,9,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RequestMeta) Reset() { @@ -136,13 +136,12 @@ func (x *RequestMeta) GetDeviceId() string { // CommandResult 统一返回命令是否真正落地,以及落地后的房间版本。 type CommandResult struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *CommandResult) Reset() { @@ -198,15 +197,14 @@ func (x *CommandResult) GetServerTimeMs() int64 { // RoomUser 只表达 room-service 需要保存的房间内轻量用户态。 type RoomUser struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + GiftValue int64 `protobuf:"varint,5,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` 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"` - GiftValue int64 `protobuf:"varint,5,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RoomUser) Reset() { @@ -277,17 +275,16 @@ func (x *RoomUser) GetGiftValue() int64 { // RoomOnlineUser 是在线用户列表的展示读模型。 // role 保留进房 presence 语义;room_role 只表达房间管理员身份;is_owner 单独表达房主身份。 type RoomOnlineUser struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *RoomOnlineUser) Reset() { @@ -371,13 +368,10 @@ func (x *RoomOnlineUser) GetIsOwner() bool { // SeatState 表达单个麦位当前占用和 RTC 发流确认状态。 type SeatState struct { - 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"` + 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"` // 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 必须带回它。 @@ -395,7 +389,9 @@ type SeatState struct { // 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"` // gift_value 是当前房间内该麦位用户收到的礼物热度累计,用户离房后清零。 - GiftValue int64 `protobuf:"varint,12,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` + GiftValue int64 `protobuf:"varint,12,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SeatState) Reset() { @@ -514,14 +510,13 @@ func (x *SeatState) GetGiftValue() int64 { // RankItem 表达房间内本地礼物榜项目。 type RankItem struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *RankItem) Reset() { @@ -584,15 +579,14 @@ func (x *RankItem) GetUpdatedAtMs() int64 { // RoomContributionRankItem 表达房间内某个周期的送礼贡献用户排行项。 type RoomContributionRankItem struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Rank int64 `protobuf:"varint,1,opt,name=rank,proto3" json:"rank,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"` + GiftValue int64 `protobuf:"varint,4,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,5,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` unknownFields protoimpl.UnknownFields - - Rank int64 `protobuf:"varint,1,opt,name=rank,proto3" json:"rank,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"` - GiftValue int64 `protobuf:"varint,4,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,5,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RoomContributionRankItem) Reset() { @@ -662,31 +656,30 @@ func (x *RoomContributionRankItem) GetUpdatedAtMs() int64 { // LuckyGiftDrawResult 是 SendGift 同步返回给当前送礼用户的幸运礼物抽奖表现。 type LuckyGiftDrawResult struct { - 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"` - EffectiveRewardCoins int64 `protobuf:"varint,11,opt,name=effective_reward_coins,json=effectiveRewardCoins,proto3" json:"effective_reward_coins,omitempty"` - RewardStatus string `protobuf:"bytes,12,opt,name=reward_status,json=rewardStatus,proto3" json:"reward_status,omitempty"` - StageFeedback bool `protobuf:"varint,13,opt,name=stage_feedback,json=stageFeedback,proto3" json:"stage_feedback,omitempty"` - HighMultiplier bool `protobuf:"varint,14,opt,name=high_multiplier,json=highMultiplier,proto3" json:"high_multiplier,omitempty"` - CreatedAtMs int64 `protobuf:"varint,15,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - WalletTransactionId string `protobuf:"bytes,16,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` - CoinBalanceAfter int64 `protobuf:"varint,17,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + 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"` + EffectiveRewardCoins int64 `protobuf:"varint,11,opt,name=effective_reward_coins,json=effectiveRewardCoins,proto3" json:"effective_reward_coins,omitempty"` + RewardStatus string `protobuf:"bytes,12,opt,name=reward_status,json=rewardStatus,proto3" json:"reward_status,omitempty"` + StageFeedback bool `protobuf:"varint,13,opt,name=stage_feedback,json=stageFeedback,proto3" json:"stage_feedback,omitempty"` + HighMultiplier bool `protobuf:"varint,14,opt,name=high_multiplier,json=highMultiplier,proto3" json:"high_multiplier,omitempty"` + CreatedAtMs int64 `protobuf:"varint,15,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + WalletTransactionId string `protobuf:"bytes,16,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` + CoinBalanceAfter int64 `protobuf:"varint,17,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` // target_user_id 是本次幸运礼物抽奖对应的收礼用户;多目标送礼用它关联结果。 TargetUserId int64 `protobuf:"varint,18,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` // hits 只包含 gift_count 微批中实际中奖的位置;旧客户端忽略该追加字段。 - Hits []*SendGiftLuckyHit `protobuf:"bytes,19,rep,name=hits,proto3" json:"hits,omitempty"` + Hits []*SendGiftLuckyHit `protobuf:"bytes,19,rep,name=hits,proto3" json:"hits,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *LuckyGiftDrawResult) Reset() { @@ -854,17 +847,16 @@ func (x *LuckyGiftDrawResult) GetHits() []*SendGiftLuckyHit { // RoomRocketRewardItem 是后台配置给客户端展示的火箭奖励候选项。 type RoomRocketRewardItem struct { - 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"` + 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"` // quantity 表示该奖项在一次火箭发射中最多发给多少个在房用户;为空或 0 时兼容旧配置按 1 份处理。 - Quantity int64 `protobuf:"varint,6,opt,name=quantity,proto3" json:"quantity,omitempty"` + Quantity int64 `protobuf:"varint,6,opt,name=quantity,proto3" json:"quantity,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RoomRocketRewardItem) Reset() { @@ -941,10 +933,7 @@ func (x *RoomRocketRewardItem) GetQuantity() int64 { // RoomRocketLevel 暴露单个等级火箭的物料、阈值和三类奖励池。 type RoomRocketLevel struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + 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"` @@ -954,6 +943,8 @@ 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() { @@ -1051,18 +1042,17 @@ func (x *RoomRocketLevel) GetIgniterRewards() []*RoomRocketRewardItem { // RoomRocketRewardGrant 是一次火箭发射后给某个用户结算出的具体奖励。 type RoomRocketRewardGrant struct { - 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"` + 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 } func (x *RoomRocketRewardGrant) Reset() { @@ -1153,13 +1143,12 @@ func (x *RoomRocketRewardGrant) GetStatus() string { // RoomRocketContribution 是当前火箭等级内的实际加燃料贡献累计。 type RoomRocketContribution struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Fuel int64 `protobuf:"varint,2,opt,name=fuel,proto3" json:"fuel,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,3,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` unknownFields protoimpl.UnknownFields - - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Fuel int64 `protobuf:"varint,2,opt,name=fuel,proto3" json:"fuel,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,3,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RoomRocketContribution) Reset() { @@ -1215,20 +1204,19 @@ func (x *RoomRocketContribution) GetUpdatedAtMs() int64 { // RoomRocketPendingLaunch 是已经点火、等待延迟发射的单枚火箭。 type RoomRocketPendingLaunch struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *RoomRocketPendingLaunch) Reset() { @@ -1333,10 +1321,7 @@ func (x *RoomRocketPendingLaunch) GetCoverUrl() string { // RoomRocketState 是 Room Cell 持有并随快照恢复的当前火箭状态。 type RoomRocketState struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + 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"` @@ -1352,6 +1337,8 @@ type RoomRocketState struct { 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"` CurrentContributions []*RoomRocketContribution `protobuf:"bytes,15,rep,name=current_contributions,json=currentContributions,proto3" json:"current_contributions,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RoomRocketState) Reset() { @@ -1491,18 +1478,17 @@ func (x *RoomRocketState) GetCurrentContributions() []*RoomRocketContribution { // RoomRocketInfo 是 App 初始化火箭 UI 的完整读模型。 type RoomRocketInfo struct { - 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"` + 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 } func (x *RoomRocketInfo) Reset() { @@ -1593,16 +1579,15 @@ func (x *RoomRocketInfo) GetRewardStackPolicy() string { // RoomRocketGiftFuelRule 是后台配置的礼物燃料覆盖规则。 type RoomRocketGiftFuelRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *RoomRocketGiftFuelRule) Reset() { @@ -1679,10 +1664,7 @@ func (x *RoomRocketGiftFuelRule) GetExcluded() bool { // AdminRoomRocketConfig 是后台管理读写的完整火箭配置。 type AdminRoomRocketConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + 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"` @@ -1697,6 +1679,8 @@ 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() { @@ -1828,11 +1812,10 @@ func (x *AdminRoomRocketConfig) GetUpdatedAtMs() int64 { } type AdminGetRoomRocketConfigRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AdminGetRoomRocketConfigRequest) Reset() { @@ -1873,12 +1856,11 @@ func (x *AdminGetRoomRocketConfigRequest) GetMeta() *RequestMeta { } type AdminGetRoomRocketConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminGetRoomRocketConfigResponse) Reset() { @@ -1926,13 +1908,12 @@ func (x *AdminGetRoomRocketConfigResponse) GetServerTimeMs() int64 { } type AdminUpdateRoomRocketConfigRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminUpdateRoomRocketConfigRequest) Reset() { @@ -1987,12 +1968,11 @@ func (x *AdminUpdateRoomRocketConfigRequest) GetAdminId() int64 { } type AdminUpdateRoomRocketConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminUpdateRoomRocketConfigResponse) Reset() { @@ -2040,14 +2020,13 @@ func (x *AdminUpdateRoomRocketConfigResponse) GetServerTimeMs() int64 { } type AdminRoomSeatConfig struct { - 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"` + 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 } func (x *AdminRoomSeatConfig) Reset() { @@ -2109,11 +2088,10 @@ func (x *AdminRoomSeatConfig) GetUpdatedAtMs() int64 { } type AdminGetRoomSeatConfigRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AdminGetRoomSeatConfigRequest) Reset() { @@ -2154,12 +2132,11 @@ func (x *AdminGetRoomSeatConfigRequest) GetMeta() *RequestMeta { } type AdminGetRoomSeatConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminGetRoomSeatConfigResponse) Reset() { @@ -2207,13 +2184,12 @@ func (x *AdminGetRoomSeatConfigResponse) GetServerTimeMs() int64 { } type AdminUpdateRoomSeatConfigRequest struct { - 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"` + 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 } func (x *AdminUpdateRoomSeatConfigRequest) Reset() { @@ -2268,12 +2244,11 @@ func (x *AdminUpdateRoomSeatConfigRequest) GetDefaultSeatCount() int32 { } type AdminUpdateRoomSeatConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminUpdateRoomSeatConfigResponse) Reset() { @@ -2321,12 +2296,11 @@ func (x *AdminUpdateRoomSeatConfigResponse) GetServerTimeMs() int64 { } type AdminHumanRoomRobotCountryPool struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` + RobotUserIds []int64 `protobuf:"varint,2,rep,packed,name=robot_user_ids,json=robotUserIds,proto3" json:"robot_user_ids,omitempty"` unknownFields protoimpl.UnknownFields - - CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` - RobotUserIds []int64 `protobuf:"varint,2,rep,packed,name=robot_user_ids,json=robotUserIds,proto3" json:"robot_user_ids,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AdminHumanRoomRobotCountryPool) Reset() { @@ -2374,14 +2348,13 @@ func (x *AdminHumanRoomRobotCountryPool) GetRobotUserIds() []int64 { } type AdminHumanRoomRobotCountryRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` - MaxRoomCount int32 `protobuf:"varint,2,opt,name=max_room_count,json=maxRoomCount,proto3" json:"max_room_count,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` + MaxRoomCount int32 `protobuf:"varint,2,opt,name=max_room_count,json=maxRoomCount,proto3" json:"max_room_count,omitempty"` // allowed_owner_ids 为空表示该国家扫描所有真人房;非空时只扫描房主展示短号/内部 owner_user_id 命中的房间。 AllowedOwnerIds []string `protobuf:"bytes,3,rep,name=allowed_owner_ids,json=allowedOwnerIds,proto3" json:"allowed_owner_ids,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminHumanRoomRobotCountryRule) Reset() { @@ -2436,10 +2409,7 @@ func (x *AdminHumanRoomRobotCountryRule) GetAllowedOwnerIds() []string { } type AdminHumanRoomRobotConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + 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"` CandidateRoomMaxOnline int32 `protobuf:"varint,3,opt,name=candidate_room_max_online,json=candidateRoomMaxOnline,proto3" json:"candidate_room_max_online,omitempty"` @@ -2470,7 +2440,9 @@ type AdminHumanRoomRobotConfig struct { // country_limit_enabled 打开后只按 country_rules 中配置的国家进真人房。 CountryLimitEnabled bool `protobuf:"varint,27,opt,name=country_limit_enabled,json=countryLimitEnabled,proto3" json:"country_limit_enabled,omitempty"` // country_rules 配置每个国家最多同时进入几个真人房;空集合表示不进入任何国家。 - CountryRules []*AdminHumanRoomRobotCountryRule `protobuf:"bytes,28,rep,name=country_rules,json=countryRules,proto3" json:"country_rules,omitempty"` + CountryRules []*AdminHumanRoomRobotCountryRule `protobuf:"bytes,28,rep,name=country_rules,json=countryRules,proto3" json:"country_rules,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminHumanRoomRobotConfig) Reset() { @@ -2700,11 +2672,10 @@ func (x *AdminHumanRoomRobotConfig) GetCountryRules() []*AdminHumanRoomRobotCoun } type AdminGetHumanRoomRobotConfigRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AdminGetHumanRoomRobotConfigRequest) Reset() { @@ -2745,12 +2716,11 @@ func (x *AdminGetHumanRoomRobotConfigRequest) GetMeta() *RequestMeta { } type AdminGetHumanRoomRobotConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Config *AdminHumanRoomRobotConfig `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 - - Config *AdminHumanRoomRobotConfig `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"` + sizeCache protoimpl.SizeCache } func (x *AdminGetHumanRoomRobotConfigResponse) Reset() { @@ -2798,13 +2768,12 @@ func (x *AdminGetHumanRoomRobotConfigResponse) GetServerTimeMs() int64 { } type AdminUpdateHumanRoomRobotConfigRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Config *AdminHumanRoomRobotConfig `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` + AdminId uint64 `protobuf:"varint,3,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Config *AdminHumanRoomRobotConfig `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` - AdminId uint64 `protobuf:"varint,3,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AdminUpdateHumanRoomRobotConfigRequest) Reset() { @@ -2859,12 +2828,11 @@ func (x *AdminUpdateHumanRoomRobotConfigRequest) GetAdminId() uint64 { } type AdminUpdateHumanRoomRobotConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Config *AdminHumanRoomRobotConfig `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 - - Config *AdminHumanRoomRobotConfig `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"` + sizeCache protoimpl.SizeCache } func (x *AdminUpdateHumanRoomRobotConfigResponse) Reset() { @@ -2912,17 +2880,16 @@ func (x *AdminUpdateHumanRoomRobotConfigResponse) GetServerTimeMs() int64 { } type AdminRoomPinRoom struct { - 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"` + 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 } func (x *AdminRoomPinRoom) Reset() { @@ -3005,24 +2972,23 @@ func (x *AdminRoomPinRoom) GetStatus() string { } type AdminRoomPin struct { - 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"` + 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 } func (x *AdminRoomPin) Reset() { @@ -3154,17 +3120,16 @@ func (x *AdminRoomPin) GetPinType() string { } type AdminListRoomPinsRequest struct { - 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"` + 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 } func (x *AdminListRoomPinsRequest) Reset() { @@ -3247,13 +3212,12 @@ func (x *AdminListRoomPinsRequest) GetPinType() string { } type AdminListRoomPinsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminListRoomPinsResponse) Reset() { @@ -3308,18 +3272,17 @@ func (x *AdminListRoomPinsResponse) GetServerTimeMs() int64 { } type AdminCreateRoomPinRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminCreateRoomPinRequest) Reset() { @@ -3409,12 +3372,11 @@ func (x *AdminCreateRoomPinRequest) GetPinType() string { } type AdminCreateRoomPinResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminCreateRoomPinResponse) Reset() { @@ -3462,13 +3424,12 @@ func (x *AdminCreateRoomPinResponse) GetServerTimeMs() int64 { } type AdminCancelRoomPinRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminCancelRoomPinRequest) Reset() { @@ -3523,12 +3484,11 @@ func (x *AdminCancelRoomPinRequest) GetAdminId() uint64 { } type AdminCancelRoomPinResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminCancelRoomPinResponse) Reset() { @@ -3576,22 +3536,21 @@ func (x *AdminCancelRoomPinResponse) GetServerTimeMs() int64 { } type AdminRobotRoomGiftRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - GiftIds []string `protobuf:"bytes,1,rep,name=gift_ids,json=giftIds,proto3" json:"gift_ids,omitempty"` - LuckyGiftIds []string `protobuf:"bytes,2,rep,name=lucky_gift_ids,json=luckyGiftIds,proto3" json:"lucky_gift_ids,omitempty"` - NormalGiftIntervalMs int64 `protobuf:"varint,3,opt,name=normal_gift_interval_ms,json=normalGiftIntervalMs,proto3" json:"normal_gift_interval_ms,omitempty"` - LuckyComboMin int64 `protobuf:"varint,4,opt,name=lucky_combo_min,json=luckyComboMin,proto3" json:"lucky_combo_min,omitempty"` - LuckyComboMax int64 `protobuf:"varint,5,opt,name=lucky_combo_max,json=luckyComboMax,proto3" json:"lucky_combo_max,omitempty"` - LuckyPauseMinMs int64 `protobuf:"varint,6,opt,name=lucky_pause_min_ms,json=luckyPauseMinMs,proto3" json:"lucky_pause_min_ms,omitempty"` - LuckyPauseMaxMs int64 `protobuf:"varint,7,opt,name=lucky_pause_max_ms,json=luckyPauseMaxMs,proto3" json:"lucky_pause_max_ms,omitempty"` - RobotStayMinMs int64 `protobuf:"varint,8,opt,name=robot_stay_min_ms,json=robotStayMinMs,proto3" json:"robot_stay_min_ms,omitempty"` - RobotStayMaxMs int64 `protobuf:"varint,9,opt,name=robot_stay_max_ms,json=robotStayMaxMs,proto3" json:"robot_stay_max_ms,omitempty"` - RobotReplaceMinMs int64 `protobuf:"varint,10,opt,name=robot_replace_min_ms,json=robotReplaceMinMs,proto3" json:"robot_replace_min_ms,omitempty"` - RobotReplaceMaxMs int64 `protobuf:"varint,11,opt,name=robot_replace_max_ms,json=robotReplaceMaxMs,proto3" json:"robot_replace_max_ms,omitempty"` - MaxGiftSenders int64 `protobuf:"varint,12,opt,name=max_gift_senders,json=maxGiftSenders,proto3" json:"max_gift_senders,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + GiftIds []string `protobuf:"bytes,1,rep,name=gift_ids,json=giftIds,proto3" json:"gift_ids,omitempty"` + LuckyGiftIds []string `protobuf:"bytes,2,rep,name=lucky_gift_ids,json=luckyGiftIds,proto3" json:"lucky_gift_ids,omitempty"` + NormalGiftIntervalMs int64 `protobuf:"varint,3,opt,name=normal_gift_interval_ms,json=normalGiftIntervalMs,proto3" json:"normal_gift_interval_ms,omitempty"` + LuckyComboMin int64 `protobuf:"varint,4,opt,name=lucky_combo_min,json=luckyComboMin,proto3" json:"lucky_combo_min,omitempty"` + LuckyComboMax int64 `protobuf:"varint,5,opt,name=lucky_combo_max,json=luckyComboMax,proto3" json:"lucky_combo_max,omitempty"` + LuckyPauseMinMs int64 `protobuf:"varint,6,opt,name=lucky_pause_min_ms,json=luckyPauseMinMs,proto3" json:"lucky_pause_min_ms,omitempty"` + LuckyPauseMaxMs int64 `protobuf:"varint,7,opt,name=lucky_pause_max_ms,json=luckyPauseMaxMs,proto3" json:"lucky_pause_max_ms,omitempty"` + RobotStayMinMs int64 `protobuf:"varint,8,opt,name=robot_stay_min_ms,json=robotStayMinMs,proto3" json:"robot_stay_min_ms,omitempty"` + RobotStayMaxMs int64 `protobuf:"varint,9,opt,name=robot_stay_max_ms,json=robotStayMaxMs,proto3" json:"robot_stay_max_ms,omitempty"` + RobotReplaceMinMs int64 `protobuf:"varint,10,opt,name=robot_replace_min_ms,json=robotReplaceMinMs,proto3" json:"robot_replace_min_ms,omitempty"` + RobotReplaceMaxMs int64 `protobuf:"varint,11,opt,name=robot_replace_max_ms,json=robotReplaceMaxMs,proto3" json:"robot_replace_max_ms,omitempty"` + MaxGiftSenders int64 `protobuf:"varint,12,opt,name=max_gift_senders,json=maxGiftSenders,proto3" json:"max_gift_senders,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminRobotRoomGiftRule) Reset() { @@ -3709,10 +3668,7 @@ func (x *AdminRobotRoomGiftRule) GetMaxGiftSenders() int64 { } type AdminRobotRoom struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` RoomShortId string `protobuf:"bytes,3,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` @@ -3728,6 +3684,8 @@ type AdminRobotRoom struct { UpdatedAtMs int64 `protobuf:"varint,13,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` ActiveRobotCount int32 `protobuf:"varint,14,opt,name=active_robot_count,json=activeRobotCount,proto3" json:"active_robot_count,omitempty"` SeatCount int32 `protobuf:"varint,15,opt,name=seat_count,json=seatCount,proto3" json:"seat_count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminRobotRoom) Reset() { @@ -3866,14 +3824,13 @@ func (x *AdminRobotRoom) GetSeatCount() int32 { } type AdminListRobotRoomsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` 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"` - Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AdminListRobotRoomsRequest) Reset() { @@ -3935,13 +3892,12 @@ func (x *AdminListRobotRoomsRequest) GetStatus() string { } type AdminListRobotRoomsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Rooms []*AdminRobotRoom `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 - - Rooms []*AdminRobotRoom `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"` + sizeCache protoimpl.SizeCache } func (x *AdminListRobotRoomsResponse) Reset() { @@ -3996,10 +3952,7 @@ func (x *AdminListRobotRoomsResponse) GetServerTimeMs() int64 { } type AdminCreateRobotRoomRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` OwnerRobotUserId int64 `protobuf:"varint,2,opt,name=owner_robot_user_id,json=ownerRobotUserId,proto3" json:"owner_robot_user_id,omitempty"` CandidateRobotUserIds []int64 `protobuf:"varint,3,rep,packed,name=candidate_robot_user_ids,json=candidateRobotUserIds,proto3" json:"candidate_robot_user_ids,omitempty"` @@ -4012,6 +3965,8 @@ type AdminCreateRobotRoomRequest struct { AdminId uint64 `protobuf:"varint,10,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` OwnerCountryCode string `protobuf:"bytes,11,opt,name=owner_country_code,json=ownerCountryCode,proto3" json:"owner_country_code,omitempty"` SeatCount int32 `protobuf:"varint,12,opt,name=seat_count,json=seatCount,proto3" json:"seat_count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminCreateRobotRoomRequest) Reset() { @@ -4129,12 +4084,11 @@ func (x *AdminCreateRobotRoomRequest) GetSeatCount() int32 { } type AdminCreateRobotRoomResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Room *AdminRobotRoom `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 - - Room *AdminRobotRoom `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"` + sizeCache protoimpl.SizeCache } func (x *AdminCreateRobotRoomResponse) Reset() { @@ -4182,13 +4136,12 @@ func (x *AdminCreateRobotRoomResponse) GetServerTimeMs() int64 { } type AdminSetRobotRoomStatusRequest struct { - state protoimpl.MessageState - 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"` + AdminId uint64 `protobuf:"varint,3,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` - AdminId uint64 `protobuf:"varint,3,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AdminSetRobotRoomStatusRequest) Reset() { @@ -4243,12 +4196,11 @@ func (x *AdminSetRobotRoomStatusRequest) GetAdminId() uint64 { } type AdminSetRobotRoomStatusResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Room *AdminRobotRoom `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 - - Room *AdminRobotRoom `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"` + sizeCache protoimpl.SizeCache } func (x *AdminSetRobotRoomStatusResponse) Reset() { @@ -4296,14 +4248,13 @@ func (x *AdminSetRobotRoomStatusResponse) GetServerTimeMs() int64 { } type AdminRenameOwnerCountryCodeRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - OldCountryCode string `protobuf:"bytes,2,opt,name=old_country_code,json=oldCountryCode,proto3" json:"old_country_code,omitempty"` - NewCountryCode string `protobuf:"bytes,3,opt,name=new_country_code,json=newCountryCode,proto3" json:"new_country_code,omitempty"` - AdminId uint64 `protobuf:"varint,4,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + OldCountryCode string `protobuf:"bytes,2,opt,name=old_country_code,json=oldCountryCode,proto3" json:"old_country_code,omitempty"` + NewCountryCode string `protobuf:"bytes,3,opt,name=new_country_code,json=newCountryCode,proto3" json:"new_country_code,omitempty"` + AdminId uint64 `protobuf:"varint,4,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminRenameOwnerCountryCodeRequest) Reset() { @@ -4365,13 +4316,12 @@ func (x *AdminRenameOwnerCountryCodeRequest) GetAdminId() uint64 { } type AdminRenameOwnerCountryCodeResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RoomListEntries int64 `protobuf:"varint,1,opt,name=room_list_entries,json=roomListEntries,proto3" json:"room_list_entries,omitempty"` - RoomSnapshots int64 `protobuf:"varint,2,opt,name=room_snapshots,json=roomSnapshots,proto3" json:"room_snapshots,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + RoomListEntries int64 `protobuf:"varint,1,opt,name=room_list_entries,json=roomListEntries,proto3" json:"room_list_entries,omitempty"` + RoomSnapshots int64 `protobuf:"varint,2,opt,name=room_snapshots,json=roomSnapshots,proto3" json:"room_snapshots,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 *AdminRenameOwnerCountryCodeResponse) Reset() { @@ -4426,12 +4376,11 @@ func (x *AdminRenameOwnerCountryCodeResponse) GetServerTimeMs() int64 { } type AdminFilterAvailableRoomRobotsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + UserIds []int64 `protobuf:"varint,2,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - UserIds []int64 `protobuf:"varint,2,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AdminFilterAvailableRoomRobotsRequest) Reset() { @@ -4479,13 +4428,12 @@ func (x *AdminFilterAvailableRoomRobotsRequest) GetUserIds() []int64 { } type AdminFilterAvailableRoomRobotsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AvailableUserIds []int64 `protobuf:"varint,1,rep,packed,name=available_user_ids,json=availableUserIds,proto3" json:"available_user_ids,omitempty"` - OccupiedUserIds []int64 `protobuf:"varint,2,rep,packed,name=occupied_user_ids,json=occupiedUserIds,proto3" json:"occupied_user_ids,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + AvailableUserIds []int64 `protobuf:"varint,1,rep,packed,name=available_user_ids,json=availableUserIds,proto3" json:"available_user_ids,omitempty"` + OccupiedUserIds []int64 `protobuf:"varint,2,rep,packed,name=occupied_user_ids,json=occupiedUserIds,proto3" json:"occupied_user_ids,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 *AdminFilterAvailableRoomRobotsResponse) Reset() { @@ -4541,15 +4489,14 @@ func (x *AdminFilterAvailableRoomRobotsResponse) GetServerTimeMs() int64 { // RoomBanState 表达单个房间 ban 的治理状态。 type RoomBanState struct { - 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"` + 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"` + ExpiresAtMs int64 `protobuf:"varint,4,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RoomBanState) Reset() { @@ -4612,27 +4559,24 @@ func (x *RoomBanState) GetExpiresAtMs() int64 { // RoomSnapshot 把 room-service 对外需要暴露的房间投影集中返回。 type RoomSnapshot struct { - 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"` + 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"` // locked 只表达房间是否需要入房密码;具体密码哈希不对外映射到 HTTP JSON。 Locked bool `protobuf:"varint,19,opt,name=locked,proto3" json:"locked,omitempty"` // rocket 是语音房火箭当前状态;配置物料通过 GetRoomRocket 单独读取,避免快照过大。 @@ -4640,7 +4584,9 @@ type RoomSnapshot struct { // ban_states 保存 ban 的过期边界;ban_user_ids 仍只服务简单集合判断。 BanStates []*RoomBanState `protobuf:"bytes,21,rep,name=ban_states,json=banStates,proto3" json:"ban_states,omitempty"` // online_count 允许 lite 响应不携带 online_users 明细仍保留准确在线人数。 - OnlineCount int32 `protobuf:"varint,22,opt,name=online_count,json=onlineCount,proto3" json:"online_count,omitempty"` + OnlineCount int32 `protobuf:"varint,22,opt,name=online_count,json=onlineCount,proto3" json:"online_count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RoomSnapshot) Reset() { @@ -4823,16 +4769,15 @@ func (x *RoomSnapshot) GetOnlineCount() int32 { // RoomBackgroundImage 是房间维度保存过的背景图素材。 // 保存列表归属于 room-service,当前生效背景仍写入 RoomSnapshot.room_ext["background_url"]。 type RoomBackgroundImage struct { - 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"` + 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 } func (x *RoomBackgroundImage) Reset() { @@ -4908,13 +4853,12 @@ func (x *RoomBackgroundImage) GetUpdatedAtMs() int64 { } type SaveRoomBackgroundRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *SaveRoomBackgroundRequest) Reset() { @@ -4969,12 +4913,11 @@ func (x *SaveRoomBackgroundRequest) GetImageUrl() string { } type SaveRoomBackgroundResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *SaveRoomBackgroundResponse) Reset() { @@ -5022,13 +4965,12 @@ func (x *SaveRoomBackgroundResponse) GetServerTimeMs() int64 { } type ListRoomBackgroundsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListRoomBackgroundsRequest) Reset() { @@ -5083,13 +5025,12 @@ func (x *ListRoomBackgroundsRequest) GetViewerUserId() int64 { } type ListRoomBackgroundsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` 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() { @@ -5144,12 +5085,11 @@ func (x *ListRoomBackgroundsResponse) GetServerTimeMs() int64 { } type SetRoomBackgroundRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *SetRoomBackgroundRequest) Reset() { @@ -5197,13 +5137,12 @@ func (x *SetRoomBackgroundRequest) GetBackgroundId() int64 { } type SetRoomBackgroundResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *SetRoomBackgroundResponse) Reset() { @@ -5261,11 +5200,8 @@ 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 - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + 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 必须非空;当前只作为房间状态字段保存和透出。 @@ -5285,7 +5221,9 @@ type CreateRoomRequest struct { // robot_room 只供内部机器人房间编排器设置;gateway 不接受客户端提交该字段。 RobotRoom bool `protobuf:"varint,10,opt,name=robot_room,json=robotRoom,proto3" json:"robot_room,omitempty"` // robot_user_ids 是该机器人房间允许参与机器人送礼和虚拟上麦的用户集合。 - RobotUserIds []int64 `protobuf:"varint,11,rep,packed,name=robot_user_ids,json=robotUserIds,proto3" json:"robot_user_ids,omitempty"` + RobotUserIds []int64 `protobuf:"varint,11,rep,packed,name=robot_user_ids,json=robotUserIds,proto3" json:"robot_user_ids,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CreateRoomRequest) Reset() { @@ -5397,12 +5335,11 @@ func (x *CreateRoomRequest) GetRobotUserIds() []int64 { // CreateRoomResponse 返回新建后的房间快照。 type CreateRoomResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CreateRoomResponse) Reset() { @@ -5452,15 +5389,14 @@ func (x *CreateRoomResponse) GetRoom() *RoomSnapshot { // UpdateRoomProfileRequest 修改房间展示资料和麦位数量。 // 该命令只允许当前在房间 presence 内的 owner 执行,座位数必须命中后台启用配置。 type UpdateRoomProfileRequest struct { - 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"` + 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 } func (x *UpdateRoomProfileRequest) Reset() { @@ -5530,12 +5466,11 @@ func (x *UpdateRoomProfileRequest) GetSeatCount() int32 { // UpdateRoomProfileResponse 返回修改后的最新房间快照。 type UpdateRoomProfileResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UpdateRoomProfileResponse) Reset() { @@ -5584,19 +5519,18 @@ func (x *UpdateRoomProfileResponse) GetRoom() *RoomSnapshot { // JoinRoomRequest 把用户 presence 接入房间业务态。 type RoomEntryVehicleSnapshot struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *RoomEntryVehicleSnapshot) Reset() { @@ -5694,15 +5628,14 @@ func (x *RoomEntryVehicleSnapshot) GetExpiresAtMs() int64 { // RoomUserDisplayProfile 是 gateway 在入口固化的用户展示快照,只服务 IM/UI 兜底。 type RoomUserDisplayProfile struct { - 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"` - Nickname string `protobuf:"bytes,2,opt,name=nickname,proto3" json:"nickname,omitempty"` - Avatar string `protobuf:"bytes,3,opt,name=avatar,proto3" json:"avatar,omitempty"` - DisplayUserId string `protobuf:"bytes,4,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` - PrettyDisplayUserId string `protobuf:"bytes,5,opt,name=pretty_display_user_id,json=prettyDisplayUserId,proto3" json:"pretty_display_user_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Nickname string `protobuf:"bytes,2,opt,name=nickname,proto3" json:"nickname,omitempty"` + Avatar string `protobuf:"bytes,3,opt,name=avatar,proto3" json:"avatar,omitempty"` + DisplayUserId string `protobuf:"bytes,4,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` + PrettyDisplayUserId string `protobuf:"bytes,5,opt,name=pretty_display_user_id,json=prettyDisplayUserId,proto3" json:"pretty_display_user_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RoomUserDisplayProfile) Reset() { @@ -5771,12 +5704,9 @@ func (x *RoomUserDisplayProfile) GetPrettyDisplayUserId() string { } type JoinRoomRequest struct { - 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"` + 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"` @@ -5791,6 +5721,8 @@ type JoinRoomRequest struct { // presence_recovery 只用于客户端仍在房间但业务 presence 已超时清理的恢复。 // 恢复成功只补回 Room Cell 在线状态,不发布 RoomUserJoined IM/outbox,避免重复入场表现和统计。 PresenceRecovery bool `protobuf:"varint,10,opt,name=presence_recovery,json=presenceRecovery,proto3" json:"presence_recovery,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *JoinRoomRequest) Reset() { @@ -5896,14 +5828,13 @@ func (x *JoinRoomRequest) GetPresenceRecovery() bool { // RoomEffectiveVipSnapshot 是 room-service 在进房时从 wallet-service 固化的轻量 VIP 展示事实。 // 权益执行仍以后端 effective_benefits 为准,客户端不能用该快照自行声明房间权限。 type RoomEffectiveVipSnapshot struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ProgramType string `protobuf:"bytes,1,opt,name=program_type,json=programType,proto3" json:"program_type,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"` - RoomEntryNoticeEnabled bool `protobuf:"varint,4,opt,name=room_entry_notice_enabled,json=roomEntryNoticeEnabled,proto3" json:"room_entry_notice_enabled,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + ProgramType string `protobuf:"bytes,1,opt,name=program_type,json=programType,proto3" json:"program_type,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"` + RoomEntryNoticeEnabled bool `protobuf:"varint,4,opt,name=room_entry_notice_enabled,json=roomEntryNoticeEnabled,proto3" json:"room_entry_notice_enabled,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RoomEffectiveVipSnapshot) Reset() { @@ -5966,14 +5897,13 @@ func (x *RoomEffectiveVipSnapshot) GetRoomEntryNoticeEnabled() bool { // JoinRoomResponse 返回加入后的房间快照。 type JoinRoomResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + EffectiveVip *RoomEffectiveVipSnapshot `protobuf:"bytes,4,opt,name=effective_vip,json=effectiveVip,proto3" json:"effective_vip,omitempty"` 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"` - EffectiveVip *RoomEffectiveVipSnapshot `protobuf:"bytes,4,opt,name=effective_vip,json=effectiveVip,proto3" json:"effective_vip,omitempty"` + sizeCache protoimpl.SizeCache } func (x *JoinRoomResponse) Reset() { @@ -6037,11 +5967,10 @@ func (x *JoinRoomResponse) GetEffectiveVip() *RoomEffectiveVipSnapshot { // RoomHeartbeatRequest 显式刷新已经存在的房间业务 presence。 // 它不能替代 JoinRoom;用户不在房间时必须拒绝,避免心跳把已离开的用户重新加入房间。 type RoomHeartbeatRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RoomHeartbeatRequest) Reset() { @@ -6083,13 +6012,12 @@ func (x *RoomHeartbeatRequest) GetMeta() *RequestMeta { // RoomHeartbeatResponse 返回刷新后的用户 presence 和房间快照。 type RoomHeartbeatResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *RoomHeartbeatResponse) Reset() { @@ -6145,11 +6073,10 @@ func (x *RoomHeartbeatResponse) GetRoom() *RoomSnapshot { // LeaveRoomRequest 把用户从房间 presence 移出。 type LeaveRoomRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + sizeCache protoimpl.SizeCache } func (x *LeaveRoomRequest) Reset() { @@ -6191,12 +6118,11 @@ func (x *LeaveRoomRequest) GetMeta() *RequestMeta { // LeaveRoomResponse 返回离房后的房间快照。 type LeaveRoomResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + sizeCache protoimpl.SizeCache } func (x *LeaveRoomResponse) Reset() { @@ -6245,12 +6171,11 @@ func (x *LeaveRoomResponse) GetRoom() *RoomSnapshot { // CloseRoomRequest 关闭房间并清理业务 presence 和麦位。 type CloseRoomRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CloseRoomRequest) Reset() { @@ -6299,12 +6224,11 @@ func (x *CloseRoomRequest) GetReason() string { // CloseRoomResponse 返回关闭后的房间快照。 type CloseRoomResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CloseRoomResponse) Reset() { @@ -6353,29 +6277,28 @@ func (x *CloseRoomResponse) GetRoom() *RoomSnapshot { // AdminRoomListItem 是后台房间管理卡片;它来自 room-service owner 读模型,不允许后台直连房间库。 type AdminRoomListItem struct { - 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"` + 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 } func (x *AdminRoomListItem) Reset() { @@ -6542,19 +6465,18 @@ func (x *AdminRoomListItem) GetUpdatedAtMs() int64 { } type AdminListRoomsRequest struct { - 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"` + 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 } func (x *AdminListRoomsRequest) Reset() { @@ -6651,13 +6573,12 @@ func (x *AdminListRoomsRequest) GetOwnerUserId() int64 { } type AdminListRoomsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminListRoomsResponse) Reset() { @@ -6712,12 +6633,11 @@ func (x *AdminListRoomsResponse) GetServerTimeMs() int64 { } type AdminGetRoomRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminGetRoomRequest) Reset() { @@ -6765,12 +6685,11 @@ func (x *AdminGetRoomRequest) GetRoomId() string { } type AdminGetRoomResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminGetRoomResponse) Reset() { @@ -6818,22 +6737,21 @@ func (x *AdminGetRoomResponse) GetServerTimeMs() int64 { } type AdminUpdateRoomRequest struct { - 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"` + 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"` // owner_country_code 是内部运维/同步字段,用于通过真实 Room Cell owner 修复房主国家投影。 OwnerCountryCode *string `protobuf:"bytes,11,opt,name=owner_country_code,json=ownerCountryCode,proto3,oneof" json:"owner_country_code,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminUpdateRoomRequest) Reset() { @@ -6944,12 +6862,11 @@ func (x *AdminUpdateRoomRequest) GetOwnerCountryCode() string { } type AdminUpdateRoomResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AdminUpdateRoomResponse) Reset() { @@ -6997,13 +6914,12 @@ func (x *AdminUpdateRoomResponse) GetRoom() *RoomSnapshot { } type AdminDeleteRoomRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminDeleteRoomRequest) Reset() { @@ -7058,12 +6974,11 @@ func (x *AdminDeleteRoomRequest) GetAdminName() string { } type AdminDeleteRoomResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AdminDeleteRoomResponse) Reset() { @@ -7112,14 +7027,13 @@ func (x *AdminDeleteRoomResponse) GetRoom() *RoomSnapshot { // MicUpRequest 申请把用户放到指定麦位。 type MicUpRequest struct { - 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"` + 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"` // target_display_profile 是上麦用户展示快照,room-service 只透传到麦位 IM/outbox。 TargetDisplayProfile *RoomUserDisplayProfile `protobuf:"bytes,3,opt,name=target_display_profile,json=targetDisplayProfile,proto3" json:"target_display_profile,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *MicUpRequest) Reset() { @@ -7175,15 +7089,14 @@ func (x *MicUpRequest) GetTargetDisplayProfile() *RoomUserDisplayProfile { // MicUpResponse 返回最新房间快照与目标麦位。 type MicUpResponse struct { - 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"` + 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 } func (x *MicUpResponse) Reset() { @@ -7253,16 +7166,15 @@ func (x *MicUpResponse) GetPublishDeadlineMs() int64 { // MicDownRequest 把用户从当前麦位移下。 type MicDownRequest struct { - 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"` + 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"` // target_display_profile 只用于补偿 IM 展示,空值不影响下麦状态提交。 TargetDisplayProfile *RoomUserDisplayProfile `protobuf:"bytes,4,opt,name=target_display_profile,json=targetDisplayProfile,proto3" json:"target_display_profile,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *MicDownRequest) Reset() { @@ -7325,13 +7237,12 @@ func (x *MicDownRequest) GetTargetDisplayProfile() *RoomUserDisplayProfile { // MicDownResponse 返回最新房间快照与目标麦位。 type MicDownResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *MicDownResponse) Reset() { @@ -7387,15 +7298,14 @@ func (x *MicDownResponse) GetRoom() *RoomSnapshot { // ChangeMicSeatRequest 直接调整指定用户所在麦位。 type ChangeMicSeatRequest struct { - 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"` + 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"` // target_display_profile 是被换麦用户展示快照,避免客户端等待在线成员刷新。 TargetDisplayProfile *RoomUserDisplayProfile `protobuf:"bytes,4,opt,name=target_display_profile,json=targetDisplayProfile,proto3" json:"target_display_profile,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ChangeMicSeatRequest) Reset() { @@ -7458,12 +7368,11 @@ func (x *ChangeMicSeatRequest) GetTargetDisplayProfile() *RoomUserDisplayProfile // ChangeMicSeatResponse 返回变更后的房间快照。 type ChangeMicSeatResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ChangeMicSeatResponse) Reset() { @@ -7513,11 +7422,8 @@ 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 - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + 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"` @@ -7526,6 +7432,8 @@ type ConfirmMicPublishingRequest struct { Source string `protobuf:"bytes,6,opt,name=source,proto3" json:"source,omitempty"` // target_display_profile 是确认发流用户展示快照,空值不影响状态收敛。 TargetDisplayProfile *RoomUserDisplayProfile `protobuf:"bytes,7,opt,name=target_display_profile,json=targetDisplayProfile,proto3" json:"target_display_profile,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ConfirmMicPublishingRequest) Reset() { @@ -7609,13 +7517,12 @@ func (x *ConfirmMicPublishingRequest) GetTargetDisplayProfile() *RoomUserDisplay // ConfirmMicPublishingResponse 返回确认后的最新房间快照。 type ConfirmMicPublishingResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ConfirmMicPublishingResponse) Reset() { @@ -7671,15 +7578,14 @@ func (x *ConfirmMicPublishingResponse) GetRoom() *RoomSnapshot { // MicHeartbeatRequest 刷新当前 publishing 麦位会话的服务端麦上心跳。 type MicHeartbeatRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + 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"` + 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() { @@ -7735,14 +7641,13 @@ func (x *MicHeartbeatRequest) GetMicSessionId() string { // MicHeartbeatResponse 返回刷新后的麦位和房间快照。 type MicHeartbeatResponse struct { - 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"` + 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() { @@ -7805,16 +7710,15 @@ func (x *MicHeartbeatResponse) GetMicHeartbeatAtMs() int64 { // SetMicMuteRequest 修改麦位上的服务端可见静音态。 type SetMicMuteRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + 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"` // target_display_profile 是被静音状态变更用户展示快照,只服务 IM/UI 兜底。 TargetDisplayProfile *RoomUserDisplayProfile `protobuf:"bytes,4,opt,name=target_display_profile,json=targetDisplayProfile,proto3" json:"target_display_profile,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SetMicMuteRequest) Reset() { @@ -7877,13 +7781,12 @@ func (x *SetMicMuteRequest) GetTargetDisplayProfile() *RoomUserDisplayProfile { // SetMicMuteResponse 返回静音态变更后的最新房间快照。 type SetMicMuteResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *SetMicMuteResponse) Reset() { @@ -7940,17 +7843,16 @@ func (x *SetMicMuteResponse) GetRoom() *RoomSnapshot { // ApplyRTCEventRequest 把可信 RTC 服务端回调转换成 Room Cell 命令。 // event_type 当前只接受 audio_started、audio_stopped、room_exited。 type ApplyRTCEventRequest struct { - 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"` + 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 } func (x *ApplyRTCEventRequest) Reset() { @@ -8034,13 +7936,12 @@ func (x *ApplyRTCEventRequest) GetExternalEventId() string { // ApplyRTCEventResponse 返回 RTC 事件落房间状态后的快照。 type ApplyRTCEventResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ApplyRTCEventResponse) Reset() { @@ -8096,13 +7997,12 @@ func (x *ApplyRTCEventResponse) GetRoom() *RoomSnapshot { // SetMicSeatLockRequest 锁定或解锁指定麦位。 type SetMicSeatLockRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *SetMicSeatLockRequest) Reset() { @@ -8158,12 +8058,11 @@ func (x *SetMicSeatLockRequest) GetLocked() bool { // SetMicSeatLockResponse 返回锁麦后的最新房间快照。 type SetMicSeatLockResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SetMicSeatLockResponse) Reset() { @@ -8212,12 +8111,11 @@ func (x *SetMicSeatLockResponse) GetRoom() *RoomSnapshot { // SetChatEnabledRequest 开启或关闭房间公屏。 type SetChatEnabledRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SetChatEnabledRequest) Reset() { @@ -8266,12 +8164,11 @@ func (x *SetChatEnabledRequest) GetEnabled() bool { // SetChatEnabledResponse 返回聊天开关变更后的最新房间快照。 type SetChatEnabledResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SetChatEnabledResponse) Reset() { @@ -8321,13 +8218,12 @@ func (x *SetChatEnabledResponse) GetRoom() *RoomSnapshot { // SetRoomPasswordRequest 设置或清空房间入房密码。 // locked=true 时 password 必须非空;locked=false 表示清空密码并解除锁房。 type SetRoomPasswordRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *SetRoomPasswordRequest) Reset() { @@ -8383,12 +8279,11 @@ func (x *SetRoomPasswordRequest) GetPassword() string { // SetRoomPasswordResponse 返回锁房状态变更后的最新房间快照。 type SetRoomPasswordResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SetRoomPasswordResponse) Reset() { @@ -8437,13 +8332,12 @@ func (x *SetRoomPasswordResponse) GetRoom() *RoomSnapshot { // SetRoomAdminRequest 添加或移除房间管理员。 type SetRoomAdminRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *SetRoomAdminRequest) Reset() { @@ -8499,12 +8393,11 @@ func (x *SetRoomAdminRequest) GetEnabled() bool { // SetRoomAdminResponse 返回管理员集合变更后的最新房间快照。 type SetRoomAdminResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SetRoomAdminResponse) Reset() { @@ -8553,13 +8446,12 @@ func (x *SetRoomAdminResponse) GetRoom() *RoomSnapshot { // MuteUserRequest 修改房间内禁言态。 type MuteUserRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *MuteUserRequest) Reset() { @@ -8615,12 +8507,11 @@ func (x *MuteUserRequest) GetMuted() bool { // MuteUserResponse 返回最新房间快照。 type MuteUserResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + sizeCache protoimpl.SizeCache } func (x *MuteUserResponse) Reset() { @@ -8669,14 +8560,13 @@ func (x *MuteUserResponse) GetRoom() *RoomSnapshot { // KickUserRequest 把指定用户踢出房间。 type KickUserRequest struct { - 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"` + 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"` + DurationMs int64 `protobuf:"varint,3,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *KickUserRequest) Reset() { @@ -8732,16 +8622,15 @@ func (x *KickUserRequest) GetDurationMs() int64 { // KickUserResponse 返回最新房间快照。 type KickUserResponse struct { - 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"` + 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"` // 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"` + RtcKickError string `protobuf:"bytes,4,opt,name=rtc_kick_error,json=rtcKickError,proto3" json:"rtc_kick_error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *KickUserResponse) Reset() { @@ -8804,12 +8693,11 @@ func (x *KickUserResponse) GetRtcKickError() string { // UnbanUserRequest 解除房间内 ban,用户仍需重新 JoinRoom。 type UnbanUserRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *UnbanUserRequest) Reset() { @@ -8858,12 +8746,11 @@ func (x *UnbanUserRequest) GetTargetUserId() int64 { // UnbanUserResponse 返回解封后的最新房间快照。 type UnbanUserResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UnbanUserResponse) Reset() { @@ -8913,16 +8800,15 @@ func (x *UnbanUserResponse) GetRoom() *RoomSnapshot { // SystemEvictUserRequest 是平台级封禁、风控或后台治理触发的系统驱逐入口。 // 该命令仍由 Room Cell 修改房间状态;调用方不能直接写房间 presence 或麦位。 type SystemEvictUserRequest struct { - 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"` + 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"` + BanFromRoom bool `protobuf:"varint,5,opt,name=ban_from_room,json=banFromRoom,proto3" json:"ban_from_room,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SystemEvictUserRequest) Reset() { @@ -8992,16 +8878,15 @@ func (x *SystemEvictUserRequest) GetBanFromRoom() bool { // SystemEvictUserResponse 返回系统驱逐的房间状态和外部 RTC 副作用结果。 type SystemEvictUserResponse struct { - 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"` + 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 } func (x *SystemEvictUserResponse) Reset() { @@ -9078,17 +8963,16 @@ func (x *SystemEvictUserResponse) GetRtcKickError() string { // SendGiftTargetHostScope 是 gateway 在送礼入口按每个接收方固化的主播工资入账快照。 type SendGiftTargetHostScope struct { - 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"` + state protoimpl.MessageState `protogen:"open.v1"` + TargetUserId int64 `protobuf:"varint,1,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` // target_is_host 由 gateway 根据 user-service active host profile 注入,客户端不能直接声明。 TargetIsHost bool `protobuf:"varint,2,opt,name=target_is_host,json=targetIsHost,proto3" json:"target_is_host,omitempty"` // target_host_region_id 是主播所属区域,后续结算按该区域匹配 Host & Agency 政策。 TargetHostRegionId int64 `protobuf:"varint,3,opt,name=target_host_region_id,json=targetHostRegionId,proto3" json:"target_host_region_id,omitempty"` // target_agency_owner_user_id 是送礼瞬间主播上级代理收款用户;为空表示当前无代理或代理关系不可结算。 TargetAgencyOwnerUserId int64 `protobuf:"varint,4,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 *SendGiftTargetHostScope) Reset() { @@ -9152,15 +9036,14 @@ func (x *SendGiftTargetHostScope) GetTargetAgencyOwnerUserId() int64 { // SendGiftDisplayProfile 是 gateway 在送礼入口固化的轻量展示快照。 // room-service 只把它写入事件和 IM,不把用户资料扩散到 Room Cell 核心状态。 type SendGiftDisplayProfile struct { - 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"` - Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` - Avatar string `protobuf:"bytes,3,opt,name=avatar,proto3" json:"avatar,omitempty"` - DisplayUserId string `protobuf:"bytes,4,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` - PrettyDisplayUserId string `protobuf:"bytes,5,opt,name=pretty_display_user_id,json=prettyDisplayUserId,proto3" json:"pretty_display_user_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` + Avatar string `protobuf:"bytes,3,opt,name=avatar,proto3" json:"avatar,omitempty"` + DisplayUserId string `protobuf:"bytes,4,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` + PrettyDisplayUserId string `protobuf:"bytes,5,opt,name=pretty_display_user_id,json=prettyDisplayUserId,proto3" json:"pretty_display_user_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SendGiftDisplayProfile) Reset() { @@ -9231,21 +9114,20 @@ func (x *SendGiftDisplayProfile) GetPrettyDisplayUserId() string { // SendGiftBatchTarget 是批量送礼展示响应中单个目标的结算和展示快照。 // 它只服务发送方本地即时展示,不替代逐目标 RoomGiftSent 业务事实。 type SendGiftBatchTarget struct { - 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"` - ReceiverNickname string `protobuf:"bytes,2,opt,name=receiver_nickname,json=receiverNickname,proto3" json:"receiver_nickname,omitempty"` - ReceiverAvatar string `protobuf:"bytes,3,opt,name=receiver_avatar,json=receiverAvatar,proto3" json:"receiver_avatar,omitempty"` - ReceiverDisplayUserId string `protobuf:"bytes,4,opt,name=receiver_display_user_id,json=receiverDisplayUserId,proto3" json:"receiver_display_user_id,omitempty"` - ReceiverPrettyDisplayUserId string `protobuf:"bytes,5,opt,name=receiver_pretty_display_user_id,json=receiverPrettyDisplayUserId,proto3" json:"receiver_pretty_display_user_id,omitempty"` - GiftValue int64 `protobuf:"varint,6,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` - TargetGiftValue int64 `protobuf:"varint,7,opt,name=target_gift_value,json=targetGiftValue,proto3" json:"target_gift_value,omitempty"` - CoinSpent int64 `protobuf:"varint,8,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` - BillingReceiptId string `protobuf:"bytes,9,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` - CommandId string `protobuf:"bytes,10,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - LuckyGift *LuckyGiftDrawResult `protobuf:"bytes,11,opt,name=lucky_gift,json=luckyGift,proto3" json:"lucky_gift,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + TargetUserId int64 `protobuf:"varint,1,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + ReceiverNickname string `protobuf:"bytes,2,opt,name=receiver_nickname,json=receiverNickname,proto3" json:"receiver_nickname,omitempty"` + ReceiverAvatar string `protobuf:"bytes,3,opt,name=receiver_avatar,json=receiverAvatar,proto3" json:"receiver_avatar,omitempty"` + ReceiverDisplayUserId string `protobuf:"bytes,4,opt,name=receiver_display_user_id,json=receiverDisplayUserId,proto3" json:"receiver_display_user_id,omitempty"` + ReceiverPrettyDisplayUserId string `protobuf:"bytes,5,opt,name=receiver_pretty_display_user_id,json=receiverPrettyDisplayUserId,proto3" json:"receiver_pretty_display_user_id,omitempty"` + GiftValue int64 `protobuf:"varint,6,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` + TargetGiftValue int64 `protobuf:"varint,7,opt,name=target_gift_value,json=targetGiftValue,proto3" json:"target_gift_value,omitempty"` + CoinSpent int64 `protobuf:"varint,8,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` + BillingReceiptId string `protobuf:"bytes,9,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` + CommandId string `protobuf:"bytes,10,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + LuckyGift *LuckyGiftDrawResult `protobuf:"bytes,11,opt,name=lucky_gift,json=luckyGift,proto3" json:"lucky_gift,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SendGiftBatchTarget) Reset() { @@ -9358,10 +9240,7 @@ func (x *SendGiftBatchTarget) GetLuckyGift() *LuckyGiftDrawResult { // SendGiftBatchDisplay 是新批量送礼接口返回给发送方的本地展示协议。 // 房间广播使用同构的 RoomGiftBatchSent IM 事件;coin_balance_after 不进入该展示对象。 type SendGiftBatchDisplay struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` EventId string `protobuf:"bytes,1,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"` SenderUserId int64 `protobuf:"varint,2,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` SenderName string `protobuf:"bytes,3,opt,name=sender_name,json=senderName,proto3" json:"sender_name,omitempty"` @@ -9384,6 +9263,8 @@ type SendGiftBatchDisplay struct { TargetUserIds []int64 `protobuf:"varint,20,rep,packed,name=target_user_ids,json=targetUserIds,proto3" json:"target_user_ids,omitempty"` Targets []*SendGiftBatchTarget `protobuf:"bytes,21,rep,name=targets,proto3" json:"targets,omitempty"` CommandId string `protobuf:"bytes,22,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SendGiftBatchDisplay) Reset() { @@ -9572,11 +9453,8 @@ func (x *SendGiftBatchDisplay) GetCommandId() string { // SendGiftRequest 是首版房间内最重要的变现命令。 type SendGiftRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + 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"` @@ -9613,6 +9491,8 @@ type SendGiftRequest struct { // sender_registered_at_ms 是 gateway 从 user-service 读取的账号创建事实;客户端不能提交或覆盖。 // room-service 只随首次送礼命令持久化并透传给 lucky-gift-service,不据此拥有用户主数据。 SenderRegisteredAtMs int64 `protobuf:"varint,21,opt,name=sender_registered_at_ms,json=senderRegisteredAtMs,proto3" json:"sender_registered_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SendGiftRequest) Reset() { @@ -9794,16 +9674,13 @@ func (x *SendGiftRequest) GetSenderRegisteredAtMs() int64 { // SendGiftResponse 返回扣费成功并落到房间后的状态结果。 type SendGiftResponse struct { - 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"` + 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"` // lucky_gift 是本次送礼的聚合幸运礼物结果;多目标时倍率和返奖金额按所有目标累加。 LuckyGift *LuckyGiftDrawResult `protobuf:"bytes,7,opt,name=lucky_gift,json=luckyGift,proto3" json:"lucky_gift,omitempty"` // lucky_gifts 是每个收礼目标的独立抽奖结果;多目标客户端用 target_user_id 对齐明细表现。 @@ -9815,7 +9692,9 @@ type SendGiftResponse struct { // batch_display 是新 batch-send 接口的多人展示快照;旧 send 入口保持空值。 BatchDisplay *SendGiftBatchDisplay `protobuf:"bytes,11,opt,name=batch_display,json=batchDisplay,proto3" json:"batch_display,omitempty"` // v2 保存并重放首次成功的原始结算结果;追加字段不改变旧 Flutter 对顶层 V1 字段的读取。 - V2 *SendGiftResultV2 `protobuf:"bytes,12,opt,name=v2,proto3" json:"v2,omitempty"` + V2 *SendGiftResultV2 `protobuf:"bytes,12,opt,name=v2,proto3" json:"v2,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SendGiftResponse) Reset() { @@ -9934,13 +9813,12 @@ func (x *SendGiftResponse) GetV2() *SendGiftResultV2 { // CheckSpeakPermissionRequest 让腾讯云 IM 发言回调或 gateway 在公屏前同步问房间业务态。 type CheckSpeakPermissionRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *CheckSpeakPermissionRequest) Reset() { @@ -9996,13 +9874,12 @@ func (x *CheckSpeakPermissionRequest) GetAppCode() string { // CheckSpeakPermissionResponse 返回当前用户是否允许发言。 type CheckSpeakPermissionResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *CheckSpeakPermissionResponse) Reset() { @@ -10058,15 +9935,14 @@ func (x *CheckSpeakPermissionResponse) GetRoomVersion() int64 { // VerifyRoomPresenceRequest 让外部 IM 入口在进群前确认用户业务上仍在房间内。 type VerifyRoomPresenceRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *VerifyRoomPresenceRequest) Reset() { @@ -10136,13 +10012,12 @@ func (x *VerifyRoomPresenceRequest) GetAppCode() string { // VerifyRoomPresenceResponse 返回用户是否仍然属于该房间。 type VerifyRoomPresenceResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *VerifyRoomPresenceResponse) Reset() { @@ -10199,12 +10074,11 @@ func (x *VerifyRoomPresenceResponse) GetRoomVersion() int64 { // ResolveRoomAppCodeRequest 仅供已验签的三方回调按全局 room_id 解析租户。 // 该入口不接受客户端 app_code,避免固定 URL 参数把 Fami 事件错误路由到 Lalu。 type ResolveRoomAppCodeRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` unknownFields protoimpl.UnknownFields - - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ResolveRoomAppCodeRequest) Reset() { @@ -10252,11 +10126,10 @@ func (x *ResolveRoomAppCodeRequest) GetRoomId() string { } type ResolveRoomAppCodeResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` unknownFields protoimpl.UnknownFields - - AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ResolveRoomAppCodeResponse) Reset() { @@ -10300,17 +10173,14 @@ func (x *ResolveRoomAppCodeResponse) GetAppCode() string { // visible_region_id 是 gateway 解析的实际查询区域:默认取 viewer 区域,显式筛选时取已校验的 filter_region_id。 // gateway 同时写 filter_region_id 绑定游标;客户端不能直接构造任一内部字段。 type ListRoomsRequest struct { - 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"` + 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"` // country_code 是可选国家筛选值;gateway 必须先确认它属于 active 区域。 CountryCode string `protobuf:"bytes,8,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` // viewer_country_code 是当前用户国家,用于 All/区域列表的本国家优先排序。 @@ -10319,6 +10189,8 @@ type ListRoomsRequest struct { AllVisibleRegions bool `protobuf:"varint,10,opt,name=all_visible_regions,json=allVisibleRegions,proto3" json:"all_visible_regions,omitempty"` // filter_region_id 是 gateway 校验过的 active 区域筛选;它与 all_visible_regions/country_code 互斥。 FilterRegionId int64 `protobuf:"varint,11,opt,name=filter_region_id,json=filterRegionId,proto3" json:"filter_region_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListRoomsRequest) Reset() { @@ -10431,17 +10303,16 @@ func (x *ListRoomsRequest) GetFilterRegionId() int64 { // ListRoomsByOwnersRequest 查询一组房主名下 active 房间。 // owner_user_ids 必须由 gateway 根据上游业务归属注入,客户端不能直接提交任意房主集合。 type ListRoomsByOwnersRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + OwnerUserIds []int64 `protobuf:"varint,3,rep,packed,name=owner_user_ids,json=ownerUserIds,proto3" json:"owner_user_ids,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 - - 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"` - OwnerUserIds []int64 `protobuf:"varint,3,rep,packed,name=owner_user_ids,json=ownerUserIds,proto3" json:"owner_user_ids,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"` + sizeCache protoimpl.SizeCache } func (x *ListRoomsByOwnersRequest) Reset() { @@ -10526,19 +10397,18 @@ func (x *ListRoomsByOwnersRequest) GetQuery() string { // ListRoomFeedsRequest 查询 Mine 页 visited/friend/following/followed 房间流。 // 它和公共房间发现列表分离,避免把用户关系流误建模成房间全集过滤。 type ListRoomFeedsRequest struct { - 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"` + 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"` + RelatedUsers []*RoomFeedRelatedUser `protobuf:"bytes,8,rep,name=related_users,json=relatedUsers,proto3" json:"related_users,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListRoomFeedsRequest) Reset() { @@ -10629,14 +10499,13 @@ func (x *ListRoomFeedsRequest) GetRelatedUsers() []*RoomFeedRelatedUser { // ListRoomGiftLeaderboardRequest 查询当前 UTC 周期内的房间金币消耗榜。 type ListRoomGiftLeaderboardRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListRoomGiftLeaderboardRequest) Reset() { @@ -10699,12 +10568,11 @@ func (x *ListRoomGiftLeaderboardRequest) GetPageSize() int32 { // RoomFeedRelatedUser 是 Mine 关系房间流的排序输入,不让 room-service 持有好友/关注事实。 type RoomFeedRelatedUser struct { - 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"` + 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 } func (x *RoomFeedRelatedUser) Reset() { @@ -10753,25 +10621,24 @@ func (x *RoomFeedRelatedUser) GetRelationUpdatedAtMs() int64 { // RoomListItem 是房间发现页卡片读模型,不承载完整 Room Cell 状态。 type RoomListItem struct { - 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"` - CountryCode string `protobuf:"bytes,16,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` + 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"` + CountryCode string `protobuf:"bytes,16,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RoomListItem) Reset() { @@ -10911,12 +10778,11 @@ func (x *RoomListItem) GetCountryCode() string { // ListRoomsResponse 返回一页房间卡片和下一页不透明 cursor。 type ListRoomsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListRoomsResponse) Reset() { @@ -10965,14 +10831,13 @@ func (x *ListRoomsResponse) GetNextCursor() string { // RoomGiftLeaderboardItem 是跨房间金币消耗榜卡片;score 只表达该周期房间礼物金币消耗。 type RoomGiftLeaderboardItem struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *RoomGiftLeaderboardItem) Reset() { @@ -11035,16 +10900,15 @@ func (x *RoomGiftLeaderboardItem) GetRoom() *RoomListItem { // ListRoomGiftLeaderboardResponse 返回当前 UTC 周期房间金币榜。 type ListRoomGiftLeaderboardResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListRoomGiftLeaderboardResponse) Reset() { @@ -11121,15 +10985,14 @@ func (x *ListRoomGiftLeaderboardResponse) GetServerTimeMs() int64 { // ListRoomContributionRankRequest 查询单房间内用户送礼贡献周期榜。 type ListRoomContributionRankRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + Period string `protobuf:"bytes,3,opt,name=period,proto3" json:"period,omitempty"` + Limit int32 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"` + ViewerUserId int64 `protobuf:"varint,5,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` 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"` - Period string `protobuf:"bytes,3,opt,name=period,proto3" json:"period,omitempty"` - Limit int32 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"` - ViewerUserId int64 `protobuf:"varint,5,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListRoomContributionRankRequest) Reset() { @@ -11199,17 +11062,16 @@ func (x *ListRoomContributionRankRequest) GetViewerUserId() int64 { // ListRoomContributionRankResponse 返回单房间内用户送礼贡献周期榜。 type ListRoomContributionRankResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + Period string `protobuf:"bytes,2,opt,name=period,proto3" json:"period,omitempty"` + StartAtMs int64 `protobuf:"varint,3,opt,name=start_at_ms,json=startAtMs,proto3" json:"start_at_ms,omitempty"` + EndAtMs int64 `protobuf:"varint,4,opt,name=end_at_ms,json=endAtMs,proto3" json:"end_at_ms,omitempty"` + Items []*RoomContributionRankItem `protobuf:"bytes,5,rep,name=items,proto3" json:"items,omitempty"` + Total int64 `protobuf:"varint,6,opt,name=total,proto3" json:"total,omitempty"` + ServerTimeMs int64 `protobuf:"varint,7,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` unknownFields protoimpl.UnknownFields - - RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - Period string `protobuf:"bytes,2,opt,name=period,proto3" json:"period,omitempty"` - StartAtMs int64 `protobuf:"varint,3,opt,name=start_at_ms,json=startAtMs,proto3" json:"start_at_ms,omitempty"` - EndAtMs int64 `protobuf:"varint,4,opt,name=end_at_ms,json=endAtMs,proto3" json:"end_at_ms,omitempty"` - Items []*RoomContributionRankItem `protobuf:"bytes,5,rep,name=items,proto3" json:"items,omitempty"` - Total int64 `protobuf:"varint,6,opt,name=total,proto3" json:"total,omitempty"` - ServerTimeMs int64 `protobuf:"varint,7,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListRoomContributionRankResponse) Reset() { @@ -11294,12 +11156,11 @@ func (x *ListRoomContributionRankResponse) GetServerTimeMs() int64 { // GetMyRoomRequest 查询当前用户自己创建的房间。 // 该查询必须由 gateway 写入鉴权后的 owner_user_id,不能从客户端接收用户 ID。 type GetMyRoomRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetMyRoomRequest) Reset() { @@ -11349,13 +11210,12 @@ func (x *GetMyRoomRequest) GetOwnerUserId() int64 { // GetMyRoomResponse 返回 Mine 顶部“我的房间”权威卡片。 // 它直接读取 rooms 元数据并用 Room Cell 快照补充实时卡片字段,不依赖发现页投影是否已经写入。 type GetMyRoomResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetMyRoomResponse) Reset() { @@ -11412,12 +11272,11 @@ func (x *GetMyRoomResponse) GetServerTimeMs() int64 { // GetCurrentRoomRequest 查询当前用户是否仍有可恢复的房间 presence。 // 该查询必须由 gateway 写入鉴权后的 user_id,客户端不能提交 user_id。 type GetCurrentRoomRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetCurrentRoomRequest) Reset() { @@ -11467,19 +11326,18 @@ func (x *GetCurrentRoomRequest) GetUserId() int64 { // GetCurrentRoomResponse 是 App 启动、回前台和网络恢复时的房间恢复探测结果。 // 它只表达是否需要恢复,不会隐式 JoinRoom 或刷新 presence。 type GetCurrentRoomResponse struct { - 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"` + 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 } func (x *GetCurrentRoomResponse) Reset() { @@ -11578,13 +11436,12 @@ func (x *GetCurrentRoomResponse) GetServerTimeMs() int64 { // GetRoomSnapshotRequest 主动读取当前房间完整快照。 // 该查询必须由 gateway 写入鉴权后的 viewer_user_id,客户端不能提交 viewer_user_id。 type GetRoomSnapshotRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetRoomSnapshotRequest) Reset() { @@ -11640,14 +11497,13 @@ func (x *GetRoomSnapshotRequest) GetViewerUserId() int64 { // GetRoomSnapshotResponse 返回 Room Cell 当前快照;只读,不刷新 presence。 type GetRoomSnapshotResponse struct { - 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"` + 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"` + IsFollowed bool `protobuf:"varint,3,opt,name=is_followed,json=isFollowed,proto3" json:"is_followed,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GetRoomSnapshotResponse) Reset() { @@ -11704,13 +11560,12 @@ func (x *GetRoomSnapshotResponse) GetIsFollowed() bool { // GetRoomRocketRequest 主动读取当前房间火箭配置物料和进度状态。 // 该查询必须由 gateway 写入鉴权后的 viewer_user_id,客户端不能提交 viewer_user_id。 type GetRoomRocketRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetRoomRocketRequest) Reset() { @@ -11765,12 +11620,11 @@ func (x *GetRoomRocketRequest) GetViewerUserId() int64 { } type GetRoomRocketResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetRoomRocketResponse) Reset() { @@ -11819,16 +11673,15 @@ func (x *GetRoomRocketResponse) GetServerTimeMs() int64 { // ListRoomOnlineUsersRequest 分页查询房间在线用户,不让客户端拉完整 RoomSnapshot 做列表分页。 type ListRoomOnlineUsersRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListRoomOnlineUsersRequest) Reset() { @@ -11904,16 +11757,15 @@ func (x *ListRoomOnlineUsersRequest) GetSort() string { } type ListRoomOnlineUsersResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListRoomOnlineUsersResponse) Reset() { @@ -11990,17 +11842,16 @@ func (x *ListRoomOnlineUsersResponse) GetItems() []*RoomOnlineUser { // RoomBannedUser 是房间黑名单列表的轻量治理读模型;用户展示资料由 gateway 批量补齐。 type RoomBannedUser struct { - 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"` + 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"` + 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 + sizeCache protoimpl.SizeCache } func (x *RoomBannedUser) Reset() { @@ -12077,15 +11928,14 @@ func (x *RoomBannedUser) GetPermanent() bool { // ListRoomBannedUsersRequest 分页查询房间当前仍有效的黑名单。 type ListRoomBannedUsersRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListRoomBannedUsersRequest) Reset() { @@ -12154,15 +12004,14 @@ func (x *ListRoomBannedUsersRequest) GetPageSize() int32 { } type ListRoomBannedUsersResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListRoomBannedUsersResponse) Reset() { @@ -12233,13 +12082,12 @@ func (x *ListRoomBannedUsersResponse) GetServerTimeMs() int64 { // FollowRoomRequest 建立当前用户对房间的关注关系。 // 该关系是 room-service 的用户-房间低频关系事实,不进入 Room Cell command log。 type FollowRoomRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *FollowRoomRequest) Reset() { @@ -12294,14 +12142,13 @@ func (x *FollowRoomRequest) GetUserId() int64 { } type FollowRoomResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *FollowRoomResponse) Reset() { @@ -12364,13 +12211,12 @@ func (x *FollowRoomResponse) GetServerTimeMs() int64 { // UnfollowRoomRequest 取消当前用户对房间的关注关系;未关注时按幂等成功处理。 type UnfollowRoomRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *UnfollowRoomRequest) Reset() { @@ -12425,13 +12271,12 @@ func (x *UnfollowRoomRequest) GetUserId() int64 { } type UnfollowRoomResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *UnfollowRoomResponse) Reset() { @@ -12488,16 +12333,15 @@ func (x *UnfollowRoomResponse) GetServerTimeMs() int64 { // SendGiftLuckyHit 是 V2 微批中需要逐次播放的精简中奖命中。 // 声明追加在文件尾以保持既有 protobuf message index 稳定;字段可在前面的消息中正常引用。 type SendGiftLuckyHit struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - GiftIndex int32 `protobuf:"varint,1,opt,name=gift_index,json=giftIndex,proto3" json:"gift_index,omitempty"` - DrawId string `protobuf:"bytes,2,opt,name=draw_id,json=drawId,proto3" json:"draw_id,omitempty"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - SelectedTierId string `protobuf:"bytes,4,opt,name=selected_tier_id,json=selectedTierId,proto3" json:"selected_tier_id,omitempty"` - MultiplierPpm int64 `protobuf:"varint,5,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` - RewardCoins int64 `protobuf:"varint,6,opt,name=reward_coins,json=rewardCoins,proto3" json:"reward_coins,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + GiftIndex int32 `protobuf:"varint,1,opt,name=gift_index,json=giftIndex,proto3" json:"gift_index,omitempty"` + DrawId string `protobuf:"bytes,2,opt,name=draw_id,json=drawId,proto3" json:"draw_id,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + SelectedTierId string `protobuf:"bytes,4,opt,name=selected_tier_id,json=selectedTierId,proto3" json:"selected_tier_id,omitempty"` + MultiplierPpm int64 `protobuf:"varint,5,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` + RewardCoins int64 `protobuf:"varint,6,opt,name=reward_coins,json=rewardCoins,proto3" json:"reward_coins,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SendGiftLuckyHit) Reset() { @@ -12576,21 +12420,18 @@ func (x *SendGiftLuckyHit) GetRewardCoins() int64 { // 旧客户端继续读取 SendGiftResponse 顶层 V1 字段;V2 客户端只以该对象判断幂等、 // 提交顺序和实际结算数量,避免网络重试时拿“当前房间快照”冒充原始结算结果。 type SendGiftResultV2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ApiVersion int32 `protobuf:"varint,1,opt,name=api_version,json=apiVersion,proto3" json:"api_version,omitempty"` - CommandId string `protobuf:"bytes,2,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - ComboSessionId string `protobuf:"bytes,3,opt,name=combo_session_id,json=comboSessionId,proto3" json:"combo_session_id,omitempty"` - BatchSeq int64 `protobuf:"varint,4,opt,name=batch_seq,json=batchSeq,proto3" json:"batch_seq,omitempty"` - IdempotentReplay bool `protobuf:"varint,5,opt,name=idempotent_replay,json=idempotentReplay,proto3" json:"idempotent_replay,omitempty"` - CommittedRoomVersion int64 `protobuf:"varint,6,opt,name=committed_room_version,json=committedRoomVersion,proto3" json:"committed_room_version,omitempty"` - BillingReceiptId string `protobuf:"bytes,7,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` - CoinBalanceAfter int64 `protobuf:"varint,8,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` - GiftIncomeBalanceAfter int64 `protobuf:"varint,9,opt,name=gift_income_balance_after,json=giftIncomeBalanceAfter,proto3" json:"gift_income_balance_after,omitempty"` - SettledGiftCount int32 `protobuf:"varint,10,opt,name=settled_gift_count,json=settledGiftCount,proto3" json:"settled_gift_count,omitempty"` - SettledTargetUserIds []int64 `protobuf:"varint,11,rep,packed,name=settled_target_user_ids,json=settledTargetUserIds,proto3" json:"settled_target_user_ids,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + ApiVersion int32 `protobuf:"varint,1,opt,name=api_version,json=apiVersion,proto3" json:"api_version,omitempty"` + CommandId string `protobuf:"bytes,2,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + ComboSessionId string `protobuf:"bytes,3,opt,name=combo_session_id,json=comboSessionId,proto3" json:"combo_session_id,omitempty"` + BatchSeq int64 `protobuf:"varint,4,opt,name=batch_seq,json=batchSeq,proto3" json:"batch_seq,omitempty"` + IdempotentReplay bool `protobuf:"varint,5,opt,name=idempotent_replay,json=idempotentReplay,proto3" json:"idempotent_replay,omitempty"` + CommittedRoomVersion int64 `protobuf:"varint,6,opt,name=committed_room_version,json=committedRoomVersion,proto3" json:"committed_room_version,omitempty"` + BillingReceiptId string `protobuf:"bytes,7,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` + CoinBalanceAfter int64 `protobuf:"varint,8,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + GiftIncomeBalanceAfter int64 `protobuf:"varint,9,opt,name=gift_income_balance_after,json=giftIncomeBalanceAfter,proto3" json:"gift_income_balance_after,omitempty"` + SettledGiftCount int32 `protobuf:"varint,10,opt,name=settled_gift_count,json=settledGiftCount,proto3" json:"settled_gift_count,omitempty"` + SettledTargetUserIds []int64 `protobuf:"varint,11,rep,packed,name=settled_target_user_ids,json=settledTargetUserIds,proto3" json:"settled_target_user_ids,omitempty"` // balance_version 是 sender 被扣费资产在该批次完成后的 wallet 账户版本;幂等重放保持首次值。 BalanceVersion int64 `protobuf:"varint,12,opt,name=balance_version,json=balanceVersion,proto3" json:"balance_version,omitempty"` LuckyGift *LuckyGiftDrawResult `protobuf:"bytes,13,opt,name=lucky_gift,json=luckyGift,proto3" json:"lucky_gift,omitempty"` @@ -12601,6 +12442,8 @@ type SendGiftResultV2 struct { GiftRank []*RankItem `protobuf:"bytes,18,rep,name=gift_rank,json=giftRank,proto3" json:"gift_rank,omitempty"` // operation_status 当前成功响应固定为 committed;该字段让 V2 契约可以明确区分未来的异步受理态。 OperationStatus string `protobuf:"bytes,19,opt,name=operation_status,json=operationStatus,proto3" json:"operation_status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SendGiftResultV2) Reset() { @@ -12768,2724 +12611,1186 @@ func (x *SendGiftResultV2) GetOperationStatus() string { var File_proto_room_v1_room_proto protoreflect.FileDescriptor -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, 0xa5, 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, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, - 0x64, 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, 0x9f, 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, 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, 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, 0xd1, 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, 0x12, 0x1d, 0x0a, 0x0a, - 0x67, 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 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, 0xa0, 0x01, 0x0a, 0x18, 0x52, 0x6f, - 0x6f, 0x6d, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x61, - 0x6e, 0x6b, 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, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03, 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, 0x04, 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, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xee, 0x05, 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, 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, 0x0b, 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, 0x0c, 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, 0x0d, - 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, 0x0e, 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, 0x0f, 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, 0x10, 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, 0x11, 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, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x04, 0x68, 0x69, 0x74, 0x73, - 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, - 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x4c, - 0x75, 0x63, 0x6b, 0x79, 0x48, 0x69, 0x74, 0x52, 0x04, 0x68, 0x69, 0x74, 0x73, 0x22, 0xda, 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, 0x12, 0x1a, - 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 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, 0x69, 0x0a, 0x16, 0x52, 0x6f, 0x6f, 0x6d, 0x52, - 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 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, 0x66, 0x75, - 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x66, 0x75, 0x65, 0x6c, 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, 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, 0xaa, 0x05, 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, 0x12, 0x5a, 0x0a, - 0x15, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0f, 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, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 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, 0x69, 0x0a, 0x1e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x48, - 0x75, 0x6d, 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x72, - 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, - 0x73, 0x22, 0x95, 0x01, 0x0a, 0x1e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x48, 0x75, 0x6d, 0x61, 0x6e, - 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x75, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, - 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x72, - 0x6f, 0x6f, 0x6d, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x0c, 0x6d, 0x61, 0x78, 0x52, 0x6f, 0x6f, 0x6d, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, 0x0a, - 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, - 0x64, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0xd8, 0x0a, 0x0a, 0x19, 0x41, 0x64, - 0x6d, 0x69, 0x6e, 0x48, 0x75, 0x6d, 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, - 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, 0x39, 0x0a, 0x19, - 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x6d, - 0x61, 0x78, 0x5f, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x16, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x4d, 0x61, - 0x78, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x31, 0x0a, 0x15, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, - 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x72, 0x6f, 0x6f, 0x6d, 0x46, 0x75, 0x6c, 0x6c, - 0x53, 0x74, 0x6f, 0x70, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x29, 0x0a, 0x11, 0x72, 0x6f, - 0x62, 0x6f, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x79, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x6d, 0x73, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x79, - 0x4d, 0x69, 0x6e, 0x4d, 0x73, 0x12, 0x29, 0x0a, 0x11, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x73, - 0x74, 0x61, 0x79, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x79, 0x4d, 0x61, 0x78, 0x4d, 0x73, - 0x12, 0x2f, 0x0a, 0x14, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, - 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, - 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x4d, 0x69, 0x6e, 0x4d, - 0x73, 0x12, 0x2f, 0x0a, 0x14, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, - 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x11, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x4d, 0x61, 0x78, - 0x4d, 0x73, 0x12, 0x35, 0x0a, 0x17, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x5f, 0x67, 0x69, 0x66, - 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x14, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x47, 0x69, 0x66, 0x74, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x69, 0x66, - 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x67, 0x69, 0x66, - 0x74, 0x49, 0x64, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x67, 0x69, - 0x66, 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x75, - 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x49, 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x14, 0x73, 0x75, - 0x70, 0x65, 0x72, 0x5f, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, - 0x64, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x73, 0x75, 0x70, 0x65, 0x72, 0x4c, - 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x49, 0x64, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6c, - 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x63, 0x6f, 0x6d, 0x62, 0x6f, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x43, 0x6f, 0x6d, 0x62, 0x6f, - 0x4d, 0x69, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x63, 0x6f, 0x6d, - 0x62, 0x6f, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6c, 0x75, - 0x63, 0x6b, 0x79, 0x43, 0x6f, 0x6d, 0x62, 0x6f, 0x4d, 0x61, 0x78, 0x12, 0x2b, 0x0a, 0x12, 0x6c, - 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x70, 0x61, 0x75, 0x73, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x6d, - 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x50, 0x61, - 0x75, 0x73, 0x65, 0x4d, 0x69, 0x6e, 0x4d, 0x73, 0x12, 0x2b, 0x0a, 0x12, 0x6c, 0x75, 0x63, 0x6b, - 0x79, 0x5f, 0x70, 0x61, 0x75, 0x73, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6d, 0x73, 0x18, 0x10, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x50, 0x61, 0x75, 0x73, 0x65, - 0x4d, 0x61, 0x78, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x67, 0x69, 0x66, - 0x74, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0e, 0x6d, 0x61, 0x78, 0x47, 0x69, 0x66, 0x74, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x12, - 0x52, 0x0a, 0x0d, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x73, - 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, - 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x48, 0x75, 0x6d, 0x61, - 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, - 0x79, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x6f, - 0x6f, 0x6c, 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, 0x13, 0x20, 0x01, 0x28, 0x04, - 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, 0x14, 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, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x3c, 0x0a, 0x1b, 0x6e, 0x6f, - 0x72, 0x6d, 0x61, 0x6c, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, - 0x61, 0x6c, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x17, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x47, 0x69, 0x66, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x76, 0x61, 0x6c, 0x4d, 0x69, 0x6e, 0x4d, 0x73, 0x12, 0x3c, 0x0a, 0x1b, 0x6e, 0x6f, 0x72, 0x6d, - 0x61, 0x6c, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, - 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6d, 0x73, 0x18, 0x17, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x6e, - 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x47, 0x69, 0x66, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, - 0x6c, 0x4d, 0x61, 0x78, 0x4d, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x18, 0x18, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x72, 0x6f, 0x6f, 0x6d, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x4d, 0x69, 0x6e, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x33, 0x0a, 0x16, 0x72, - 0x6f, 0x6f, 0x6d, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6f, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x72, 0x6f, 0x6f, - 0x6d, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4d, 0x61, 0x78, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x12, 0x2a, 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x6f, 0x77, 0x6e, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x1a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x65, 0x64, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x32, 0x0a, 0x15, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x65, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x72, 0x79, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x12, 0x52, 0x0a, 0x0d, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6c, 0x65, - 0x73, 0x18, 0x1c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x48, 0x75, 0x6d, - 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x75, 0x6c, 0x65, 0x73, 0x22, 0x55, 0x0a, 0x23, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x65, 0x74, - 0x48, 0x75, 0x6d, 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 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, 0x8e, 0x01, 0x0a, 0x24, - 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x65, 0x74, 0x48, 0x75, 0x6d, 0x61, 0x6e, 0x52, 0x6f, 0x6f, - 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, - 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x48, 0x75, 0x6d, 0x61, 0x6e, 0x52, - 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 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, 0xb5, 0x01, 0x0a, - 0x26, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x75, 0x6d, 0x61, - 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 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, 0x40, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x48, 0x75, 0x6d, - 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 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, 0x04, 0x52, 0x07, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x49, 0x64, 0x22, 0x91, 0x01, 0x0a, 0x27, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x48, 0x75, 0x6d, 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, - 0x6f, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x40, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x48, 0x75, 0x6d, 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, - 0x6f, 0x62, 0x6f, 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, 0x9c, 0x04, 0x0a, 0x16, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, - 0x74, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x64, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x67, 0x69, 0x66, 0x74, 0x49, 0x64, 0x73, - 0x12, 0x24, 0x0a, 0x0e, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, - 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x47, - 0x69, 0x66, 0x74, 0x49, 0x64, 0x73, 0x12, 0x35, 0x0a, 0x17, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, - 0x5f, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x47, - 0x69, 0x66, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x73, 0x12, 0x26, 0x0a, - 0x0f, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x63, 0x6f, 0x6d, 0x62, 0x6f, 0x5f, 0x6d, 0x69, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x43, 0x6f, 0x6d, - 0x62, 0x6f, 0x4d, 0x69, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x63, - 0x6f, 0x6d, 0x62, 0x6f, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, - 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x43, 0x6f, 0x6d, 0x62, 0x6f, 0x4d, 0x61, 0x78, 0x12, 0x2b, 0x0a, - 0x12, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x70, 0x61, 0x75, 0x73, 0x65, 0x5f, 0x6d, 0x69, 0x6e, - 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6c, 0x75, 0x63, 0x6b, 0x79, - 0x50, 0x61, 0x75, 0x73, 0x65, 0x4d, 0x69, 0x6e, 0x4d, 0x73, 0x12, 0x2b, 0x0a, 0x12, 0x6c, 0x75, - 0x63, 0x6b, 0x79, 0x5f, 0x70, 0x61, 0x75, 0x73, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6d, 0x73, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x50, 0x61, 0x75, - 0x73, 0x65, 0x4d, 0x61, 0x78, 0x4d, 0x73, 0x12, 0x29, 0x0a, 0x11, 0x72, 0x6f, 0x62, 0x6f, 0x74, - 0x5f, 0x73, 0x74, 0x61, 0x79, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x79, 0x4d, 0x69, 0x6e, - 0x4d, 0x73, 0x12, 0x29, 0x0a, 0x11, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x79, - 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, - 0x6f, 0x62, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x79, 0x4d, 0x61, 0x78, 0x4d, 0x73, 0x12, 0x2f, 0x0a, - 0x14, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x6d, - 0x69, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x72, 0x6f, 0x62, - 0x6f, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x4d, 0x69, 0x6e, 0x4d, 0x73, 0x12, 0x2f, - 0x0a, 0x14, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, - 0x6d, 0x61, 0x78, 0x5f, 0x6d, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x72, 0x6f, - 0x62, 0x6f, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x4d, 0x61, 0x78, 0x4d, 0x73, 0x12, - 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x73, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x47, 0x69, - 0x66, 0x74, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x22, 0xbc, 0x04, 0x0a, 0x0e, 0x41, 0x64, - 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x6f, 0x6f, 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, 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, 0x22, 0x0a, 0x0d, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x6f, 0x6f, 0x6d, 0x53, 0x68, 0x6f, - 0x72, 0x74, 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, 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, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x6f, - 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x52, - 0x6f, 0x62, 0x6f, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x6f, - 0x62, 0x6f, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x09, 0x20, 0x03, - 0x28, 0x03, 0x52, 0x0c, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, - 0x12, 0x42, 0x0a, 0x09, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x6f, - 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x08, 0x67, 0x69, 0x66, 0x74, - 0x52, 0x75, 0x6c, 0x65, 0x12, 0x2d, 0x0a, 0x13, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, - 0x62, 0x79, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x10, 0x63, 0x72, 0x65, 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, 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, 0x2c, 0x0a, 0x12, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, - 0x6f, 0x62, 0x6f, 0x74, 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, 0x22, 0x95, 0x01, 0x0a, 0x1a, 0x41, 0x64, 0x6d, - 0x69, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x62, 0x6f, 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, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x22, 0x8e, 0x01, 0x0a, 0x1b, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, - 0x62, 0x6f, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x33, 0x0a, 0x05, 0x72, 0x6f, 0x6f, 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, - 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x6f, 0x6f, 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, 0x9b, 0x04, 0x0a, 0x1b, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x52, 0x6f, 0x62, 0x6f, 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, 0x2d, 0x0a, 0x13, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x72, 0x6f, 0x62, 0x6f, 0x74, - 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, - 0x12, 0x37, 0x0a, 0x18, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, - 0x62, 0x6f, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x03, 0x52, 0x15, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x62, - 0x6f, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x69, 0x6e, - 0x5f, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0d, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x52, - 0x6f, 0x62, 0x6f, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x6f, - 0x6d, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 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, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x6f, 0x6f, - 0x6d, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 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, 0x42, 0x0a, 0x09, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x72, 0x75, 0x6c, 0x65, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, - 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x62, 0x6f, - 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x08, 0x67, - 0x69, 0x66, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0c, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, - 0x77, 0x0a, 0x1c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, - 0x62, 0x6f, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x31, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, - 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x6f, 0x6f, 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, 0x83, 0x01, 0x0a, 0x1e, 0x41, 0x64, 0x6d, - 0x69, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x74, - 0x61, 0x74, 0x75, 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, 0x16, 0x0a, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 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, 0x7a, - 0x0a, 0x1f, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, - 0x6f, 0x6f, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x31, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x6f, 0x6f, 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, 0xc3, 0x01, 0x0a, 0x22, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 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, 0x28, 0x0a, 0x10, 0x6f, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, - 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x6c, 0x64, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x6e, - 0x65, 0x77, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6e, 0x65, 0x77, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, - 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, - 0x22, 0x9e, 0x01, 0x0a, 0x23, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, - 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x6f, 0x6f, 0x6d, - 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, 0x6f, 0x6f, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x72, 0x6f, - 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 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, 0x72, 0x0a, 0x25, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, - 0x6f, 0x74, 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, 0x19, 0x0a, 0x08, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x03, 0x52, 0x07, 0x75, 0x73, - 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0xa8, 0x01, 0x0a, 0x26, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x6f, - 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x03, 0x52, 0x10, 0x61, 0x76, - 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x2a, - 0x0a, 0x11, 0x6f, 0x63, 0x63, 0x75, 0x70, 0x69, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0f, 0x6f, 0x63, 0x63, 0x75, 0x70, - 0x69, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 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, 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, 0xf8, 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, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x16, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 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, 0xa2, 0x03, 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, 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x10, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, - 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x6f, 0x6f, - 0x6d, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x6f, 0x62, 0x6f, 0x74, - 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 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, 0xc2, - 0x01, 0x0a, 0x16, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 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, 0x1a, 0x0a, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, - 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x26, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x33, - 0x0a, 0x16, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, - 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, - 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x22, 0xe4, 0x03, 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, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x63, 0x74, 0x6f, 0x72, - 0x5f, 0x69, 0x73, 0x5f, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0c, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x49, 0x73, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x12, 0x59, 0x0a, - 0x15, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x70, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, - 0x6d, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x52, 0x13, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x2b, 0x0a, - 0x11, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, - 0x72, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, - 0x63, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x22, 0xa2, 0x01, 0x0a, 0x18, 0x52, - 0x6f, 0x6f, 0x6d, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x56, 0x69, 0x70, 0x53, - 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x67, 0x72, - 0x61, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, - 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x54, 0x79, 0x70, 0x65, 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, 0x39, 0x0a, 0x19, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x72, 0x6f, 0x6f, 0x6d, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x4e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, - 0xf4, 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, 0x12, 0x4c, 0x0a, 0x0d, 0x65, 0x66, 0x66, 0x65, - 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x69, 0x70, 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, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x56, 0x69, 0x70, - 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x0c, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x56, 0x69, 0x70, 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, 0x8c, 0x04, 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, 0x12, 0x31, 0x0a, 0x12, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x06, 0x52, 0x10, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x88, 0x01, 0x01, 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, 0x42, 0x15, - 0x0a, 0x13, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, - 0x5f, 0x63, 0x6f, 0x64, 0x65, 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, 0xb4, 0x01, 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, 0x12, 0x5b, 0x0a, 0x16, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x70, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, - 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x52, 0x14, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, - 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 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, - 0xdb, 0x01, 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, - 0x12, 0x5b, 0x0a, 0x16, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, - 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x14, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 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, 0xe2, 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, 0x12, 0x5b, 0x0a, 0x16, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, - 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x52, 0x14, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 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, 0xd5, 0x02, 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, 0x12, 0x5b, 0x0a, 0x16, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x14, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 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, 0xdc, 0x01, 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, 0x12, 0x5b, 0x0a, - 0x16, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, - 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, - 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x52, 0x14, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 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, 0xd6, - 0x01, 0x0a, 0x17, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, 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, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x73, 0x5f, 0x68, 0x6f, - 0x73, 0x74, 0x18, 0x02, 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, - 0x03, 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, 0x04, 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, 0xc2, 0x01, 0x0a, 0x16, 0x53, 0x65, 0x6e, 0x64, - 0x47, 0x69, 0x66, 0x74, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 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, 0x1a, 0x0a, 0x08, 0x75, - 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, - 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, - 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, - 0x26, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x16, 0x70, 0x72, 0x65, 0x74, 0x74, - 0x79, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x8a, 0x04, 0x0a, - 0x13, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x54, 0x61, - 0x72, 0x67, 0x65, 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, 0x2b, 0x0a, 0x11, 0x72, 0x65, - 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x4e, - 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x63, 0x65, 0x69, - 0x76, 0x65, 0x72, 0x5f, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0e, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, - 0x12, 0x37, 0x0a, 0x18, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x15, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x44, 0x0a, 0x1f, 0x72, 0x65, 0x63, - 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, 0x64, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x1b, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x50, 0x72, 0x65, 0x74, - 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2a, - 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x47, 0x69, 0x66, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, - 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, - 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x62, 0x69, 0x6c, - 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x5f, 0x69, 0x64, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x65, - 0x63, 0x65, 0x69, 0x70, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x41, 0x0a, 0x0a, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, - 0x67, 0x69, 0x66, 0x74, 0x18, 0x0b, 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, 0x22, 0xf4, 0x06, 0x0a, 0x14, 0x53, 0x65, - 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 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, 0x24, 0x0a, - 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x61, - 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x6e, - 0x64, 0x65, 0x72, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x33, 0x0a, 0x16, 0x73, 0x65, 0x6e, - 0x64, 0x65, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, 0x65, 0x6e, 0x64, 0x65, - 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x40, - 0x0a, 0x1d, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, - 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x72, 0x65, - 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 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, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, - 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x67, - 0x69, 0x66, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, - 0x6c, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x47, 0x69, 0x66, 0x74, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x69, 0x6e, - 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, - 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x0b, 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, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, - 0x6f, 0x6f, 0x6d, 0x48, 0x65, 0x61, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, - 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, - 0x12, 0x24, 0x0a, 0x0e, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x63, 0x6f, - 0x64, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x69, 0x66, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x70, 0x5f, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0e, 0x63, 0x70, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x10, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x69, 0x66, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, - 0x0d, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x11, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x67, 0x69, 0x66, 0x74, 0x49, 0x63, 0x6f, 0x6e, 0x55, 0x72, - 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x67, - 0x69, 0x66, 0x74, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x12, - 0x2a, 0x0a, 0x11, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x18, 0x13, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x67, 0x69, 0x66, 0x74, - 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x14, - 0x20, 0x03, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, - 0x49, 0x64, 0x73, 0x12, 0x3c, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x15, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, - 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x42, 0x61, 0x74, - 0x63, 0x68, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, - 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, - 0x22, 0xe0, 0x07, 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, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x12, 0x54, 0x0a, 0x12, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, - 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, - 0x64, 0x47, 0x69, 0x66, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, - 0x63, 0x6f, 0x70, 0x65, 0x52, 0x10, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, - 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x5b, 0x0a, 0x16, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, - 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, - 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x44, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x14, 0x73, - 0x65, 0x6e, 0x64, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x12, 0x5d, 0x0a, 0x17, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x69, - 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x11, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, - 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x44, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x15, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x6f, - 0x64, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x62, 0x6f, 0x5f, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x63, 0x6f, 0x6d, 0x62, 0x6f, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, - 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x65, 0x71, 0x18, 0x14, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x08, 0x62, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x71, 0x12, 0x35, 0x0a, 0x17, - 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, - 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x73, - 0x65, 0x6e, 0x64, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x41, - 0x74, 0x4d, 0x73, 0x22, 0x9e, 0x05, 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, - 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x63, 0x6f, - 0x69, 0x6e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x39, - 0x0a, 0x19, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x5f, 0x62, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x16, 0x67, 0x69, 0x66, 0x74, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x42, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x0d, 0x62, 0x61, 0x74, - 0x63, 0x68, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x69, - 0x73, 0x70, 0x6c, 0x61, 0x79, 0x52, 0x0c, 0x62, 0x61, 0x74, 0x63, 0x68, 0x44, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x12, 0x2f, 0x0a, 0x02, 0x76, 0x32, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, - 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, 0x75, 0x6c, 0x74, 0x56, 0x32, - 0x52, 0x02, 0x76, 0x32, 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, 0x53, 0x0a, 0x19, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x6d, - 0x41, 0x70, 0x70, 0x43, 0x6f, 0x64, 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, 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, 0x37, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, - 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x41, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 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, 0x22, - 0x97, 0x03, 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, 0x12, 0x21, 0x0a, 0x0c, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, - 0x2e, 0x0a, 0x13, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, - 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x76, 0x69, - 0x65, 0x77, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, - 0x2e, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, - 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x61, 0x6c, - 0x6c, 0x56, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x28, 0x0a, 0x10, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xec, 0x01, 0x0a, 0x18, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x42, 0x79, 0x4f, 0x77, 0x6e, 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, 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, 0x24, 0x0a, 0x0e, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x73, 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, 0xd6, 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, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 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, 0xbe, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x43, 0x6f, 0x6e, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 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, 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, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, - 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x76, - 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0c, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x22, 0x8a, 0x02, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x6b, 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, - 0x16, 0x0a, 0x06, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x02, 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, 0x03, 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, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x41, - 0x74, 0x4d, 0x73, 0x12, 0x3d, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x6b, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, - 0x6d, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x06, 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, 0x07, 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, 0x22, 0xe4, 0x01, 0x0a, 0x10, 0x53, - 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x48, 0x69, 0x74, 0x12, - 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 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, 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, 0x28, 0x0a, - 0x10, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x04, 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, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0d, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x50, 0x70, 0x6d, 0x12, 0x21, - 0x0a, 0x0c, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x69, 0x6e, - 0x73, 0x22, 0xb1, 0x07, 0x0a, 0x10, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x56, 0x32, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x61, 0x70, 0x69, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 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, 0x28, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x62, 0x6f, 0x5f, - 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x62, 0x6f, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x65, 0x71, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x08, 0x62, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x71, 0x12, 0x2b, 0x0a, - 0x11, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6c, - 0x61, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, - 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x12, 0x34, 0x0a, 0x16, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x74, 0x65, 0x64, 0x52, 0x6f, 0x6f, 0x6d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x2c, 0x0a, 0x12, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x63, 0x65, - 0x69, 0x70, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x62, 0x69, - 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 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, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x63, 0x6f, 0x69, 0x6e, - 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x19, - 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x5f, 0x62, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x16, 0x67, 0x69, 0x66, 0x74, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x65, 0x74, 0x74, 0x6c, - 0x65, 0x64, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x10, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x47, 0x69, 0x66, 0x74, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x17, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x64, - 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, - 0x18, 0x0b, 0x20, 0x03, 0x28, 0x03, 0x52, 0x14, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x27, 0x0a, 0x0f, - 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0a, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x67, - 0x69, 0x66, 0x74, 0x18, 0x0d, 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, 0x0e, 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, 0x12, 0x3e, 0x0a, - 0x0a, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x68, 0x69, 0x74, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x48, - 0x69, 0x74, 0x52, 0x09, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x48, 0x69, 0x74, 0x73, 0x12, 0x48, 0x0a, - 0x0d, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x10, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, - 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x42, 0x61, 0x74, - 0x63, 0x68, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x52, 0x0c, 0x62, 0x61, 0x74, 0x63, 0x68, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, - 0x68, 0x65, 0x61, 0x74, 0x18, 0x11, 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, 0x12, 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, 0x29, 0x0a, 0x10, 0x6f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x13, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x32, 0xb2, 0x1b, 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, 0x90, - 0x01, 0x0a, 0x1f, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x75, - 0x6d, 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x35, 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, 0x48, 0x75, - 0x6d, 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 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, 0x48, 0x75, 0x6d, 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, - 0x62, 0x6f, 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, 0x6f, 0x0a, 0x14, 0x41, 0x64, 0x6d, 0x69, 0x6e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x12, - 0x2a, 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, 0x62, 0x6f, 0x74, - 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 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, 0x62, 0x6f, 0x74, 0x52, 0x6f, 0x6f, 0x6d, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x17, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x62, 0x6f, - 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x62, 0x6f, 0x74, - 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x84, 0x01, 0x0a, 0x1b, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x6e, 0x61, - 0x6d, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, - 0x64, 0x65, 0x12, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x4f, 0x77, - 0x6e, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 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, 0x52, 0x65, 0x6e, 0x61, 0x6d, - 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, - 0x65, 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, 0xd9, 0x02, 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, 0x12, 0x69, 0x0a, 0x12, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x41, 0x70, 0x70, 0x43, 0x6f, 0x64, - 0x65, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x41, 0x70, 0x70, - 0x43, 0x6f, 0x64, 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, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x41, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe4, 0x10, 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, 0x87, 0x01, 0x0a, 0x1c, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x47, 0x65, 0x74, 0x48, 0x75, 0x6d, 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, - 0x6f, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x65, - 0x74, 0x48, 0x75, 0x6d, 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, - 0x69, 0x6e, 0x47, 0x65, 0x74, 0x48, 0x75, 0x6d, 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, - 0x62, 0x6f, 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, 0x6c, 0x0a, 0x13, 0x41, 0x64, 0x6d, - 0x69, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, - 0x12, 0x29, 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, 0x62, 0x6f, 0x74, 0x52, - 0x6f, 0x6f, 0x6d, 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, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x1e, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, - 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x12, 0x34, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, - 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x41, 0x76, 0x61, 0x69, - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 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, 0x5e, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x6f, 0x6f, 0x6d, 0x73, 0x42, 0x79, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x27, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x42, 0x79, 0x4f, 0x77, 0x6e, 0x65, 0x72, 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, 0x7b, 0x0a, 0x18, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x61, 0x6e, 0x6b, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, - 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x6b, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, - 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x6b, 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, -} +const file_proto_room_v1_room_proto_rawDesc = "" + + "\n" + + "\x18proto/room/v1/room.proto\x12\rhyapp.room.v1\"\xa5\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\x12\x1b\n" + + "\tdevice_id\x18\t \x01(\tR\bdeviceId\"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\"\x9f\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\x12\x1d\n" + + "\n" + + "gift_value\x18\x05 \x01(\x03R\tgiftValue\"\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\"\xd1\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\x12\x1d\n" + + "\n" + + "gift_value\x18\f \x01(\x03R\tgiftValue\"|\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\"\xa0\x01\n" + + "\x18RoomContributionRankItem\x12\x12\n" + + "\x04rank\x18\x01 \x01(\x03R\x04rank\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x14\n" + + "\x05score\x18\x03 \x01(\x03R\x05score\x12\x1d\n" + + "\n" + + "gift_value\x18\x04 \x01(\x03R\tgiftValue\x12\"\n" + + "\rupdated_at_ms\x18\x05 \x01(\x03R\vupdatedAtMs\"\xee\x05\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\x124\n" + + "\x16effective_reward_coins\x18\v \x01(\x03R\x14effectiveRewardCoins\x12#\n" + + "\rreward_status\x18\f \x01(\tR\frewardStatus\x12%\n" + + "\x0estage_feedback\x18\r \x01(\bR\rstageFeedback\x12'\n" + + "\x0fhigh_multiplier\x18\x0e \x01(\bR\x0ehighMultiplier\x12\"\n" + + "\rcreated_at_ms\x18\x0f \x01(\x03R\vcreatedAtMs\x122\n" + + "\x15wallet_transaction_id\x18\x10 \x01(\tR\x13walletTransactionId\x12,\n" + + "\x12coin_balance_after\x18\x11 \x01(\x03R\x10coinBalanceAfter\x12$\n" + + "\x0etarget_user_id\x18\x12 \x01(\x03R\ftargetUserId\x123\n" + + "\x04hits\x18\x13 \x03(\v2\x1f.hyapp.room.v1.SendGiftLuckyHitR\x04hits\"\xda\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\x12\x1a\n" + + "\bquantity\x18\x06 \x01(\x03R\bquantity\"\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\"i\n" + + "\x16RoomRocketContribution\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x12\n" + + "\x04fuel\x18\x02 \x01(\x03R\x04fuel\x12\"\n" + + "\rupdated_at_ms\x18\x03 \x01(\x03R\vupdatedAtMs\"\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\"\xaa\x05\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\x12Z\n" + + "\x15current_contributions\x18\x0f \x03(\v2%.hyapp.room.v1.RoomRocketContributionR\x14currentContributions\"\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\"i\n" + + "\x1eAdminHumanRoomRobotCountryPool\x12!\n" + + "\fcountry_code\x18\x01 \x01(\tR\vcountryCode\x12$\n" + + "\x0erobot_user_ids\x18\x02 \x03(\x03R\frobotUserIds\"\x95\x01\n" + + "\x1eAdminHumanRoomRobotCountryRule\x12!\n" + + "\fcountry_code\x18\x01 \x01(\tR\vcountryCode\x12$\n" + + "\x0emax_room_count\x18\x02 \x01(\x05R\fmaxRoomCount\x12*\n" + + "\x11allowed_owner_ids\x18\x03 \x03(\tR\x0fallowedOwnerIds\"\xd8\n" + + "\n" + + "\x19AdminHumanRoomRobotConfig\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x18\n" + + "\aenabled\x18\x02 \x01(\bR\aenabled\x129\n" + + "\x19candidate_room_max_online\x18\x03 \x01(\x05R\x16candidateRoomMaxOnline\x121\n" + + "\x15room_full_stop_online\x18\x04 \x01(\x05R\x12roomFullStopOnline\x12)\n" + + "\x11robot_stay_min_ms\x18\x05 \x01(\x03R\x0erobotStayMinMs\x12)\n" + + "\x11robot_stay_max_ms\x18\x06 \x01(\x03R\x0erobotStayMaxMs\x12/\n" + + "\x14robot_replace_min_ms\x18\a \x01(\x03R\x11robotReplaceMinMs\x12/\n" + + "\x14robot_replace_max_ms\x18\b \x01(\x03R\x11robotReplaceMaxMs\x125\n" + + "\x17normal_gift_interval_ms\x18\t \x01(\x03R\x14normalGiftIntervalMs\x12\x19\n" + + "\bgift_ids\x18\n" + + " \x03(\tR\agiftIds\x12$\n" + + "\x0elucky_gift_ids\x18\v \x03(\tR\fluckyGiftIds\x12/\n" + + "\x14super_lucky_gift_ids\x18\f \x03(\tR\x11superLuckyGiftIds\x12&\n" + + "\x0flucky_combo_min\x18\r \x01(\x03R\rluckyComboMin\x12&\n" + + "\x0flucky_combo_max\x18\x0e \x01(\x03R\rluckyComboMax\x12+\n" + + "\x12lucky_pause_min_ms\x18\x0f \x01(\x03R\x0fluckyPauseMinMs\x12+\n" + + "\x12lucky_pause_max_ms\x18\x10 \x01(\x03R\x0fluckyPauseMaxMs\x12(\n" + + "\x10max_gift_senders\x18\x11 \x01(\x03R\x0emaxGiftSenders\x12R\n" + + "\rcountry_pools\x18\x12 \x03(\v2-.hyapp.room.v1.AdminHumanRoomRobotCountryPoolR\fcountryPools\x12-\n" + + "\x13updated_by_admin_id\x18\x13 \x01(\x04R\x10updatedByAdminId\x12\"\n" + + "\rcreated_at_ms\x18\x14 \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x15 \x01(\x03R\vupdatedAtMs\x12<\n" + + "\x1bnormal_gift_interval_min_ms\x18\x16 \x01(\x03R\x17normalGiftIntervalMinMs\x12<\n" + + "\x1bnormal_gift_interval_max_ms\x18\x17 \x01(\x03R\x17normalGiftIntervalMaxMs\x123\n" + + "\x16room_target_min_online\x18\x18 \x01(\x05R\x13roomTargetMinOnline\x123\n" + + "\x16room_target_max_online\x18\x19 \x01(\x05R\x13roomTargetMaxOnline\x12*\n" + + "\x11allowed_owner_ids\x18\x1a \x03(\tR\x0fallowedOwnerIds\x122\n" + + "\x15country_limit_enabled\x18\x1b \x01(\bR\x13countryLimitEnabled\x12R\n" + + "\rcountry_rules\x18\x1c \x03(\v2-.hyapp.room.v1.AdminHumanRoomRobotCountryRuleR\fcountryRules\"U\n" + + "#AdminGetHumanRoomRobotConfigRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\"\x8e\x01\n" + + "$AdminGetHumanRoomRobotConfigResponse\x12@\n" + + "\x06config\x18\x01 \x01(\v2(.hyapp.room.v1.AdminHumanRoomRobotConfigR\x06config\x12$\n" + + "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xb5\x01\n" + + "&AdminUpdateHumanRoomRobotConfigRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12@\n" + + "\x06config\x18\x02 \x01(\v2(.hyapp.room.v1.AdminHumanRoomRobotConfigR\x06config\x12\x19\n" + + "\badmin_id\x18\x03 \x01(\x04R\aadminId\"\x91\x01\n" + + "'AdminUpdateHumanRoomRobotConfigResponse\x12@\n" + + "\x06config\x18\x01 \x01(\v2(.hyapp.room.v1.AdminHumanRoomRobotConfigR\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\"\x9c\x04\n" + + "\x16AdminRobotRoomGiftRule\x12\x19\n" + + "\bgift_ids\x18\x01 \x03(\tR\agiftIds\x12$\n" + + "\x0elucky_gift_ids\x18\x02 \x03(\tR\fluckyGiftIds\x125\n" + + "\x17normal_gift_interval_ms\x18\x03 \x01(\x03R\x14normalGiftIntervalMs\x12&\n" + + "\x0flucky_combo_min\x18\x04 \x01(\x03R\rluckyComboMin\x12&\n" + + "\x0flucky_combo_max\x18\x05 \x01(\x03R\rluckyComboMax\x12+\n" + + "\x12lucky_pause_min_ms\x18\x06 \x01(\x03R\x0fluckyPauseMinMs\x12+\n" + + "\x12lucky_pause_max_ms\x18\a \x01(\x03R\x0fluckyPauseMaxMs\x12)\n" + + "\x11robot_stay_min_ms\x18\b \x01(\x03R\x0erobotStayMinMs\x12)\n" + + "\x11robot_stay_max_ms\x18\t \x01(\x03R\x0erobotStayMaxMs\x12/\n" + + "\x14robot_replace_min_ms\x18\n" + + " \x01(\x03R\x11robotReplaceMinMs\x12/\n" + + "\x14robot_replace_max_ms\x18\v \x01(\x03R\x11robotReplaceMaxMs\x12(\n" + + "\x10max_gift_senders\x18\f \x01(\x03R\x0emaxGiftSenders\"\xbc\x04\n" + + "\x0eAdminRobotRoom\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x17\n" + + "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12\"\n" + + "\rroom_short_id\x18\x03 \x01(\tR\vroomShortId\x12\x14\n" + + "\x05title\x18\x04 \x01(\tR\x05title\x12\x1b\n" + + "\tcover_url\x18\x05 \x01(\tR\bcoverUrl\x12*\n" + + "\x11visible_region_id\x18\x06 \x01(\x03R\x0fvisibleRegionId\x12\x16\n" + + "\x06status\x18\a \x01(\tR\x06status\x12-\n" + + "\x13owner_robot_user_id\x18\b \x01(\x03R\x10ownerRobotUserId\x12$\n" + + "\x0erobot_user_ids\x18\t \x03(\x03R\frobotUserIds\x12B\n" + + "\tgift_rule\x18\n" + + " \x01(\v2%.hyapp.room.v1.AdminRobotRoomGiftRuleR\bgiftRule\x12-\n" + + "\x13created_by_admin_id\x18\v \x01(\x04R\x10createdByAdminId\x12\"\n" + + "\rcreated_at_ms\x18\f \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\r \x01(\x03R\vupdatedAtMs\x12,\n" + + "\x12active_robot_count\x18\x0e \x01(\x05R\x10activeRobotCount\x12\x1d\n" + + "\n" + + "seat_count\x18\x0f \x01(\x05R\tseatCount\"\x95\x01\n" + + "\x1aAdminListRobotRoomsRequest\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\x16\n" + + "\x06status\x18\x04 \x01(\tR\x06status\"\x8e\x01\n" + + "\x1bAdminListRobotRoomsResponse\x123\n" + + "\x05rooms\x18\x01 \x03(\v2\x1d.hyapp.room.v1.AdminRobotRoomR\x05rooms\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\x12$\n" + + "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\x9b\x04\n" + + "\x1bAdminCreateRobotRoomRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12-\n" + + "\x13owner_robot_user_id\x18\x02 \x01(\x03R\x10ownerRobotUserId\x127\n" + + "\x18candidate_robot_user_ids\x18\x03 \x03(\x03R\x15candidateRobotUserIds\x12&\n" + + "\x0fmin_robot_count\x18\x04 \x01(\x05R\rminRobotCount\x12&\n" + + "\x0fmax_robot_count\x18\x05 \x01(\x05R\rmaxRobotCount\x12\x1b\n" + + "\troom_name\x18\x06 \x01(\tR\broomName\x12\x1f\n" + + "\vroom_avatar\x18\a \x01(\tR\n" + + "roomAvatar\x12*\n" + + "\x11visible_region_id\x18\b \x01(\x03R\x0fvisibleRegionId\x12B\n" + + "\tgift_rule\x18\t \x01(\v2%.hyapp.room.v1.AdminRobotRoomGiftRuleR\bgiftRule\x12\x19\n" + + "\badmin_id\x18\n" + + " \x01(\x04R\aadminId\x12,\n" + + "\x12owner_country_code\x18\v \x01(\tR\x10ownerCountryCode\x12\x1d\n" + + "\n" + + "seat_count\x18\f \x01(\x05R\tseatCount\"w\n" + + "\x1cAdminCreateRobotRoomResponse\x121\n" + + "\x04room\x18\x01 \x01(\v2\x1d.hyapp.room.v1.AdminRobotRoomR\x04room\x12$\n" + + "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\x83\x01\n" + + "\x1eAdminSetRobotRoomStatusRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x16\n" + + "\x06status\x18\x02 \x01(\tR\x06status\x12\x19\n" + + "\badmin_id\x18\x03 \x01(\x04R\aadminId\"z\n" + + "\x1fAdminSetRobotRoomStatusResponse\x121\n" + + "\x04room\x18\x01 \x01(\v2\x1d.hyapp.room.v1.AdminRobotRoomR\x04room\x12$\n" + + "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xc3\x01\n" + + "\"AdminRenameOwnerCountryCodeRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12(\n" + + "\x10old_country_code\x18\x02 \x01(\tR\x0eoldCountryCode\x12(\n" + + "\x10new_country_code\x18\x03 \x01(\tR\x0enewCountryCode\x12\x19\n" + + "\badmin_id\x18\x04 \x01(\x04R\aadminId\"\x9e\x01\n" + + "#AdminRenameOwnerCountryCodeResponse\x12*\n" + + "\x11room_list_entries\x18\x01 \x01(\x03R\x0froomListEntries\x12%\n" + + "\x0eroom_snapshots\x18\x02 \x01(\x03R\rroomSnapshots\x12$\n" + + "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"r\n" + + "%AdminFilterAvailableRoomRobotsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x19\n" + + "\buser_ids\x18\x02 \x03(\x03R\auserIds\"\xa8\x01\n" + + "&AdminFilterAvailableRoomRobotsResponse\x12,\n" + + "\x12available_user_ids\x18\x01 \x03(\x03R\x10availableUserIds\x12*\n" + + "\x11occupied_user_ids\x18\x02 \x03(\x03R\x0foccupiedUserIds\x12$\n" + + "\x0eserver_time_ms\x18\x03 \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\"\xf8\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\x12!\n" + + "\fonline_count\x18\x16 \x01(\x05R\vonlineCount\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\"\xa2\x03\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\x12,\n" + + "\x12owner_country_code\x18\t \x01(\tR\x10ownerCountryCode\x12\x1d\n" + + "\n" + + "robot_room\x18\n" + + " \x01(\bR\trobotRoom\x12$\n" + + "\x0erobot_user_ids\x18\v \x03(\x03R\frobotUserIds\"{\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\"\xc2\x01\n" + + "\x16RoomUserDisplayProfile\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" + + "\bnickname\x18\x02 \x01(\tR\bnickname\x12\x16\n" + + "\x06avatar\x18\x03 \x01(\tR\x06avatar\x12&\n" + + "\x0fdisplay_user_id\x18\x04 \x01(\tR\rdisplayUserId\x123\n" + + "\x16pretty_display_user_id\x18\x05 \x01(\tR\x13prettyDisplayUserId\"\xe4\x03\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\x12(\n" + + "\x10actor_country_id\x18\x05 \x01(\x03R\x0eactorCountryId\x12&\n" + + "\x0factor_region_id\x18\x06 \x01(\x03R\ractorRegionId\x12$\n" + + "\x0eactor_is_robot\x18\a \x01(\bR\factorIsRobot\x12Y\n" + + "\x15actor_display_profile\x18\b \x01(\v2%.hyapp.room.v1.RoomUserDisplayProfileR\x13actorDisplayProfile\x12#\n" + + "\rresponse_mode\x18\t \x01(\tR\fresponseMode\x12+\n" + + "\x11presence_recovery\x18\n" + + " \x01(\bR\x10presenceRecovery\"\xa2\x01\n" + + "\x18RoomEffectiveVipSnapshot\x12!\n" + + "\fprogram_type\x18\x01 \x01(\tR\vprogramType\x12\x14\n" + + "\x05level\x18\x02 \x01(\x05R\x05level\x12\x12\n" + + "\x04name\x18\x03 \x01(\tR\x04name\x129\n" + + "\x19room_entry_notice_enabled\x18\x04 \x01(\bR\x16roomEntryNoticeEnabled\"\xf4\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\x12L\n" + + "\reffective_vip\x18\x04 \x01(\v2'.hyapp.room.v1.RoomEffectiveVipSnapshotR\feffectiveVip\"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\"\x8c\x04\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\tadminName\x121\n" + + "\x12owner_country_code\x18\v \x01(\tH\x06R\x10ownerCountryCode\x88\x01\x01B\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_idB\x15\n" + + "\x13_owner_country_code\"\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\"\xb4\x01\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\x12[\n" + + "\x16target_display_profile\x18\x03 \x01(\v2%.hyapp.room.v1.RoomUserDisplayProfileR\x14targetDisplayProfile\"\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\"\xdb\x01\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\x12[\n" + + "\x16target_display_profile\x18\x04 \x01(\v2%.hyapp.room.v1.RoomUserDisplayProfileR\x14targetDisplayProfile\"\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\"\xe2\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\x12[\n" + + "\x16target_display_profile\x18\x04 \x01(\v2%.hyapp.room.v1.RoomUserDisplayProfileR\x14targetDisplayProfile\"~\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\"\xd5\x02\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\x12[\n" + + "\x16target_display_profile\x18\a \x01(\v2%.hyapp.room.v1.RoomUserDisplayProfileR\x14targetDisplayProfile\"\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\"\xdc\x01\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\x12[\n" + + "\x16target_display_profile\x18\x04 \x01(\v2%.hyapp.room.v1.RoomUserDisplayProfileR\x14targetDisplayProfile\"\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\"\xd6\x01\n" + + "\x17SendGiftTargetHostScope\x12$\n" + + "\x0etarget_user_id\x18\x01 \x01(\x03R\ftargetUserId\x12$\n" + + "\x0etarget_is_host\x18\x02 \x01(\bR\ftargetIsHost\x121\n" + + "\x15target_host_region_id\x18\x03 \x01(\x03R\x12targetHostRegionId\x12<\n" + + "\x1btarget_agency_owner_user_id\x18\x04 \x01(\x03R\x17targetAgencyOwnerUserId\"\xc2\x01\n" + + "\x16SendGiftDisplayProfile\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" + + "\busername\x18\x02 \x01(\tR\busername\x12\x16\n" + + "\x06avatar\x18\x03 \x01(\tR\x06avatar\x12&\n" + + "\x0fdisplay_user_id\x18\x04 \x01(\tR\rdisplayUserId\x123\n" + + "\x16pretty_display_user_id\x18\x05 \x01(\tR\x13prettyDisplayUserId\"\x8a\x04\n" + + "\x13SendGiftBatchTarget\x12$\n" + + "\x0etarget_user_id\x18\x01 \x01(\x03R\ftargetUserId\x12+\n" + + "\x11receiver_nickname\x18\x02 \x01(\tR\x10receiverNickname\x12'\n" + + "\x0freceiver_avatar\x18\x03 \x01(\tR\x0ereceiverAvatar\x127\n" + + "\x18receiver_display_user_id\x18\x04 \x01(\tR\x15receiverDisplayUserId\x12D\n" + + "\x1freceiver_pretty_display_user_id\x18\x05 \x01(\tR\x1breceiverPrettyDisplayUserId\x12\x1d\n" + + "\n" + + "gift_value\x18\x06 \x01(\x03R\tgiftValue\x12*\n" + + "\x11target_gift_value\x18\a \x01(\x03R\x0ftargetGiftValue\x12\x1d\n" + + "\n" + + "coin_spent\x18\b \x01(\x03R\tcoinSpent\x12,\n" + + "\x12billing_receipt_id\x18\t \x01(\tR\x10billingReceiptId\x12\x1d\n" + + "\n" + + "command_id\x18\n" + + " \x01(\tR\tcommandId\x12A\n" + + "\n" + + "lucky_gift\x18\v \x01(\v2\".hyapp.room.v1.LuckyGiftDrawResultR\tluckyGift\"\xf4\x06\n" + + "\x14SendGiftBatchDisplay\x12\x19\n" + + "\bevent_id\x18\x01 \x01(\tR\aeventId\x12$\n" + + "\x0esender_user_id\x18\x02 \x01(\x03R\fsenderUserId\x12\x1f\n" + + "\vsender_name\x18\x03 \x01(\tR\n" + + "senderName\x12#\n" + + "\rsender_avatar\x18\x04 \x01(\tR\fsenderAvatar\x123\n" + + "\x16sender_display_user_id\x18\x05 \x01(\tR\x13senderDisplayUserId\x12@\n" + + "\x1dsender_pretty_display_user_id\x18\x06 \x01(\tR\x19senderPrettyDisplayUserId\x12\x17\n" + + "\agift_id\x18\a \x01(\tR\x06giftId\x12\x1d\n" + + "\n" + + "gift_count\x18\b \x01(\x05R\tgiftCount\x12(\n" + + "\x10total_gift_value\x18\t \x01(\x03R\x0etotalGiftValue\x12(\n" + + "\x10total_coin_spent\x18\n" + + " \x01(\x03R\x0etotalCoinSpent\x12,\n" + + "\x12billing_receipt_id\x18\v \x01(\tR\x10billingReceiptId\x12\x1b\n" + + "\troom_heat\x18\f \x01(\x03R\broomHeat\x12\x17\n" + + "\apool_id\x18\r \x01(\tR\x06poolId\x12$\n" + + "\x0egift_type_code\x18\x0e \x01(\tR\fgiftTypeCode\x12(\n" + + "\x10cp_relation_type\x18\x0f \x01(\tR\x0ecpRelationType\x12\x1b\n" + + "\tgift_name\x18\x10 \x01(\tR\bgiftName\x12\"\n" + + "\rgift_icon_url\x18\x11 \x01(\tR\vgiftIconUrl\x12,\n" + + "\x12gift_animation_url\x18\x12 \x01(\tR\x10giftAnimationUrl\x12*\n" + + "\x11gift_effect_types\x18\x13 \x03(\tR\x0fgiftEffectTypes\x12&\n" + + "\x0ftarget_user_ids\x18\x14 \x03(\x03R\rtargetUserIds\x12<\n" + + "\atargets\x18\x15 \x03(\v2\".hyapp.room.v1.SendGiftBatchTargetR\atargets\x12\x1d\n" + + "\n" + + "command_id\x18\x16 \x01(\tR\tcommandId\"\xe0\a\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\x12*\n" + + "\x11sender_country_id\x18\f \x01(\x03R\x0fsenderCountryId\x12%\n" + + "\x0eentitlement_id\x18\r \x01(\tR\rentitlementId\x12\x16\n" + + "\x06source\x18\x0e \x01(\tR\x06source\x12T\n" + + "\x12target_host_scopes\x18\x0f \x03(\v2&.hyapp.room.v1.SendGiftTargetHostScopeR\x10targetHostScopes\x12[\n" + + "\x16sender_display_profile\x18\x10 \x01(\v2%.hyapp.room.v1.SendGiftDisplayProfileR\x14senderDisplayProfile\x12]\n" + + "\x17target_display_profiles\x18\x11 \x03(\v2%.hyapp.room.v1.SendGiftDisplayProfileR\x15targetDisplayProfiles\x12!\n" + + "\fdisplay_mode\x18\x12 \x01(\tR\vdisplayMode\x12(\n" + + "\x10combo_session_id\x18\x13 \x01(\tR\x0ecomboSessionId\x12\x1b\n" + + "\tbatch_seq\x18\x14 \x01(\x03R\bbatchSeq\x125\n" + + "\x17sender_registered_at_ms\x18\x15 \x01(\x03R\x14senderRegisteredAtMs\"\x9e\x05\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\x12,\n" + + "\x12coin_balance_after\x18\t \x01(\x03R\x10coinBalanceAfter\x129\n" + + "\x19gift_income_balance_after\x18\n" + + " \x01(\x03R\x16giftIncomeBalanceAfter\x12H\n" + + "\rbatch_display\x18\v \x01(\v2#.hyapp.room.v1.SendGiftBatchDisplayR\fbatchDisplay\x12/\n" + + "\x02v2\x18\f \x01(\v2\x1f.hyapp.room.v1.SendGiftResultV2R\x02v2\"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\"S\n" + + "\x19ResolveRoomAppCodeRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x17\n" + + "\aroom_id\x18\x02 \x01(\tR\x06roomId\"7\n" + + "\x1aResolveRoomAppCodeResponse\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\"\x97\x03\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\x12!\n" + + "\fcountry_code\x18\b \x01(\tR\vcountryCode\x12.\n" + + "\x13viewer_country_code\x18\t \x01(\tR\x11viewerCountryCode\x12.\n" + + "\x13all_visible_regions\x18\n" + + " \x01(\bR\x11allVisibleRegions\x12(\n" + + "\x10filter_region_id\x18\v \x01(\x03R\x0efilterRegionId\"\xec\x01\n" + + "\x18ListRoomsByOwnersRequest\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" + + "\x0eowner_user_ids\x18\x03 \x03(\x03R\fownerUserIds\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\"\xd6\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\x12!\n" + + "\fcountry_code\x18\x10 \x01(\tR\vcountryCode\"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\"\xbe\x01\n" + + "\x1fListRoomContributionRankRequest\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" + + "\x06period\x18\x03 \x01(\tR\x06period\x12\x14\n" + + "\x05limit\x18\x04 \x01(\x05R\x05limit\x12$\n" + + "\x0eviewer_user_id\x18\x05 \x01(\x03R\fviewerUserId\"\x8a\x02\n" + + " ListRoomContributionRankResponse\x12\x17\n" + + "\aroom_id\x18\x01 \x01(\tR\x06roomId\x12\x16\n" + + "\x06period\x18\x02 \x01(\tR\x06period\x12\x1e\n" + + "\vstart_at_ms\x18\x03 \x01(\x03R\tstartAtMs\x12\x1a\n" + + "\tend_at_ms\x18\x04 \x01(\x03R\aendAtMs\x12=\n" + + "\x05items\x18\x05 \x03(\v2'.hyapp.room.v1.RoomContributionRankItemR\x05items\x12\x14\n" + + "\x05total\x18\x06 \x01(\x03R\x05total\x12$\n" + + "\x0eserver_time_ms\x18\a \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\fserverTimeMs\"\xe4\x01\n" + + "\x10SendGiftLuckyHit\x12\x1d\n" + + "\n" + + "gift_index\x18\x01 \x01(\x05R\tgiftIndex\x12\x17\n" + + "\adraw_id\x18\x02 \x01(\tR\x06drawId\x12$\n" + + "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x12(\n" + + "\x10selected_tier_id\x18\x04 \x01(\tR\x0eselectedTierId\x12%\n" + + "\x0emultiplier_ppm\x18\x05 \x01(\x03R\rmultiplierPpm\x12!\n" + + "\freward_coins\x18\x06 \x01(\x03R\vrewardCoins\"\xb1\a\n" + + "\x10SendGiftResultV2\x12\x1f\n" + + "\vapi_version\x18\x01 \x01(\x05R\n" + + "apiVersion\x12\x1d\n" + + "\n" + + "command_id\x18\x02 \x01(\tR\tcommandId\x12(\n" + + "\x10combo_session_id\x18\x03 \x01(\tR\x0ecomboSessionId\x12\x1b\n" + + "\tbatch_seq\x18\x04 \x01(\x03R\bbatchSeq\x12+\n" + + "\x11idempotent_replay\x18\x05 \x01(\bR\x10idempotentReplay\x124\n" + + "\x16committed_room_version\x18\x06 \x01(\x03R\x14committedRoomVersion\x12,\n" + + "\x12billing_receipt_id\x18\a \x01(\tR\x10billingReceiptId\x12,\n" + + "\x12coin_balance_after\x18\b \x01(\x03R\x10coinBalanceAfter\x129\n" + + "\x19gift_income_balance_after\x18\t \x01(\x03R\x16giftIncomeBalanceAfter\x12,\n" + + "\x12settled_gift_count\x18\n" + + " \x01(\x05R\x10settledGiftCount\x125\n" + + "\x17settled_target_user_ids\x18\v \x03(\x03R\x14settledTargetUserIds\x12'\n" + + "\x0fbalance_version\x18\f \x01(\x03R\x0ebalanceVersion\x12A\n" + + "\n" + + "lucky_gift\x18\r \x01(\v2\".hyapp.room.v1.LuckyGiftDrawResultR\tluckyGift\x12C\n" + + "\vlucky_gifts\x18\x0e \x03(\v2\".hyapp.room.v1.LuckyGiftDrawResultR\n" + + "luckyGifts\x12>\n" + + "\n" + + "lucky_hits\x18\x0f \x03(\v2\x1f.hyapp.room.v1.SendGiftLuckyHitR\tluckyHits\x12H\n" + + "\rbatch_display\x18\x10 \x01(\v2#.hyapp.room.v1.SendGiftBatchDisplayR\fbatchDisplay\x12\x1b\n" + + "\troom_heat\x18\x11 \x01(\x03R\broomHeat\x124\n" + + "\tgift_rank\x18\x12 \x03(\v2\x17.hyapp.room.v1.RankItemR\bgiftRank\x12)\n" + + "\x10operation_status\x18\x13 \x01(\tR\x0foperationStatus2\xb2\x1b\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\x12\x90\x01\n" + + "\x1fAdminUpdateHumanRoomRobotConfig\x125.hyapp.room.v1.AdminUpdateHumanRoomRobotConfigRequest\x1a6.hyapp.room.v1.AdminUpdateHumanRoomRobotConfigResponse\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\x12o\n" + + "\x14AdminCreateRobotRoom\x12*.hyapp.room.v1.AdminCreateRobotRoomRequest\x1a+.hyapp.room.v1.AdminCreateRobotRoomResponse\x12x\n" + + "\x17AdminSetRobotRoomStatus\x12-.hyapp.room.v1.AdminSetRobotRoomStatusRequest\x1a..hyapp.room.v1.AdminSetRobotRoomStatusResponse\x12\x84\x01\n" + + "\x1bAdminRenameOwnerCountryCode\x121.hyapp.room.v1.AdminRenameOwnerCountryCodeRequest\x1a2.hyapp.room.v1.AdminRenameOwnerCountryCodeResponse\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\xd9\x02\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.VerifyRoomPresenceResponse\x12i\n" + + "\x12ResolveRoomAppCode\x12(.hyapp.room.v1.ResolveRoomAppCodeRequest\x1a).hyapp.room.v1.ResolveRoomAppCodeResponse2\xe4\x10\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\x12\x87\x01\n" + + "\x1cAdminGetHumanRoomRobotConfig\x122.hyapp.room.v1.AdminGetHumanRoomRobotConfigRequest\x1a3.hyapp.room.v1.AdminGetHumanRoomRobotConfigResponse\x12f\n" + + "\x11AdminListRoomPins\x12'.hyapp.room.v1.AdminListRoomPinsRequest\x1a(.hyapp.room.v1.AdminListRoomPinsResponse\x12l\n" + + "\x13AdminListRobotRooms\x12).hyapp.room.v1.AdminListRobotRoomsRequest\x1a*.hyapp.room.v1.AdminListRobotRoomsResponse\x12\x8d\x01\n" + + "\x1eAdminFilterAvailableRoomRobots\x124.hyapp.room.v1.AdminFilterAvailableRoomRobotsRequest\x1a5.hyapp.room.v1.AdminFilterAvailableRoomRobotsResponse\x12N\n" + + "\tListRooms\x12\x1f.hyapp.room.v1.ListRoomsRequest\x1a .hyapp.room.v1.ListRoomsResponse\x12^\n" + + "\x11ListRoomsByOwners\x12'.hyapp.room.v1.ListRoomsByOwnersRequest\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\x12{\n" + + "\x18ListRoomContributionRank\x12..hyapp.room.v1.ListRoomContributionRankRequest\x1a/.hyapp.room.v1.ListRoomContributionRankResponse\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_rawDescOnce sync.Once - file_proto_room_v1_room_proto_rawDescData = file_proto_room_v1_room_proto_rawDesc + file_proto_room_v1_room_proto_rawDescData []byte ) 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(file_proto_room_v1_room_proto_rawDescData) + 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))) }) return file_proto_room_v1_room_proto_rawDescData } @@ -15973,7 +14278,7 @@ func file_proto_room_v1_room_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_room_v1_room_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_room_v1_room_proto_rawDesc), len(file_proto_room_v1_room_proto_rawDesc)), NumEnums: 0, NumMessages: 159, NumExtensions: 0, @@ -15984,7 +14289,6 @@ 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_grpc.pb.go b/api/proto/room/v1/room_grpc.pb.go index b647f921..fcc21dab 100644 --- a/api/proto/room/v1/room_grpc.pb.go +++ b/api/proto/room/v1/room_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.6.2 -// - protoc v5.29.2 +// - protoc v7.35.0 // source: proto/room/v1/room.proto package roomv1 diff --git a/api/proto/user/v1/auth.pb.go b/api/proto/user/v1/auth.pb.go index 6e480cdf..0dd2dc3e 100644 --- a/api/proto/user/v1/auth.pb.go +++ b/api/proto/user/v1/auth.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v5.29.2 +// protoc v7.35.0 // source: proto/user/v1/auth.proto package userv1 @@ -1001,11 +1001,13 @@ func (x *QuickCreateAccountResponse) GetPasswordSet() bool { // RefreshTokenRequest 使用 refresh token 换取新 token。 type RefreshTokenRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RefreshToken string `protobuf:"bytes,2,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,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"` + RefreshToken string `protobuf:"bytes,2,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"` + // refresh_request_id 由客户端按一次 refresh 尝试生成,网络重试必须复用;旧客户端可为空。 + RefreshRequestId string `protobuf:"bytes,3,opt,name=refresh_request_id,json=refreshRequestId,proto3" json:"refresh_request_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RefreshTokenRequest) Reset() { @@ -1052,6 +1054,13 @@ func (x *RefreshTokenRequest) GetRefreshToken() string { return "" } +func (x *RefreshTokenRequest) GetRefreshRequestId() string { + if x != nil { + return x.RefreshRequestId + } + return "" +} + // RefreshTokenResponse 返回轮换后的令牌。 type RefreshTokenResponse struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -2048,10 +2057,11 @@ const file_proto_user_v1_auth_proto_rawDesc = "" + "\btimezone\x18\x13 \x01(\tR\btimezone\"o\n" + "\x1aQuickCreateAccountResponse\x12.\n" + "\x05token\x18\x01 \x01(\v2\x18.hyapp.user.v1.AuthTokenR\x05token\x12!\n" + - "\fpassword_set\x18\x02 \x01(\bR\vpasswordSet\"j\n" + + "\fpassword_set\x18\x02 \x01(\bR\vpasswordSet\"\x98\x01\n" + "\x13RefreshTokenRequest\x12.\n" + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12#\n" + - "\rrefresh_token\x18\x02 \x01(\tR\frefreshToken\"F\n" + + "\rrefresh_token\x18\x02 \x01(\tR\frefreshToken\x12,\n" + + "\x12refresh_request_id\x18\x03 \x01(\tR\x10refreshRequestId\"F\n" + "\x14RefreshTokenResponse\x12.\n" + "\x05token\x18\x01 \x01(\v2\x18.hyapp.user.v1.AuthTokenR\x05token\"\x83\x01\n" + "\rLogoutRequest\x12.\n" + diff --git a/api/proto/user/v1/auth.proto b/api/proto/user/v1/auth.proto index 01cca86a..b65798eb 100644 --- a/api/proto/user/v1/auth.proto +++ b/api/proto/user/v1/auth.proto @@ -126,6 +126,8 @@ message QuickCreateAccountResponse { message RefreshTokenRequest { RequestMeta meta = 1; string refresh_token = 2; + // refresh_request_id 由客户端按一次 refresh 尝试生成,网络重试必须复用;旧客户端可为空。 + string refresh_request_id = 3; } // RefreshTokenResponse 返回轮换后的令牌。 diff --git a/api/proto/user/v1/auth_grpc.pb.go b/api/proto/user/v1/auth_grpc.pb.go index 97e929a5..c7a713cf 100644 --- a/api/proto/user/v1/auth_grpc.pb.go +++ b/api/proto/user/v1/auth_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.6.2 -// - protoc v5.29.2 +// - protoc v7.35.0 // source: proto/user/v1/auth.proto package userv1 diff --git a/api/proto/user/v1/host.pb.go b/api/proto/user/v1/host.pb.go index 0d0855a5..6c41d455 100644 --- a/api/proto/user/v1/host.pb.go +++ b/api/proto/user/v1/host.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v5.29.2 +// protoc v7.35.0 // source: proto/user/v1/host.proto package userv1 diff --git a/api/proto/user/v1/host_grpc.pb.go b/api/proto/user/v1/host_grpc.pb.go index 999c6526..d9959a03 100644 --- a/api/proto/user/v1/host_grpc.pb.go +++ b/api/proto/user/v1/host_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.6.2 -// - protoc v5.29.2 +// - protoc v7.35.0 // source: proto/user/v1/host.proto package userv1 diff --git a/api/proto/user/v1/user.pb.go b/api/proto/user/v1/user.pb.go index 6b7c3f64..90594456 100644 --- a/api/proto/user/v1/user.pb.go +++ b/api/proto/user/v1/user.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.36.11 // protoc v7.35.0 // source: proto/user/v1/user.proto @@ -11,6 +11,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -75,23 +76,20 @@ func (UserStatus) EnumDescriptor() ([]byte, []int) { // RequestMeta 是 user-service 所有内部 RPC 的最小追踪元信息。 type RequestMeta struct { - 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"` - Caller string `protobuf:"bytes,2,opt,name=caller,proto3" json:"caller,omitempty"` - GatewayNodeId string `protobuf:"bytes,3,opt,name=gateway_node_id,json=gatewayNodeId,proto3" json:"gateway_node_id,omitempty"` - SentAtMs int64 `protobuf:"varint,4,opt,name=sent_at_ms,json=sentAtMs,proto3" json:"sent_at_ms,omitempty"` - DeviceId string `protobuf:"bytes,5,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` - ClientIp string `protobuf:"bytes,6,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` - UserAgent string `protobuf:"bytes,7,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"` - CountryByIp string `protobuf:"bytes,8,opt,name=country_by_ip,json=countryByIp,proto3" json:"country_by_ip,omitempty"` - SessionId string `protobuf:"bytes,9,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` - AppCode string `protobuf:"bytes,10,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - Platform string `protobuf:"bytes,11,opt,name=platform,proto3" json:"platform,omitempty"` - Language string `protobuf:"bytes,12,opt,name=language,proto3" json:"language,omitempty"` - Timezone string `protobuf:"bytes,13,opt,name=timezone,proto3" json:"timezone,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + Caller string `protobuf:"bytes,2,opt,name=caller,proto3" json:"caller,omitempty"` + GatewayNodeId string `protobuf:"bytes,3,opt,name=gateway_node_id,json=gatewayNodeId,proto3" json:"gateway_node_id,omitempty"` + SentAtMs int64 `protobuf:"varint,4,opt,name=sent_at_ms,json=sentAtMs,proto3" json:"sent_at_ms,omitempty"` + DeviceId string `protobuf:"bytes,5,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` + ClientIp string `protobuf:"bytes,6,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` + UserAgent string `protobuf:"bytes,7,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"` + CountryByIp string `protobuf:"bytes,8,opt,name=country_by_ip,json=countryByIp,proto3" json:"country_by_ip,omitempty"` + SessionId string `protobuf:"bytes,9,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + AppCode string `protobuf:"bytes,10,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + Platform string `protobuf:"bytes,11,opt,name=platform,proto3" json:"platform,omitempty"` + Language string `protobuf:"bytes,12,opt,name=language,proto3" json:"language,omitempty"` + Timezone string `protobuf:"bytes,13,opt,name=timezone,proto3" json:"timezone,omitempty"` // app_version/build_number 记录发起本次 RPC 的客户端构建;认证链路依赖它们把每次成功登录归档到 login_audit。 AppVersion string `protobuf:"bytes,14,opt,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"` BuildNumber string `protobuf:"bytes,15,opt,name=build_number,json=buildNumber,proto3" json:"build_number,omitempty"` @@ -102,6 +100,8 @@ type RequestMeta struct { DeviceManufacturer string `protobuf:"bytes,17,opt,name=device_manufacturer,json=deviceManufacturer,proto3" json:"device_manufacturer,omitempty"` OsVersion string `protobuf:"bytes,18,opt,name=os_version,json=osVersion,proto3" json:"os_version,omitempty"` Imei string `protobuf:"bytes,19,opt,name=imei,proto3" json:"imei,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RequestMeta) Reset() { @@ -269,18 +269,17 @@ func (x *RequestMeta) GetImei() string { // App 是 user-service 维护的 App 注册表投影,用于把客户端包名映射到内部租户键。 type App struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + AppId int64 `protobuf:"varint,1,opt,name=app_id,json=appId,proto3" json:"app_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + AppName string `protobuf:"bytes,3,opt,name=app_name,json=appName,proto3" json:"app_name,omitempty"` + PackageName string `protobuf:"bytes,4,opt,name=package_name,json=packageName,proto3" json:"package_name,omitempty"` + Platform string `protobuf:"bytes,5,opt,name=platform,proto3" json:"platform,omitempty"` + Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` + CreatedAtMs int64 `protobuf:"varint,7,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,8,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` unknownFields protoimpl.UnknownFields - - AppId int64 `protobuf:"varint,1,opt,name=app_id,json=appId,proto3" json:"app_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - AppName string `protobuf:"bytes,3,opt,name=app_name,json=appName,proto3" json:"app_name,omitempty"` - PackageName string `protobuf:"bytes,4,opt,name=package_name,json=packageName,proto3" json:"package_name,omitempty"` - Platform string `protobuf:"bytes,5,opt,name=platform,proto3" json:"platform,omitempty"` - Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` - CreatedAtMs int64 `protobuf:"varint,7,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,8,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *App) Reset() { @@ -371,14 +370,13 @@ func (x *App) GetUpdatedAtMs() int64 { // ResolveAppRequest 允许 gateway 按包名/平台解析 app_code,也允许后台显式校验 app_code。 type ResolveAppRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + PackageName string `protobuf:"bytes,2,opt,name=package_name,json=packageName,proto3" json:"package_name,omitempty"` + Platform string `protobuf:"bytes,3,opt,name=platform,proto3" json:"platform,omitempty"` + AppCode string `protobuf:"bytes,4,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - PackageName string `protobuf:"bytes,2,opt,name=package_name,json=packageName,proto3" json:"package_name,omitempty"` - Platform string `protobuf:"bytes,3,opt,name=platform,proto3" json:"platform,omitempty"` - AppCode string `protobuf:"bytes,4,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ResolveAppRequest) Reset() { @@ -440,11 +438,10 @@ func (x *ResolveAppRequest) GetAppCode() string { } type ResolveAppResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + App *App `protobuf:"bytes,1,opt,name=app,proto3" json:"app,omitempty"` unknownFields protoimpl.UnknownFields - - App *App `protobuf:"bytes,1,opt,name=app,proto3" json:"app,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ResolveAppResponse) Reset() { @@ -486,43 +483,42 @@ func (x *ResolveAppResponse) GetApp() *App { // User 是用户主数据投影,包含稳定身份、当前短号和基础资料。 type User struct { - 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"` - Status UserStatus `protobuf:"varint,2,opt,name=status,proto3,enum=hyapp.user.v1.UserStatus" json:"status,omitempty"` - CreatedAtMs int64 `protobuf:"varint,3,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,4,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - DisplayUserId string `protobuf:"bytes,5,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` - DefaultDisplayUserId string `protobuf:"bytes,6,opt,name=default_display_user_id,json=defaultDisplayUserId,proto3" json:"default_display_user_id,omitempty"` - DisplayUserIdKind string `protobuf:"bytes,7,opt,name=display_user_id_kind,json=displayUserIdKind,proto3" json:"display_user_id_kind,omitempty"` - DisplayUserIdExpiresAtMs int64 `protobuf:"varint,8,opt,name=display_user_id_expires_at_ms,json=displayUserIdExpiresAtMs,proto3" json:"display_user_id_expires_at_ms,omitempty"` - Username string `protobuf:"bytes,9,opt,name=username,proto3" json:"username,omitempty"` - Gender string `protobuf:"bytes,10,opt,name=gender,proto3" json:"gender,omitempty"` - Country string `protobuf:"bytes,11,opt,name=country,proto3" json:"country,omitempty"` - Avatar string `protobuf:"bytes,12,opt,name=avatar,proto3" json:"avatar,omitempty"` - Birth string `protobuf:"bytes,13,opt,name=birth,proto3" json:"birth,omitempty"` - Language string `protobuf:"bytes,14,opt,name=language,proto3" json:"language,omitempty"` - CountryId int64 `protobuf:"varint,15,opt,name=country_id,json=countryId,proto3" json:"country_id,omitempty"` - CountryName string `protobuf:"bytes,16,opt,name=country_name,json=countryName,proto3" json:"country_name,omitempty"` - CountryDisplayName string `protobuf:"bytes,17,opt,name=country_display_name,json=countryDisplayName,proto3" json:"country_display_name,omitempty"` - RegionId int64 `protobuf:"varint,18,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - RegionCode string `protobuf:"bytes,19,opt,name=region_code,json=regionCode,proto3" json:"region_code,omitempty"` - RegionName string `protobuf:"bytes,20,opt,name=region_name,json=regionName,proto3" json:"region_name,omitempty"` - ProfileCompleted bool `protobuf:"varint,21,opt,name=profile_completed,json=profileCompleted,proto3" json:"profile_completed,omitempty"` - ProfileCompletedAtMs int64 `protobuf:"varint,22,opt,name=profile_completed_at_ms,json=profileCompletedAtMs,proto3" json:"profile_completed_at_ms,omitempty"` - OnboardingStatus string `protobuf:"bytes,23,opt,name=onboarding_status,json=onboardingStatus,proto3" json:"onboarding_status,omitempty"` - IsoNumeric string `protobuf:"bytes,24,opt,name=iso_numeric,json=isoNumeric,proto3" json:"iso_numeric,omitempty"` - PhoneCountryCode string `protobuf:"bytes,25,opt,name=phone_country_code,json=phoneCountryCode,proto3" json:"phone_country_code,omitempty"` - CountryEnabled bool `protobuf:"varint,26,opt,name=country_enabled,json=countryEnabled,proto3" json:"country_enabled,omitempty"` - AppCode string `protobuf:"bytes,27,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - Invite *InviteOverview `protobuf:"bytes,28,opt,name=invite,proto3" json:"invite,omitempty"` - PrettyId string `protobuf:"bytes,29,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_id,omitempty"` - PrettyDisplayUserId string `protobuf:"bytes,30,opt,name=pretty_display_user_id,json=prettyDisplayUserId,proto3" json:"pretty_display_user_id,omitempty"` - ProfileBgImg string `protobuf:"bytes,31,opt,name=profile_bg_img,json=profileBgImg,proto3" json:"profile_bg_img,omitempty"` - ContactInfo string `protobuf:"bytes,32,opt,name=contact_info,json=contactInfo,proto3" json:"contact_info,omitempty"` - WithdrawUsdtTrc20Address string `protobuf:"bytes,33,opt,name=withdraw_usdt_trc20_address,json=withdrawUsdtTrc20Address,proto3" json:"withdraw_usdt_trc20_address,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Status UserStatus `protobuf:"varint,2,opt,name=status,proto3,enum=hyapp.user.v1.UserStatus" json:"status,omitempty"` + CreatedAtMs int64 `protobuf:"varint,3,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,4,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + DisplayUserId string `protobuf:"bytes,5,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` + DefaultDisplayUserId string `protobuf:"bytes,6,opt,name=default_display_user_id,json=defaultDisplayUserId,proto3" json:"default_display_user_id,omitempty"` + DisplayUserIdKind string `protobuf:"bytes,7,opt,name=display_user_id_kind,json=displayUserIdKind,proto3" json:"display_user_id_kind,omitempty"` + DisplayUserIdExpiresAtMs int64 `protobuf:"varint,8,opt,name=display_user_id_expires_at_ms,json=displayUserIdExpiresAtMs,proto3" json:"display_user_id_expires_at_ms,omitempty"` + Username string `protobuf:"bytes,9,opt,name=username,proto3" json:"username,omitempty"` + Gender string `protobuf:"bytes,10,opt,name=gender,proto3" json:"gender,omitempty"` + Country string `protobuf:"bytes,11,opt,name=country,proto3" json:"country,omitempty"` + Avatar string `protobuf:"bytes,12,opt,name=avatar,proto3" json:"avatar,omitempty"` + Birth string `protobuf:"bytes,13,opt,name=birth,proto3" json:"birth,omitempty"` + Language string `protobuf:"bytes,14,opt,name=language,proto3" json:"language,omitempty"` + CountryId int64 `protobuf:"varint,15,opt,name=country_id,json=countryId,proto3" json:"country_id,omitempty"` + CountryName string `protobuf:"bytes,16,opt,name=country_name,json=countryName,proto3" json:"country_name,omitempty"` + CountryDisplayName string `protobuf:"bytes,17,opt,name=country_display_name,json=countryDisplayName,proto3" json:"country_display_name,omitempty"` + RegionId int64 `protobuf:"varint,18,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + RegionCode string `protobuf:"bytes,19,opt,name=region_code,json=regionCode,proto3" json:"region_code,omitempty"` + RegionName string `protobuf:"bytes,20,opt,name=region_name,json=regionName,proto3" json:"region_name,omitempty"` + ProfileCompleted bool `protobuf:"varint,21,opt,name=profile_completed,json=profileCompleted,proto3" json:"profile_completed,omitempty"` + ProfileCompletedAtMs int64 `protobuf:"varint,22,opt,name=profile_completed_at_ms,json=profileCompletedAtMs,proto3" json:"profile_completed_at_ms,omitempty"` + OnboardingStatus string `protobuf:"bytes,23,opt,name=onboarding_status,json=onboardingStatus,proto3" json:"onboarding_status,omitempty"` + IsoNumeric string `protobuf:"bytes,24,opt,name=iso_numeric,json=isoNumeric,proto3" json:"iso_numeric,omitempty"` + PhoneCountryCode string `protobuf:"bytes,25,opt,name=phone_country_code,json=phoneCountryCode,proto3" json:"phone_country_code,omitempty"` + CountryEnabled bool `protobuf:"varint,26,opt,name=country_enabled,json=countryEnabled,proto3" json:"country_enabled,omitempty"` + AppCode string `protobuf:"bytes,27,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + Invite *InviteOverview `protobuf:"bytes,28,opt,name=invite,proto3" json:"invite,omitempty"` + PrettyId string `protobuf:"bytes,29,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_id,omitempty"` + PrettyDisplayUserId string `protobuf:"bytes,30,opt,name=pretty_display_user_id,json=prettyDisplayUserId,proto3" json:"pretty_display_user_id,omitempty"` + ProfileBgImg string `protobuf:"bytes,31,opt,name=profile_bg_img,json=profileBgImg,proto3" json:"profile_bg_img,omitempty"` + ContactInfo string `protobuf:"bytes,32,opt,name=contact_info,json=contactInfo,proto3" json:"contact_info,omitempty"` + WithdrawUsdtTrc20Address string `protobuf:"bytes,33,opt,name=withdraw_usdt_trc20_address,json=withdrawUsdtTrc20Address,proto3" json:"withdraw_usdt_trc20_address,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *User) Reset() { @@ -788,15 +784,14 @@ func (x *User) GetWithdrawUsdtTrc20Address() string { // InviteOverview 是我的页可直接展示的邀请码和邀请计数 read model。 type InviteOverview struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - MyInviteCode string `protobuf:"bytes,1,opt,name=my_invite_code,json=myInviteCode,proto3" json:"my_invite_code,omitempty"` - InviteEnabled bool `protobuf:"varint,2,opt,name=invite_enabled,json=inviteEnabled,proto3" json:"invite_enabled,omitempty"` - InviteCount int64 `protobuf:"varint,3,opt,name=invite_count,json=inviteCount,proto3" json:"invite_count,omitempty"` - ValidInviteCount int64 `protobuf:"varint,4,opt,name=valid_invite_count,json=validInviteCount,proto3" json:"valid_invite_count,omitempty"` - ValidInviteThresholdCoin int64 `protobuf:"varint,5,opt,name=valid_invite_threshold_coin,json=validInviteThresholdCoin,proto3" json:"valid_invite_threshold_coin,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + MyInviteCode string `protobuf:"bytes,1,opt,name=my_invite_code,json=myInviteCode,proto3" json:"my_invite_code,omitempty"` + InviteEnabled bool `protobuf:"varint,2,opt,name=invite_enabled,json=inviteEnabled,proto3" json:"invite_enabled,omitempty"` + InviteCount int64 `protobuf:"varint,3,opt,name=invite_count,json=inviteCount,proto3" json:"invite_count,omitempty"` + ValidInviteCount int64 `protobuf:"varint,4,opt,name=valid_invite_count,json=validInviteCount,proto3" json:"valid_invite_count,omitempty"` + ValidInviteThresholdCoin int64 `protobuf:"varint,5,opt,name=valid_invite_threshold_coin,json=validInviteThresholdCoin,proto3" json:"valid_invite_threshold_coin,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *InviteOverview) Reset() { @@ -866,13 +861,12 @@ func (x *InviteOverview) GetValidInviteThresholdCoin() int64 { // InviteBinding 表示注册完成请求本次是否新绑定邀请关系。 type InviteBinding struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Bound bool `protobuf:"varint,1,opt,name=bound,proto3" json:"bound,omitempty"` + InviteCode string `protobuf:"bytes,2,opt,name=invite_code,json=inviteCode,proto3" json:"invite_code,omitempty"` + InviterUserId int64 `protobuf:"varint,3,opt,name=inviter_user_id,json=inviterUserId,proto3" json:"inviter_user_id,omitempty"` unknownFields protoimpl.UnknownFields - - Bound bool `protobuf:"varint,1,opt,name=bound,proto3" json:"bound,omitempty"` - InviteCode string `protobuf:"bytes,2,opt,name=invite_code,json=inviteCode,proto3" json:"invite_code,omitempty"` - InviterUserId int64 `protobuf:"varint,3,opt,name=inviter_user_id,json=inviterUserId,proto3" json:"inviter_user_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *InviteBinding) Reset() { @@ -928,20 +922,19 @@ func (x *InviteBinding) GetInviterUserId() int64 { // InviteAttribution 是被邀请用户到邀请人的只读归因快照,供活动服务按充值事实累计邀请奖励。 type InviteAttribution struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Found bool `protobuf:"varint,1,opt,name=found,proto3" json:"found,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - InvitedUserId int64 `protobuf:"varint,3,opt,name=invited_user_id,json=invitedUserId,proto3" json:"invited_user_id,omitempty"` - InviterUserId int64 `protobuf:"varint,4,opt,name=inviter_user_id,json=inviterUserId,proto3" json:"inviter_user_id,omitempty"` - InviteCode string `protobuf:"bytes,5,opt,name=invite_code,json=inviteCode,proto3" json:"invite_code,omitempty"` - BoundAtMs int64 `protobuf:"varint,6,opt,name=bound_at_ms,json=boundAtMs,proto3" json:"bound_at_ms,omitempty"` - ValidityStatus string `protobuf:"bytes,7,opt,name=validity_status,json=validityStatus,proto3" json:"validity_status,omitempty"` - AccumulatedRechargeCoinAmount int64 `protobuf:"varint,8,opt,name=accumulated_recharge_coin_amount,json=accumulatedRechargeCoinAmount,proto3" json:"accumulated_recharge_coin_amount,omitempty"` - RequiredRechargeCoinAmount int64 `protobuf:"varint,9,opt,name=required_recharge_coin_amount,json=requiredRechargeCoinAmount,proto3" json:"required_recharge_coin_amount,omitempty"` - ValidAtMs int64 `protobuf:"varint,10,opt,name=valid_at_ms,json=validAtMs,proto3" json:"valid_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Found bool `protobuf:"varint,1,opt,name=found,proto3" json:"found,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + InvitedUserId int64 `protobuf:"varint,3,opt,name=invited_user_id,json=invitedUserId,proto3" json:"invited_user_id,omitempty"` + InviterUserId int64 `protobuf:"varint,4,opt,name=inviter_user_id,json=inviterUserId,proto3" json:"inviter_user_id,omitempty"` + InviteCode string `protobuf:"bytes,5,opt,name=invite_code,json=inviteCode,proto3" json:"invite_code,omitempty"` + BoundAtMs int64 `protobuf:"varint,6,opt,name=bound_at_ms,json=boundAtMs,proto3" json:"bound_at_ms,omitempty"` + ValidityStatus string `protobuf:"bytes,7,opt,name=validity_status,json=validityStatus,proto3" json:"validity_status,omitempty"` + AccumulatedRechargeCoinAmount int64 `protobuf:"varint,8,opt,name=accumulated_recharge_coin_amount,json=accumulatedRechargeCoinAmount,proto3" json:"accumulated_recharge_coin_amount,omitempty"` + RequiredRechargeCoinAmount int64 `protobuf:"varint,9,opt,name=required_recharge_coin_amount,json=requiredRechargeCoinAmount,proto3" json:"required_recharge_coin_amount,omitempty"` + ValidAtMs int64 `protobuf:"varint,10,opt,name=valid_at_ms,json=validAtMs,proto3" json:"valid_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *InviteAttribution) Reset() { @@ -1045,12 +1038,11 @@ func (x *InviteAttribution) GetValidAtMs() int64 { } type GetInviteAttributionRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + InvitedUserId int64 `protobuf:"varint,2,opt,name=invited_user_id,json=invitedUserId,proto3" json:"invited_user_id,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - InvitedUserId int64 `protobuf:"varint,2,opt,name=invited_user_id,json=invitedUserId,proto3" json:"invited_user_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetInviteAttributionRequest) Reset() { @@ -1098,11 +1090,10 @@ func (x *GetInviteAttributionRequest) GetInvitedUserId() int64 { } type GetInviteAttributionResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Attribution *InviteAttribution `protobuf:"bytes,1,opt,name=attribution,proto3" json:"attribution,omitempty"` unknownFields protoimpl.UnknownFields - - Attribution *InviteAttribution `protobuf:"bytes,1,opt,name=attribution,proto3" json:"attribution,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetInviteAttributionResponse) Reset() { @@ -1144,18 +1135,17 @@ func (x *GetInviteAttributionResponse) GetAttribution() *InviteAttribution { // UserMicLifetimeStats 是用户维度的麦上累计基础指标,不区分主播/公会身份。 type UserMicLifetimeStats struct { - 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"` - SeatOccupiedMs int64 `protobuf:"varint,2,opt,name=seat_occupied_ms,json=seatOccupiedMs,proto3" json:"seat_occupied_ms,omitempty"` - MicOnlineMs int64 `protobuf:"varint,3,opt,name=mic_online_ms,json=micOnlineMs,proto3" json:"mic_online_ms,omitempty"` - SessionCount int64 `protobuf:"varint,4,opt,name=session_count,json=sessionCount,proto3" json:"session_count,omitempty"` - FirstMicAtMs int64 `protobuf:"varint,5,opt,name=first_mic_at_ms,json=firstMicAtMs,proto3" json:"first_mic_at_ms,omitempty"` - LastMicAtMs int64 `protobuf:"varint,6,opt,name=last_mic_at_ms,json=lastMicAtMs,proto3" json:"last_mic_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,7,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - AppCode string `protobuf:"bytes,8,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + SeatOccupiedMs int64 `protobuf:"varint,2,opt,name=seat_occupied_ms,json=seatOccupiedMs,proto3" json:"seat_occupied_ms,omitempty"` + MicOnlineMs int64 `protobuf:"varint,3,opt,name=mic_online_ms,json=micOnlineMs,proto3" json:"mic_online_ms,omitempty"` + SessionCount int64 `protobuf:"varint,4,opt,name=session_count,json=sessionCount,proto3" json:"session_count,omitempty"` + FirstMicAtMs int64 `protobuf:"varint,5,opt,name=first_mic_at_ms,json=firstMicAtMs,proto3" json:"first_mic_at_ms,omitempty"` + LastMicAtMs int64 `protobuf:"varint,6,opt,name=last_mic_at_ms,json=lastMicAtMs,proto3" json:"last_mic_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,7,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_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 *UserMicLifetimeStats) Reset() { @@ -1246,12 +1236,11 @@ func (x *UserMicLifetimeStats) GetAppCode() string { // GetUserMicLifetimeStatsRequest 查询单个用户全部历史麦位时长。 type GetUserMicLifetimeStatsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetUserMicLifetimeStatsRequest) Reset() { @@ -1299,11 +1288,10 @@ func (x *GetUserMicLifetimeStatsRequest) GetUserId() int64 { } type GetUserMicLifetimeStatsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Stats *UserMicLifetimeStats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"` unknownFields protoimpl.UnknownFields - - Stats *UserMicLifetimeStats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetUserMicLifetimeStatsResponse) Reset() { @@ -1345,18 +1333,17 @@ func (x *GetUserMicLifetimeStatsResponse) GetStats() *UserMicLifetimeStats { // CronBatchRequest 是 cron-service 触发 user-service 后台批处理的统一请求。 type CronBatchRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RunId string `protobuf:"bytes,2,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"` - WorkerId string `protobuf:"bytes,3,opt,name=worker_id,json=workerId,proto3" json:"worker_id,omitempty"` - BatchSize int32 `protobuf:"varint,4,opt,name=batch_size,json=batchSize,proto3" json:"batch_size,omitempty"` - LockTtlMs int64 `protobuf:"varint,5,opt,name=lock_ttl_ms,json=lockTtlMs,proto3" json:"lock_ttl_ms,omitempty"` - PendingPublishMaxAgeMs int64 `protobuf:"varint,6,opt,name=pending_publish_max_age_ms,json=pendingPublishMaxAgeMs,proto3" json:"pending_publish_max_age_ms,omitempty"` - PublishingSessionMaxAgeMs int64 `protobuf:"varint,7,opt,name=publishing_session_max_age_ms,json=publishingSessionMaxAgeMs,proto3" json:"publishing_session_max_age_ms,omitempty"` - OpenSessionMaxAgeMs int64 `protobuf:"varint,8,opt,name=open_session_max_age_ms,json=openSessionMaxAgeMs,proto3" json:"open_session_max_age_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RunId string `protobuf:"bytes,2,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"` + WorkerId string `protobuf:"bytes,3,opt,name=worker_id,json=workerId,proto3" json:"worker_id,omitempty"` + BatchSize int32 `protobuf:"varint,4,opt,name=batch_size,json=batchSize,proto3" json:"batch_size,omitempty"` + LockTtlMs int64 `protobuf:"varint,5,opt,name=lock_ttl_ms,json=lockTtlMs,proto3" json:"lock_ttl_ms,omitempty"` + PendingPublishMaxAgeMs int64 `protobuf:"varint,6,opt,name=pending_publish_max_age_ms,json=pendingPublishMaxAgeMs,proto3" json:"pending_publish_max_age_ms,omitempty"` + PublishingSessionMaxAgeMs int64 `protobuf:"varint,7,opt,name=publishing_session_max_age_ms,json=publishingSessionMaxAgeMs,proto3" json:"publishing_session_max_age_ms,omitempty"` + OpenSessionMaxAgeMs int64 `protobuf:"varint,8,opt,name=open_session_max_age_ms,json=openSessionMaxAgeMs,proto3" json:"open_session_max_age_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CronBatchRequest) Reset() { @@ -1447,15 +1434,14 @@ func (x *CronBatchRequest) GetOpenSessionMaxAgeMs() int64 { // CronBatchResponse 返回一个批处理 run 的执行摘要。 type CronBatchResponse struct { - 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"` + 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 } func (x *CronBatchResponse) Reset() { @@ -1525,23 +1511,22 @@ func (x *CronBatchResponse) GetHasMore() bool { // AuthToken 是登录、刷新和注册完成后返回给 gateway 的访问令牌投影。 type AuthToken struct { - 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"` - SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` - AccessToken string `protobuf:"bytes,3,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"` - RefreshToken string `protobuf:"bytes,4,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"` - ExpiresInSec int64 `protobuf:"varint,5,opt,name=expires_in_sec,json=expiresInSec,proto3" json:"expires_in_sec,omitempty"` - TokenType string `protobuf:"bytes,6,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"` - DisplayUserId string `protobuf:"bytes,7,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` - DefaultDisplayUserId string `protobuf:"bytes,8,opt,name=default_display_user_id,json=defaultDisplayUserId,proto3" json:"default_display_user_id,omitempty"` - DisplayUserIdKind string `protobuf:"bytes,9,opt,name=display_user_id_kind,json=displayUserIdKind,proto3" json:"display_user_id_kind,omitempty"` - DisplayUserIdExpiresAtMs int64 `protobuf:"varint,10,opt,name=display_user_id_expires_at_ms,json=displayUserIdExpiresAtMs,proto3" json:"display_user_id_expires_at_ms,omitempty"` - ProfileCompleted bool `protobuf:"varint,11,opt,name=profile_completed,json=profileCompleted,proto3" json:"profile_completed,omitempty"` - OnboardingStatus string `protobuf:"bytes,12,opt,name=onboarding_status,json=onboardingStatus,proto3" json:"onboarding_status,omitempty"` - AppCode string `protobuf:"bytes,13,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + AccessToken string `protobuf:"bytes,3,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"` + RefreshToken string `protobuf:"bytes,4,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"` + ExpiresInSec int64 `protobuf:"varint,5,opt,name=expires_in_sec,json=expiresInSec,proto3" json:"expires_in_sec,omitempty"` + TokenType string `protobuf:"bytes,6,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"` + DisplayUserId string `protobuf:"bytes,7,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` + DefaultDisplayUserId string `protobuf:"bytes,8,opt,name=default_display_user_id,json=defaultDisplayUserId,proto3" json:"default_display_user_id,omitempty"` + DisplayUserIdKind string `protobuf:"bytes,9,opt,name=display_user_id_kind,json=displayUserIdKind,proto3" json:"display_user_id_kind,omitempty"` + DisplayUserIdExpiresAtMs int64 `protobuf:"varint,10,opt,name=display_user_id_expires_at_ms,json=displayUserIdExpiresAtMs,proto3" json:"display_user_id_expires_at_ms,omitempty"` + ProfileCompleted bool `protobuf:"varint,11,opt,name=profile_completed,json=profileCompleted,proto3" json:"profile_completed,omitempty"` + OnboardingStatus string `protobuf:"bytes,12,opt,name=onboarding_status,json=onboardingStatus,proto3" json:"onboarding_status,omitempty"` + AppCode string `protobuf:"bytes,13,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AuthToken) Reset() { @@ -1667,12 +1652,11 @@ func (x *AuthToken) GetAppCode() string { // GetUserRequest 查询单个用户主状态。 type GetUserRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetUserRequest) Reset() { @@ -1721,11 +1705,10 @@ func (x *GetUserRequest) GetUserId() int64 { // GetUserResponse 返回单个用户主状态。 type GetUserResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` unknownFields protoimpl.UnknownFields - - User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetUserResponse) Reset() { @@ -1766,15 +1749,14 @@ func (x *GetUserResponse) GetUser() *User { } type BusinessUserLookupRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + ActorUserId int64 `protobuf:"varint,2,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + Scene string `protobuf:"bytes,3,opt,name=scene,proto3" json:"scene,omitempty"` + Keyword string `protobuf:"bytes,4,opt,name=keyword,proto3" json:"keyword,omitempty"` + PageSize int32 `protobuf:"varint,5,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - ActorUserId int64 `protobuf:"varint,2,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - Scene string `protobuf:"bytes,3,opt,name=scene,proto3" json:"scene,omitempty"` - Keyword string `protobuf:"bytes,4,opt,name=keyword,proto3" json:"keyword,omitempty"` - PageSize int32 `protobuf:"varint,5,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BusinessUserLookupRequest) Reset() { @@ -1843,18 +1825,17 @@ func (x *BusinessUserLookupRequest) GetPageSize() int32 { } type BusinessUserLookupItem struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + DisplayUserId string `protobuf:"bytes,2,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` + Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"` + Avatar string `protobuf:"bytes,4,opt,name=avatar,proto3" json:"avatar,omitempty"` + Status UserStatus `protobuf:"varint,5,opt,name=status,proto3,enum=hyapp.user.v1.UserStatus" json:"status,omitempty"` + RegionId int64 `protobuf:"varint,6,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + RegionCode string `protobuf:"bytes,7,opt,name=region_code,json=regionCode,proto3" json:"region_code,omitempty"` + RegionName string `protobuf:"bytes,8,opt,name=region_name,json=regionName,proto3" json:"region_name,omitempty"` unknownFields protoimpl.UnknownFields - - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - DisplayUserId string `protobuf:"bytes,2,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` - Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"` - Avatar string `protobuf:"bytes,4,opt,name=avatar,proto3" json:"avatar,omitempty"` - Status UserStatus `protobuf:"varint,5,opt,name=status,proto3,enum=hyapp.user.v1.UserStatus" json:"status,omitempty"` - RegionId int64 `protobuf:"varint,6,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - RegionCode string `protobuf:"bytes,7,opt,name=region_code,json=regionCode,proto3" json:"region_code,omitempty"` - RegionName string `protobuf:"bytes,8,opt,name=region_name,json=regionName,proto3" json:"region_name,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BusinessUserLookupItem) Reset() { @@ -1944,11 +1925,10 @@ func (x *BusinessUserLookupItem) GetRegionName() string { } type BusinessUserLookupResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Users []*BusinessUserLookupItem `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` unknownFields protoimpl.UnknownFields - - Users []*BusinessUserLookupItem `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BusinessUserLookupResponse) Reset() { @@ -1990,16 +1970,15 @@ func (x *BusinessUserLookupResponse) GetUsers() []*BusinessUserLookupItem { // UserProfileStats 是我的页顶部统计 read model;不得在查询时实时扫描关系链或礼物流水。 type UserProfileStats struct { - 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"` - VisitorsCount int64 `protobuf:"varint,2,opt,name=visitors_count,json=visitorsCount,proto3" json:"visitors_count,omitempty"` - FollowingCount int64 `protobuf:"varint,3,opt,name=following_count,json=followingCount,proto3" json:"following_count,omitempty"` - FriendsCount int64 `protobuf:"varint,4,opt,name=friends_count,json=friendsCount,proto3" json:"friends_count,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,5,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - AppCode string `protobuf:"bytes,6,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + VisitorsCount int64 `protobuf:"varint,2,opt,name=visitors_count,json=visitorsCount,proto3" json:"visitors_count,omitempty"` + FollowingCount int64 `protobuf:"varint,3,opt,name=following_count,json=followingCount,proto3" json:"following_count,omitempty"` + FriendsCount int64 `protobuf:"varint,4,opt,name=friends_count,json=friendsCount,proto3" json:"friends_count,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,5,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,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 *UserProfileStats) Reset() { @@ -2076,12 +2055,11 @@ func (x *UserProfileStats) GetAppCode() string { // GetMyProfileStatsRequest 查询我的页顶部统计计数。 type GetMyProfileStatsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetMyProfileStatsRequest) Reset() { @@ -2129,11 +2107,10 @@ func (x *GetMyProfileStatsRequest) GetUserId() int64 { } type GetMyProfileStatsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Stats *UserProfileStats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"` unknownFields protoimpl.UnknownFields - - Stats *UserProfileStats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetMyProfileStatsResponse) Reset() { @@ -2174,13 +2151,12 @@ func (x *GetMyProfileStatsResponse) GetStats() *UserProfileStats { } type RecordProfileVisitRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + VisitorUserId int64 `protobuf:"varint,2,opt,name=visitor_user_id,json=visitorUserId,proto3" json:"visitor_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - VisitorUserId int64 `protobuf:"varint,2,opt,name=visitor_user_id,json=visitorUserId,proto3" json:"visitor_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RecordProfileVisitRequest) Reset() { @@ -2235,12 +2211,11 @@ func (x *RecordProfileVisitRequest) GetTargetUserId() int64 { } type RecordProfileVisitResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Recorded bool `protobuf:"varint,1,opt,name=recorded,proto3" json:"recorded,omitempty"` + TargetStats *UserProfileStats `protobuf:"bytes,2,opt,name=target_stats,json=targetStats,proto3" json:"target_stats,omitempty"` unknownFields protoimpl.UnknownFields - - Recorded bool `protobuf:"varint,1,opt,name=recorded,proto3" json:"recorded,omitempty"` - TargetStats *UserProfileStats `protobuf:"bytes,2,opt,name=target_stats,json=targetStats,proto3" json:"target_stats,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RecordProfileVisitResponse) Reset() { @@ -2288,14 +2263,13 @@ func (x *RecordProfileVisitResponse) GetTargetStats() *UserProfileStats { } type ProfileVisitRecord struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - VisitorUserId int64 `protobuf:"varint,1,opt,name=visitor_user_id,json=visitorUserId,proto3" json:"visitor_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - VisitCount int64 `protobuf:"varint,3,opt,name=visit_count,json=visitCount,proto3" json:"visit_count,omitempty"` - LastVisitedAtMs int64 `protobuf:"varint,4,opt,name=last_visited_at_ms,json=lastVisitedAtMs,proto3" json:"last_visited_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + VisitorUserId int64 `protobuf:"varint,1,opt,name=visitor_user_id,json=visitorUserId,proto3" json:"visitor_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + VisitCount int64 `protobuf:"varint,3,opt,name=visit_count,json=visitCount,proto3" json:"visit_count,omitempty"` + LastVisitedAtMs int64 `protobuf:"varint,4,opt,name=last_visited_at_ms,json=lastVisitedAtMs,proto3" json:"last_visited_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ProfileVisitRecord) Reset() { @@ -2357,14 +2331,13 @@ func (x *ProfileVisitRecord) GetLastVisitedAtMs() int64 { } type ListProfileVisitorsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + 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 - - 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"` - 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"` + sizeCache protoimpl.SizeCache } func (x *ListProfileVisitorsRequest) Reset() { @@ -2426,12 +2399,11 @@ func (x *ListProfileVisitorsRequest) GetPageSize() int32 { } type ListProfileVisitorsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Records []*ProfileVisitRecord `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` unknownFields protoimpl.UnknownFields - - Records []*ProfileVisitRecord `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListProfileVisitorsResponse) Reset() { @@ -2479,13 +2451,12 @@ func (x *ListProfileVisitorsResponse) GetTotal() int64 { } type FollowUserRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - FollowerUserId int64 `protobuf:"varint,2,opt,name=follower_user_id,json=followerUserId,proto3" json:"follower_user_id,omitempty"` - FolloweeUserId int64 `protobuf:"varint,3,opt,name=followee_user_id,json=followeeUserId,proto3" json:"followee_user_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + FollowerUserId int64 `protobuf:"varint,2,opt,name=follower_user_id,json=followerUserId,proto3" json:"follower_user_id,omitempty"` + FolloweeUserId int64 `protobuf:"varint,3,opt,name=followee_user_id,json=followeeUserId,proto3" json:"followee_user_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *FollowUserRequest) Reset() { @@ -2540,12 +2511,11 @@ func (x *FollowUserRequest) GetFolloweeUserId() int64 { } type FollowUserResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Following bool `protobuf:"varint,1,opt,name=following,proto3" json:"following,omitempty"` + FollowerStats *UserProfileStats `protobuf:"bytes,2,opt,name=follower_stats,json=followerStats,proto3" json:"follower_stats,omitempty"` unknownFields protoimpl.UnknownFields - - Following bool `protobuf:"varint,1,opt,name=following,proto3" json:"following,omitempty"` - FollowerStats *UserProfileStats `protobuf:"bytes,2,opt,name=follower_stats,json=followerStats,proto3" json:"follower_stats,omitempty"` + sizeCache protoimpl.SizeCache } func (x *FollowUserResponse) Reset() { @@ -2593,13 +2563,12 @@ func (x *FollowUserResponse) GetFollowerStats() *UserProfileStats { } type UnfollowUserRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - FollowerUserId int64 `protobuf:"varint,2,opt,name=follower_user_id,json=followerUserId,proto3" json:"follower_user_id,omitempty"` - FolloweeUserId int64 `protobuf:"varint,3,opt,name=followee_user_id,json=followeeUserId,proto3" json:"followee_user_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + FollowerUserId int64 `protobuf:"varint,2,opt,name=follower_user_id,json=followerUserId,proto3" json:"follower_user_id,omitempty"` + FolloweeUserId int64 `protobuf:"varint,3,opt,name=followee_user_id,json=followeeUserId,proto3" json:"followee_user_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *UnfollowUserRequest) Reset() { @@ -2654,12 +2623,11 @@ func (x *UnfollowUserRequest) GetFolloweeUserId() int64 { } type UnfollowUserResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Following bool `protobuf:"varint,1,opt,name=following,proto3" json:"following,omitempty"` + FollowerStats *UserProfileStats `protobuf:"bytes,2,opt,name=follower_stats,json=followerStats,proto3" json:"follower_stats,omitempty"` unknownFields protoimpl.UnknownFields - - Following bool `protobuf:"varint,1,opt,name=following,proto3" json:"following,omitempty"` - FollowerStats *UserProfileStats `protobuf:"bytes,2,opt,name=follower_stats,json=followerStats,proto3" json:"follower_stats,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UnfollowUserResponse) Reset() { @@ -2707,13 +2675,12 @@ func (x *UnfollowUserResponse) GetFollowerStats() *UserProfileStats { } type FollowRecord struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - FollowerUserId int64 `protobuf:"varint,1,opt,name=follower_user_id,json=followerUserId,proto3" json:"follower_user_id,omitempty"` - FolloweeUserId int64 `protobuf:"varint,2,opt,name=followee_user_id,json=followeeUserId,proto3" json:"followee_user_id,omitempty"` - FollowedAtMs int64 `protobuf:"varint,3,opt,name=followed_at_ms,json=followedAtMs,proto3" json:"followed_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + FollowerUserId int64 `protobuf:"varint,1,opt,name=follower_user_id,json=followerUserId,proto3" json:"follower_user_id,omitempty"` + FolloweeUserId int64 `protobuf:"varint,2,opt,name=followee_user_id,json=followeeUserId,proto3" json:"followee_user_id,omitempty"` + FollowedAtMs int64 `protobuf:"varint,3,opt,name=followed_at_ms,json=followedAtMs,proto3" json:"followed_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *FollowRecord) Reset() { @@ -2768,17 +2735,16 @@ func (x *FollowRecord) GetFollowedAtMs() int64 { } type ListFollowingRequest struct { - 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"` - 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"` + 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"` + 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"` // cursor_updated_at_ms/cursor_user_id 用于内部关系流按时间游标扫描;公开 HTTP 列表仍可继续使用 page/page_size。 CursorUpdatedAtMs int64 `protobuf:"varint,5,opt,name=cursor_updated_at_ms,json=cursorUpdatedAtMs,proto3" json:"cursor_updated_at_ms,omitempty"` CursorUserId int64 `protobuf:"varint,6,opt,name=cursor_user_id,json=cursorUserId,proto3" json:"cursor_user_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListFollowingRequest) Reset() { @@ -2854,12 +2820,11 @@ func (x *ListFollowingRequest) GetCursorUserId() int64 { } type ListFollowingResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Records []*FollowRecord `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` unknownFields protoimpl.UnknownFields - - Records []*FollowRecord `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListFollowingResponse) Reset() { @@ -2907,13 +2872,12 @@ func (x *ListFollowingResponse) GetTotal() int64 { } type ApplyFriendRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RequesterUserId int64 `protobuf:"varint,2,opt,name=requester_user_id,json=requesterUserId,proto3" json:"requester_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RequesterUserId int64 `protobuf:"varint,2,opt,name=requester_user_id,json=requesterUserId,proto3" json:"requester_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ApplyFriendRequest) Reset() { @@ -2968,12 +2932,11 @@ func (x *ApplyFriendRequest) GetTargetUserId() int64 { } type ApplyFriendResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Application *FriendApplication `protobuf:"bytes,1,opt,name=application,proto3" json:"application,omitempty"` - AlreadyFriends bool `protobuf:"varint,2,opt,name=already_friends,json=alreadyFriends,proto3" json:"already_friends,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Application *FriendApplication `protobuf:"bytes,1,opt,name=application,proto3" json:"application,omitempty"` + AlreadyFriends bool `protobuf:"varint,2,opt,name=already_friends,json=alreadyFriends,proto3" json:"already_friends,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ApplyFriendResponse) Reset() { @@ -3021,13 +2984,12 @@ func (x *ApplyFriendResponse) GetAlreadyFriends() bool { } type AcceptFriendApplicationRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - AccepterUserId int64 `protobuf:"varint,2,opt,name=accepter_user_id,json=accepterUserId,proto3" json:"accepter_user_id,omitempty"` - RequesterUserId int64 `protobuf:"varint,3,opt,name=requester_user_id,json=requesterUserId,proto3" json:"requester_user_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + AccepterUserId int64 `protobuf:"varint,2,opt,name=accepter_user_id,json=accepterUserId,proto3" json:"accepter_user_id,omitempty"` + RequesterUserId int64 `protobuf:"varint,3,opt,name=requester_user_id,json=requesterUserId,proto3" json:"requester_user_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AcceptFriendApplicationRequest) Reset() { @@ -3082,11 +3044,10 @@ func (x *AcceptFriendApplicationRequest) GetRequesterUserId() int64 { } type AcceptFriendApplicationResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Friend *FriendRecord `protobuf:"bytes,1,opt,name=friend,proto3" json:"friend,omitempty"` unknownFields protoimpl.UnknownFields - - Friend *FriendRecord `protobuf:"bytes,1,opt,name=friend,proto3" json:"friend,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AcceptFriendApplicationResponse) Reset() { @@ -3127,13 +3088,12 @@ func (x *AcceptFriendApplicationResponse) GetFriend() *FriendRecord { } type DeleteFriendRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + FriendUserId int64 `protobuf:"varint,3,opt,name=friend_user_id,json=friendUserId,proto3" json:"friend_user_id,omitempty"` 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"` - FriendUserId int64 `protobuf:"varint,3,opt,name=friend_user_id,json=friendUserId,proto3" json:"friend_user_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *DeleteFriendRequest) Reset() { @@ -3188,11 +3148,10 @@ func (x *DeleteFriendRequest) GetFriendUserId() int64 { } type DeleteFriendResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"` unknownFields protoimpl.UnknownFields - - Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"` + sizeCache protoimpl.SizeCache } func (x *DeleteFriendResponse) Reset() { @@ -3233,13 +3192,12 @@ func (x *DeleteFriendResponse) GetDeleted() bool { } type FriendRecord struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + FriendUserId int64 `protobuf:"varint,2,opt,name=friend_user_id,json=friendUserId,proto3" json:"friend_user_id,omitempty"` + FriendedAtMs int64 `protobuf:"varint,3,opt,name=friended_at_ms,json=friendedAtMs,proto3" json:"friended_at_ms,omitempty"` unknownFields protoimpl.UnknownFields - - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - FriendUserId int64 `protobuf:"varint,2,opt,name=friend_user_id,json=friendUserId,proto3" json:"friend_user_id,omitempty"` - FriendedAtMs int64 `protobuf:"varint,3,opt,name=friended_at_ms,json=friendedAtMs,proto3" json:"friended_at_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *FriendRecord) Reset() { @@ -3294,17 +3252,16 @@ func (x *FriendRecord) GetFriendedAtMs() int64 { } type ListFriendsRequest struct { - 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"` - 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"` + 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"` + 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"` // cursor_updated_at_ms/cursor_user_id 用于内部关系流按时间游标扫描;公开 HTTP 列表仍可继续使用 page/page_size。 CursorUpdatedAtMs int64 `protobuf:"varint,5,opt,name=cursor_updated_at_ms,json=cursorUpdatedAtMs,proto3" json:"cursor_updated_at_ms,omitempty"` CursorUserId int64 `protobuf:"varint,6,opt,name=cursor_user_id,json=cursorUserId,proto3" json:"cursor_user_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListFriendsRequest) Reset() { @@ -3380,12 +3337,11 @@ func (x *ListFriendsRequest) GetCursorUserId() int64 { } type ListFriendsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Records []*FriendRecord `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` unknownFields protoimpl.UnknownFields - - Records []*FriendRecord `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListFriendsResponse) Reset() { @@ -3433,15 +3389,14 @@ func (x *ListFriendsResponse) GetTotal() int64 { } type FriendApplication struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RequesterUserId int64 `protobuf:"varint,1,opt,name=requester_user_id,json=requesterUserId,proto3" json:"requester_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` - CreatedAtMs int64 `protobuf:"varint,4,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,5,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + RequesterUserId int64 `protobuf:"varint,1,opt,name=requester_user_id,json=requesterUserId,proto3" json:"requester_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + CreatedAtMs int64 `protobuf:"varint,4,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,5,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *FriendApplication) Reset() { @@ -3510,15 +3465,14 @@ func (x *FriendApplication) GetUpdatedAtMs() int64 { } type ListFriendApplicationsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + Direction string `protobuf:"bytes,3,opt,name=direction,proto3" json:"direction,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 - - 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"` - Direction string `protobuf:"bytes,3,opt,name=direction,proto3" json:"direction,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"` + sizeCache protoimpl.SizeCache } func (x *ListFriendApplicationsRequest) Reset() { @@ -3587,12 +3541,11 @@ func (x *ListFriendApplicationsRequest) GetPageSize() int32 { } type ListFriendApplicationsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Applications []*FriendApplication `protobuf:"bytes,1,rep,name=applications,proto3" json:"applications,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` unknownFields protoimpl.UnknownFields - - Applications []*FriendApplication `protobuf:"bytes,1,rep,name=applications,proto3" json:"applications,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListFriendApplicationsResponse) Reset() { @@ -3641,14 +3594,13 @@ func (x *ListFriendApplicationsResponse) GetTotal() int64 { // CPUserProfile 是 CP 关系消息里需要展示的用户快照。 type CPUserProfile struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + DisplayUserId string `protobuf:"bytes,2,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` + Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"` + Avatar string `protobuf:"bytes,4,opt,name=avatar,proto3" json:"avatar,omitempty"` unknownFields protoimpl.UnknownFields - - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - DisplayUserId string `protobuf:"bytes,2,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` - Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"` - Avatar string `protobuf:"bytes,4,opt,name=avatar,proto3" json:"avatar,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CPUserProfile) Reset() { @@ -3711,17 +3663,18 @@ func (x *CPUserProfile) GetAvatar() string { // CPGiftSnapshot 固化触发申请或亲密值增长的礼物展示信息。 type CPGiftSnapshot struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + GiftIconUrl string `protobuf:"bytes,3,opt,name=gift_icon_url,json=giftIconUrl,proto3" json:"gift_icon_url,omitempty"` + GiftAnimationUrl string `protobuf:"bytes,4,opt,name=gift_animation_url,json=giftAnimationUrl,proto3" json:"gift_animation_url,omitempty"` + GiftCount int32 `protobuf:"varint,5,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` + GiftValue int64 `protobuf:"varint,6,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` + BillingReceiptId string `protobuf:"bytes,7,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` + // coin_spent 是 wallet 结算出的礼物金币价值(背包礼物也保留价值),不能用 gift_value(热度/亲密值)替代。 + CoinSpent int64 `protobuf:"varint,8,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` 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"` - GiftIconUrl string `protobuf:"bytes,3,opt,name=gift_icon_url,json=giftIconUrl,proto3" json:"gift_icon_url,omitempty"` - GiftAnimationUrl string `protobuf:"bytes,4,opt,name=gift_animation_url,json=giftAnimationUrl,proto3" json:"gift_animation_url,omitempty"` - GiftCount int32 `protobuf:"varint,5,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` - GiftValue int64 `protobuf:"varint,6,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` - BillingReceiptId string `protobuf:"bytes,7,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CPGiftSnapshot) Reset() { @@ -3803,24 +3756,30 @@ func (x *CPGiftSnapshot) GetBillingReceiptId() string { return "" } +func (x *CPGiftSnapshot) GetCoinSpent() int64 { + if x != nil { + return x.CoinSpent + } + return 0 +} + // CPApplication 是 A 给 B 发送 CP/兄弟/姐妹礼物后生成的待处理申请。 type CPApplication struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + ApplicationId string `protobuf:"bytes,1,opt,name=application_id,json=applicationId,proto3" json:"application_id,omitempty"` + RelationType string `protobuf:"bytes,2,opt,name=relation_type,json=relationType,proto3" json:"relation_type,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + Requester *CPUserProfile `protobuf:"bytes,4,opt,name=requester,proto3" json:"requester,omitempty"` + Target *CPUserProfile `protobuf:"bytes,5,opt,name=target,proto3" json:"target,omitempty"` + RoomId string `protobuf:"bytes,6,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + RoomRegionId int64 `protobuf:"varint,7,opt,name=room_region_id,json=roomRegionId,proto3" json:"room_region_id,omitempty"` + Gift *CPGiftSnapshot `protobuf:"bytes,8,opt,name=gift,proto3" json:"gift,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"` + ExpiresAtMs int64 `protobuf:"varint,11,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` + DecidedAtMs int64 `protobuf:"varint,12,opt,name=decided_at_ms,json=decidedAtMs,proto3" json:"decided_at_ms,omitempty"` unknownFields protoimpl.UnknownFields - - ApplicationId string `protobuf:"bytes,1,opt,name=application_id,json=applicationId,proto3" json:"application_id,omitempty"` - RelationType string `protobuf:"bytes,2,opt,name=relation_type,json=relationType,proto3" json:"relation_type,omitempty"` - Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` - Requester *CPUserProfile `protobuf:"bytes,4,opt,name=requester,proto3" json:"requester,omitempty"` - Target *CPUserProfile `protobuf:"bytes,5,opt,name=target,proto3" json:"target,omitempty"` - RoomId string `protobuf:"bytes,6,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - RoomRegionId int64 `protobuf:"varint,7,opt,name=room_region_id,json=roomRegionId,proto3" json:"room_region_id,omitempty"` - Gift *CPGiftSnapshot `protobuf:"bytes,8,opt,name=gift,proto3" json:"gift,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"` - ExpiresAtMs int64 `protobuf:"varint,11,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - DecidedAtMs int64 `protobuf:"varint,12,opt,name=decided_at_ms,json=decidedAtMs,proto3" json:"decided_at_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CPApplication) Reset() { @@ -3939,27 +3898,26 @@ func (x *CPApplication) GetDecidedAtMs() int64 { // CPRelationship 是两个用户已经形成的一种关系;同一用户同一时间只能 active 一种。 type CPRelationship struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RelationshipId string `protobuf:"bytes,1,opt,name=relationship_id,json=relationshipId,proto3" json:"relationship_id,omitempty"` - RelationType string `protobuf:"bytes,2,opt,name=relation_type,json=relationType,proto3" json:"relation_type,omitempty"` - Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` - Me *CPUserProfile `protobuf:"bytes,4,opt,name=me,proto3" json:"me,omitempty"` - Partner *CPUserProfile `protobuf:"bytes,5,opt,name=partner,proto3" json:"partner,omitempty"` - IntimacyValue int64 `protobuf:"varint,6,opt,name=intimacy_value,json=intimacyValue,proto3" json:"intimacy_value,omitempty"` - Level int32 `protobuf:"varint,7,opt,name=level,proto3" json:"level,omitempty"` - FormedAtMs int64 `protobuf:"varint,9,opt,name=formed_at_ms,json=formedAtMs,proto3" json:"formed_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,10,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - CurrentLevelThreshold int64 `protobuf:"varint,11,opt,name=current_level_threshold,json=currentLevelThreshold,proto3" json:"current_level_threshold,omitempty"` - NextLevelThreshold int64 `protobuf:"varint,12,opt,name=next_level_threshold,json=nextLevelThreshold,proto3" json:"next_level_threshold,omitempty"` - NeededForNextLevel int64 `protobuf:"varint,13,opt,name=needed_for_next_level,json=neededForNextLevel,proto3" json:"needed_for_next_level,omitempty"` - LevelProgressPercent int32 `protobuf:"varint,14,opt,name=level_progress_percent,json=levelProgressPercent,proto3" json:"level_progress_percent,omitempty"` - MaxLevel bool `protobuf:"varint,15,opt,name=max_level,json=maxLevel,proto3" json:"max_level,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + RelationshipId string `protobuf:"bytes,1,opt,name=relationship_id,json=relationshipId,proto3" json:"relationship_id,omitempty"` + RelationType string `protobuf:"bytes,2,opt,name=relation_type,json=relationType,proto3" json:"relation_type,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + Me *CPUserProfile `protobuf:"bytes,4,opt,name=me,proto3" json:"me,omitempty"` + Partner *CPUserProfile `protobuf:"bytes,5,opt,name=partner,proto3" json:"partner,omitempty"` + IntimacyValue int64 `protobuf:"varint,6,opt,name=intimacy_value,json=intimacyValue,proto3" json:"intimacy_value,omitempty"` + Level int32 `protobuf:"varint,7,opt,name=level,proto3" json:"level,omitempty"` + FormedAtMs int64 `protobuf:"varint,9,opt,name=formed_at_ms,json=formedAtMs,proto3" json:"formed_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,10,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + CurrentLevelThreshold int64 `protobuf:"varint,11,opt,name=current_level_threshold,json=currentLevelThreshold,proto3" json:"current_level_threshold,omitempty"` + NextLevelThreshold int64 `protobuf:"varint,12,opt,name=next_level_threshold,json=nextLevelThreshold,proto3" json:"next_level_threshold,omitempty"` + NeededForNextLevel int64 `protobuf:"varint,13,opt,name=needed_for_next_level,json=neededForNextLevel,proto3" json:"needed_for_next_level,omitempty"` + LevelProgressPercent int32 `protobuf:"varint,14,opt,name=level_progress_percent,json=levelProgressPercent,proto3" json:"level_progress_percent,omitempty"` + MaxLevel bool `protobuf:"varint,15,opt,name=max_level,json=maxLevel,proto3" json:"max_level,omitempty"` // breakup_cost_coins 是当前关系类型后台配置的解除费用;active 关系返回配置值,ended 关系返回实际支付值。 BreakupCostCoins int64 `protobuf:"varint,16,opt,name=breakup_cost_coins,json=breakupCostCoins,proto3" json:"breakup_cost_coins,omitempty"` EndedAtMs int64 `protobuf:"varint,17,opt,name=ended_at_ms,json=endedAtMs,proto3" json:"ended_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CPRelationship) Reset() { @@ -4106,17 +4064,16 @@ func (x *CPRelationship) GetEndedAtMs() int64 { // CPAvatarFrameSnapshot 是排行榜里展示用户当前头像框的轻量快照。 type CPAvatarFrameSnapshot struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` 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"` + sizeCache protoimpl.SizeCache } func (x *CPAvatarFrameSnapshot) Reset() { @@ -4200,15 +4157,14 @@ func (x *CPAvatarFrameSnapshot) GetMetadataJson() string { // CPIntimacyLeaderboardUser 是 CP 亲密榜中一方用户的展示资料。 type CPIntimacyLeaderboardUser struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` DisplayUserId string `protobuf:"bytes,2,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"` Avatar string `protobuf:"bytes,4,opt,name=avatar,proto3" json:"avatar,omitempty"` AvatarFrame *CPAvatarFrameSnapshot `protobuf:"bytes,5,opt,name=avatar_frame,json=avatarFrame,proto3" json:"avatar_frame,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CPIntimacyLeaderboardUser) Reset() { @@ -4278,10 +4234,7 @@ func (x *CPIntimacyLeaderboardUser) GetAvatarFrame() *CPAvatarFrameSnapshot { // CPIntimacyLeaderboardItem 是一对 active 关系在亲密值榜单里的读模型。 type CPIntimacyLeaderboardItem struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` Rank int64 `protobuf:"varint,1,opt,name=rank,proto3" json:"rank,omitempty"` RelationshipId string `protobuf:"bytes,2,opt,name=relationship_id,json=relationshipId,proto3" json:"relationship_id,omitempty"` RelationType string `protobuf:"bytes,3,opt,name=relation_type,json=relationType,proto3" json:"relation_type,omitempty"` @@ -4291,6 +4244,8 @@ type CPIntimacyLeaderboardItem struct { UserB *CPIntimacyLeaderboardUser `protobuf:"bytes,7,opt,name=user_b,json=userB,proto3" json:"user_b,omitempty"` FormedAtMs int64 `protobuf:"varint,8,opt,name=formed_at_ms,json=formedAtMs,proto3" json:"formed_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 *CPIntimacyLeaderboardItem) Reset() { @@ -4388,10 +4343,7 @@ func (x *CPIntimacyLeaderboardItem) GetUpdatedAtMs() int64 { // CPWeeklyRankEntry 是 activity-service 结算 CP 周榜时读取的关系周积分快照。 type CPWeeklyRankEntry struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` Rank int64 `protobuf:"varint,1,opt,name=rank,proto3" json:"rank,omitempty"` RelationshipId string `protobuf:"bytes,2,opt,name=relationship_id,json=relationshipId,proto3" json:"relationship_id,omitempty"` RelationType string `protobuf:"bytes,3,opt,name=relation_type,json=relationType,proto3" json:"relation_type,omitempty"` @@ -4402,6 +4354,8 @@ type CPWeeklyRankEntry struct { UpdatedAtMs int64 `protobuf:"varint,8,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` FirstScoredAtMs int64 `protobuf:"varint,9,opt,name=first_scored_at_ms,json=firstScoredAtMs,proto3" json:"first_scored_at_ms,omitempty"` LastScoredAtMs int64 `protobuf:"varint,10,opt,name=last_scored_at_ms,json=lastScoredAtMs,proto3" json:"last_scored_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CPWeeklyRankEntry) Reset() { @@ -4505,15 +4459,14 @@ func (x *CPWeeklyRankEntry) GetLastScoredAtMs() int64 { } type ListCPWeeklyRankEntriesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RelationType string `protobuf:"bytes,2,opt,name=relation_type,json=relationType,proto3" json:"relation_type,omitempty"` + StartMs int64 `protobuf:"varint,3,opt,name=start_ms,json=startMs,proto3" json:"start_ms,omitempty"` + EndMs int64 `protobuf:"varint,4,opt,name=end_ms,json=endMs,proto3" json:"end_ms,omitempty"` + Limit int32 `protobuf:"varint,5,opt,name=limit,proto3" json:"limit,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RelationType string `protobuf:"bytes,2,opt,name=relation_type,json=relationType,proto3" json:"relation_type,omitempty"` - StartMs int64 `protobuf:"varint,3,opt,name=start_ms,json=startMs,proto3" json:"start_ms,omitempty"` - EndMs int64 `protobuf:"varint,4,opt,name=end_ms,json=endMs,proto3" json:"end_ms,omitempty"` - Limit int32 `protobuf:"varint,5,opt,name=limit,proto3" json:"limit,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListCPWeeklyRankEntriesRequest) Reset() { @@ -4582,12 +4535,11 @@ func (x *ListCPWeeklyRankEntriesRequest) GetLimit() int32 { } type ListCPWeeklyRankEntriesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Entries []*CPWeeklyRankEntry `protobuf:"bytes,1,rep,name=entries,proto3" json:"entries,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` unknownFields protoimpl.UnknownFields - - Entries []*CPWeeklyRankEntry `protobuf:"bytes,1,rep,name=entries,proto3" json:"entries,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListCPWeeklyRankEntriesResponse) Reset() { @@ -4635,16 +4587,15 @@ func (x *ListCPWeeklyRankEntriesResponse) GetServerTimeMs() int64 { } type ListCPApplicationsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + Direction string `protobuf:"bytes,3,opt,name=direction,proto3" json:"direction,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 - - 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"` - Direction string `protobuf:"bytes,3,opt,name=direction,proto3" json:"direction,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"` + sizeCache protoimpl.SizeCache } func (x *ListCPApplicationsRequest) Reset() { @@ -4720,13 +4671,12 @@ func (x *ListCPApplicationsRequest) GetPageSize() int32 { } type ListCPApplicationsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Applications []*CPApplication `protobuf:"bytes,1,rep,name=applications,proto3" json:"applications,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 - - Applications []*CPApplication `protobuf:"bytes,1,rep,name=applications,proto3" json:"applications,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"` + sizeCache protoimpl.SizeCache } func (x *ListCPApplicationsResponse) Reset() { @@ -4781,13 +4731,12 @@ func (x *ListCPApplicationsResponse) GetServerTimeMs() int64 { } type AcceptCPApplicationRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + ApplicationId string `protobuf:"bytes,3,opt,name=application_id,json=applicationId,proto3" json:"application_id,omitempty"` 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"` - ApplicationId string `protobuf:"bytes,3,opt,name=application_id,json=applicationId,proto3" json:"application_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AcceptCPApplicationRequest) Reset() { @@ -4842,12 +4791,11 @@ func (x *AcceptCPApplicationRequest) GetApplicationId() string { } type AcceptCPApplicationResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Application *CPApplication `protobuf:"bytes,1,opt,name=application,proto3" json:"application,omitempty"` + Relationship *CPRelationship `protobuf:"bytes,2,opt,name=relationship,proto3" json:"relationship,omitempty"` unknownFields protoimpl.UnknownFields - - Application *CPApplication `protobuf:"bytes,1,opt,name=application,proto3" json:"application,omitempty"` - Relationship *CPRelationship `protobuf:"bytes,2,opt,name=relationship,proto3" json:"relationship,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AcceptCPApplicationResponse) Reset() { @@ -4895,14 +4843,13 @@ func (x *AcceptCPApplicationResponse) GetRelationship() *CPRelationship { } type RejectCPApplicationRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + ApplicationId string `protobuf:"bytes,3,opt,name=application_id,json=applicationId,proto3" json:"application_id,omitempty"` + Reason string `protobuf:"bytes,4,opt,name=reason,proto3" json:"reason,omitempty"` 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"` - ApplicationId string `protobuf:"bytes,3,opt,name=application_id,json=applicationId,proto3" json:"application_id,omitempty"` - Reason string `protobuf:"bytes,4,opt,name=reason,proto3" json:"reason,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RejectCPApplicationRequest) Reset() { @@ -4964,11 +4911,10 @@ func (x *RejectCPApplicationRequest) GetReason() string { } type RejectCPApplicationResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Application *CPApplication `protobuf:"bytes,1,opt,name=application,proto3" json:"application,omitempty"` unknownFields protoimpl.UnknownFields - - Application *CPApplication `protobuf:"bytes,1,opt,name=application,proto3" json:"application,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RejectCPApplicationResponse) Reset() { @@ -5009,15 +4955,14 @@ func (x *RejectCPApplicationResponse) GetApplication() *CPApplication { } type ListCPRelationshipsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + RelationType string `protobuf:"bytes,3,opt,name=relation_type,json=relationType,proto3" json:"relation_type,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 - - 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"` - RelationType string `protobuf:"bytes,3,opt,name=relation_type,json=relationType,proto3" json:"relation_type,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"` + sizeCache protoimpl.SizeCache } func (x *ListCPRelationshipsRequest) Reset() { @@ -5086,12 +5031,11 @@ func (x *ListCPRelationshipsRequest) GetPageSize() int32 { } type ListCPRelationshipsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Relationships []*CPRelationship `protobuf:"bytes,1,rep,name=relationships,proto3" json:"relationships,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` unknownFields protoimpl.UnknownFields - - Relationships []*CPRelationship `protobuf:"bytes,1,rep,name=relationships,proto3" json:"relationships,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListCPRelationshipsResponse) Reset() { @@ -5139,14 +5083,13 @@ func (x *ListCPRelationshipsResponse) GetTotal() int64 { } type ListCPIntimacyLeaderboardRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RelationType string `protobuf:"bytes,2,opt,name=relation_type,json=relationType,proto3" json:"relation_type,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 - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RelationType string `protobuf:"bytes,2,opt,name=relation_type,json=relationType,proto3" json:"relation_type,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"` + sizeCache protoimpl.SizeCache } func (x *ListCPIntimacyLeaderboardRequest) Reset() { @@ -5208,15 +5151,14 @@ func (x *ListCPIntimacyLeaderboardRequest) GetPageSize() int32 { } type ListCPIntimacyLeaderboardResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Items []*CPIntimacyLeaderboardItem `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 - - Items []*CPIntimacyLeaderboardItem `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"` + sizeCache protoimpl.SizeCache } func (x *ListCPIntimacyLeaderboardResponse) Reset() { @@ -5285,14 +5227,13 @@ func (x *ListCPIntimacyLeaderboardResponse) GetServerTimeMs() int64 { } type PrepareBreakCPRelationshipRequest struct { - 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"` - RelationshipId string `protobuf:"bytes,3,opt,name=relationship_id,json=relationshipId,proto3" json:"relationship_id,omitempty"` - CommandId string `protobuf:"bytes,4,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + 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"` + RelationshipId string `protobuf:"bytes,3,opt,name=relationship_id,json=relationshipId,proto3" json:"relationship_id,omitempty"` + CommandId string `protobuf:"bytes,4,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *PrepareBreakCPRelationshipRequest) Reset() { @@ -5354,16 +5295,15 @@ func (x *PrepareBreakCPRelationshipRequest) GetCommandId() string { } type PrepareBreakCPRelationshipResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Relationship *CPRelationship `protobuf:"bytes,1,opt,name=relationship,proto3" json:"relationship,omitempty"` - CommandId string `protobuf:"bytes,2,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` - BreakupCostCoins int64 `protobuf:"varint,4,opt,name=breakup_cost_coins,json=breakupCostCoins,proto3" json:"breakup_cost_coins,omitempty"` - WalletTransactionId string `protobuf:"bytes,5,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` - CoinBalanceAfter int64 `protobuf:"varint,6,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Relationship *CPRelationship `protobuf:"bytes,1,opt,name=relationship,proto3" json:"relationship,omitempty"` + CommandId string `protobuf:"bytes,2,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + BreakupCostCoins int64 `protobuf:"varint,4,opt,name=breakup_cost_coins,json=breakupCostCoins,proto3" json:"breakup_cost_coins,omitempty"` + WalletTransactionId string `protobuf:"bytes,5,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` + CoinBalanceAfter int64 `protobuf:"varint,6,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *PrepareBreakCPRelationshipResponse) Reset() { @@ -5439,17 +5379,16 @@ func (x *PrepareBreakCPRelationshipResponse) GetCoinBalanceAfter() int64 { } type ConfirmBreakCPRelationshipRequest struct { - 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"` - RelationshipId string `protobuf:"bytes,3,opt,name=relationship_id,json=relationshipId,proto3" json:"relationship_id,omitempty"` - CommandId string `protobuf:"bytes,4,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - WalletTransactionId string `protobuf:"bytes,5,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` - PaidCoinAmount int64 `protobuf:"varint,6,opt,name=paid_coin_amount,json=paidCoinAmount,proto3" json:"paid_coin_amount,omitempty"` - CoinBalanceAfter int64 `protobuf:"varint,7,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + 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"` + RelationshipId string `protobuf:"bytes,3,opt,name=relationship_id,json=relationshipId,proto3" json:"relationship_id,omitempty"` + CommandId string `protobuf:"bytes,4,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + WalletTransactionId string `protobuf:"bytes,5,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` + PaidCoinAmount int64 `protobuf:"varint,6,opt,name=paid_coin_amount,json=paidCoinAmount,proto3" json:"paid_coin_amount,omitempty"` + CoinBalanceAfter int64 `protobuf:"varint,7,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ConfirmBreakCPRelationshipRequest) Reset() { @@ -5532,14 +5471,13 @@ func (x *ConfirmBreakCPRelationshipRequest) GetCoinBalanceAfter() int64 { } type ConfirmBreakCPRelationshipResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Relationship *CPRelationship `protobuf:"bytes,1,opt,name=relationship,proto3" json:"relationship,omitempty"` - BreakupCostCoins int64 `protobuf:"varint,2,opt,name=breakup_cost_coins,json=breakupCostCoins,proto3" json:"breakup_cost_coins,omitempty"` - WalletTransactionId string `protobuf:"bytes,3,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` - CoinBalanceAfter int64 `protobuf:"varint,4,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Relationship *CPRelationship `protobuf:"bytes,1,opt,name=relationship,proto3" json:"relationship,omitempty"` + BreakupCostCoins int64 `protobuf:"varint,2,opt,name=breakup_cost_coins,json=breakupCostCoins,proto3" json:"breakup_cost_coins,omitempty"` + WalletTransactionId string `protobuf:"bytes,3,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` + CoinBalanceAfter int64 `protobuf:"varint,4,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ConfirmBreakCPRelationshipResponse) Reset() { @@ -5601,15 +5539,14 @@ func (x *ConfirmBreakCPRelationshipResponse) GetCoinBalanceAfter() int64 { } type CancelBreakCPRelationshipRequest struct { - 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"` - RelationshipId string `protobuf:"bytes,3,opt,name=relationship_id,json=relationshipId,proto3" json:"relationship_id,omitempty"` - CommandId string `protobuf:"bytes,4,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` + 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"` + RelationshipId string `protobuf:"bytes,3,opt,name=relationship_id,json=relationshipId,proto3" json:"relationship_id,omitempty"` + CommandId string `protobuf:"bytes,4,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CancelBreakCPRelationshipRequest) Reset() { @@ -5678,12 +5615,11 @@ func (x *CancelBreakCPRelationshipRequest) GetReason() string { } type CancelBreakCPRelationshipResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` unknownFields protoimpl.UnknownFields - - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CancelBreakCPRelationshipResponse) Reset() { @@ -5731,28 +5667,29 @@ func (x *CancelBreakCPRelationshipResponse) GetStatus() string { } type RoomGiftCPEvent struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + RoomId string `protobuf:"bytes,3,opt,name=room_id,json=roomId,proto3" json:"room_id,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"` + SenderUserId int64 `protobuf:"varint,6,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,7,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + GiftId string `protobuf:"bytes,8,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + GiftCount int32 `protobuf:"varint,9,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` + GiftValue int64 `protobuf:"varint,10,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` + BillingReceiptId string `protobuf:"bytes,11,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` + VisibleRegionId int64 `protobuf:"varint,12,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + CommandId string `protobuf:"bytes,13,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + GiftTypeCode string `protobuf:"bytes,14,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` + CpRelationType string `protobuf:"bytes,15,opt,name=cp_relation_type,json=cpRelationType,proto3" json:"cp_relation_type,omitempty"` + GiftName string `protobuf:"bytes,16,opt,name=gift_name,json=giftName,proto3" json:"gift_name,omitempty"` + GiftIconUrl string `protobuf:"bytes,17,opt,name=gift_icon_url,json=giftIconUrl,proto3" json:"gift_icon_url,omitempty"` + GiftAnimationUrl string `protobuf:"bytes,18,opt,name=gift_animation_url,json=giftAnimationUrl,proto3" json:"gift_animation_url,omitempty"` + // coin_spent 来自 RoomGiftSent 的 wallet 结算价值,和 gift_value 的热度口径彼此独立。 + CoinSpent int64 `protobuf:"varint,19,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` unknownFields protoimpl.UnknownFields - - 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"` - RoomId string `protobuf:"bytes,3,opt,name=room_id,json=roomId,proto3" json:"room_id,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"` - SenderUserId int64 `protobuf:"varint,6,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,7,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - GiftId string `protobuf:"bytes,8,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - GiftCount int32 `protobuf:"varint,9,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` - GiftValue int64 `protobuf:"varint,10,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` - BillingReceiptId string `protobuf:"bytes,11,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` - VisibleRegionId int64 `protobuf:"varint,12,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - CommandId string `protobuf:"bytes,13,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - GiftTypeCode string `protobuf:"bytes,14,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` - CpRelationType string `protobuf:"bytes,15,opt,name=cp_relation_type,json=cpRelationType,proto3" json:"cp_relation_type,omitempty"` - GiftName string `protobuf:"bytes,16,opt,name=gift_name,json=giftName,proto3" json:"gift_name,omitempty"` - GiftIconUrl string `protobuf:"bytes,17,opt,name=gift_icon_url,json=giftIconUrl,proto3" json:"gift_icon_url,omitempty"` - GiftAnimationUrl string `protobuf:"bytes,18,opt,name=gift_animation_url,json=giftAnimationUrl,proto3" json:"gift_animation_url,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RoomGiftCPEvent) Reset() { @@ -5911,13 +5848,19 @@ func (x *RoomGiftCPEvent) GetGiftAnimationUrl() string { return "" } -type ConsumeRoomGiftCPEventRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields +func (x *RoomGiftCPEvent) GetCoinSpent() int64 { + if x != nil { + return x.CoinSpent + } + return 0 +} - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Event *RoomGiftCPEvent `protobuf:"bytes,2,opt,name=event,proto3" json:"event,omitempty"` +type ConsumeRoomGiftCPEventRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Event *RoomGiftCPEvent `protobuf:"bytes,2,opt,name=event,proto3" json:"event,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ConsumeRoomGiftCPEventRequest) Reset() { @@ -5965,13 +5908,12 @@ func (x *ConsumeRoomGiftCPEventRequest) GetEvent() *RoomGiftCPEvent { } type ConsumeRoomGiftCPEventResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Consumed bool `protobuf:"varint,1,opt,name=consumed,proto3" json:"consumed,omitempty"` + Application *CPApplication `protobuf:"bytes,2,opt,name=application,proto3" json:"application,omitempty"` + Relationship *CPRelationship `protobuf:"bytes,3,opt,name=relationship,proto3" json:"relationship,omitempty"` unknownFields protoimpl.UnknownFields - - Consumed bool `protobuf:"varint,1,opt,name=consumed,proto3" json:"consumed,omitempty"` - Application *CPApplication `protobuf:"bytes,2,opt,name=application,proto3" json:"application,omitempty"` - Relationship *CPRelationship `protobuf:"bytes,3,opt,name=relationship,proto3" json:"relationship,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ConsumeRoomGiftCPEventResponse) Reset() { @@ -6027,20 +5969,19 @@ func (x *ConsumeRoomGiftCPEventResponse) GetRelationship() *CPRelationship { // UserReport 是 App 用户提交的治理举报单。 type UserReport struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ReportId string `protobuf:"bytes,1,opt,name=report_id,json=reportId,proto3" json:"report_id,omitempty"` - ReporterUserId int64 `protobuf:"varint,2,opt,name=reporter_user_id,json=reporterUserId,proto3" json:"reporter_user_id,omitempty"` - TargetType string `protobuf:"bytes,3,opt,name=target_type,json=targetType,proto3" json:"target_type,omitempty"` - UserId int64 `protobuf:"varint,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - RoomId string `protobuf:"bytes,5,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - ReportType string `protobuf:"bytes,6,opt,name=report_type,json=reportType,proto3" json:"report_type,omitempty"` - Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` - ImageUrls []string `protobuf:"bytes,8,rep,name=image_urls,json=imageUrls,proto3" json:"image_urls,omitempty"` - Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"` - CreatedAtMs int64 `protobuf:"varint,10,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + ReportId string `protobuf:"bytes,1,opt,name=report_id,json=reportId,proto3" json:"report_id,omitempty"` + ReporterUserId int64 `protobuf:"varint,2,opt,name=reporter_user_id,json=reporterUserId,proto3" json:"reporter_user_id,omitempty"` + TargetType string `protobuf:"bytes,3,opt,name=target_type,json=targetType,proto3" json:"target_type,omitempty"` + UserId int64 `protobuf:"varint,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + RoomId string `protobuf:"bytes,5,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + ReportType string `protobuf:"bytes,6,opt,name=report_type,json=reportType,proto3" json:"report_type,omitempty"` + Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` + ImageUrls []string `protobuf:"bytes,8,rep,name=image_urls,json=imageUrls,proto3" json:"image_urls,omitempty"` + Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,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 } func (x *UserReport) Reset() { @@ -6145,17 +6086,16 @@ func (x *UserReport) GetCreatedAtMs() int64 { // SubmitReportRequest 提交用户或房间举报;user_id 和 room_id 必须二选一。 type SubmitReportRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - ReporterUserId int64 `protobuf:"varint,2,opt,name=reporter_user_id,json=reporterUserId,proto3" json:"reporter_user_id,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - RoomId string `protobuf:"bytes,4,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - ReportType string `protobuf:"bytes,5,opt,name=report_type,json=reportType,proto3" json:"report_type,omitempty"` - Reason string `protobuf:"bytes,6,opt,name=reason,proto3" json:"reason,omitempty"` - ImageUrls []string `protobuf:"bytes,7,rep,name=image_urls,json=imageUrls,proto3" json:"image_urls,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + ReporterUserId int64 `protobuf:"varint,2,opt,name=reporter_user_id,json=reporterUserId,proto3" json:"reporter_user_id,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + RoomId string `protobuf:"bytes,4,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + ReportType string `protobuf:"bytes,5,opt,name=report_type,json=reportType,proto3" json:"report_type,omitempty"` + Reason string `protobuf:"bytes,6,opt,name=reason,proto3" json:"reason,omitempty"` + ImageUrls []string `protobuf:"bytes,7,rep,name=image_urls,json=imageUrls,proto3" json:"image_urls,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SubmitReportRequest) Reset() { @@ -6238,11 +6178,10 @@ func (x *SubmitReportRequest) GetImageUrls() []string { } type SubmitReportResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Report *UserReport `protobuf:"bytes,1,opt,name=report,proto3" json:"report,omitempty"` unknownFields protoimpl.UnknownFields - - Report *UserReport `protobuf:"bytes,1,opt,name=report,proto3" json:"report,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SubmitReportResponse) Reset() { @@ -6284,12 +6223,11 @@ func (x *SubmitReportResponse) GetReport() *UserReport { // BatchGetUsersRequest 批量查询用户主状态。 type BatchGetUsersRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + UserIds []int64 `protobuf:"varint,2,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - UserIds []int64 `protobuf:"varint,2,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BatchGetUsersRequest) Reset() { @@ -6338,11 +6276,10 @@ func (x *BatchGetUsersRequest) GetUserIds() []int64 { // BatchGetUsersResponse 返回按 user_id 索引的用户主状态。 type BatchGetUsersResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Users map[int64]*User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` unknownFields protoimpl.UnknownFields - - Users map[int64]*User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + sizeCache protoimpl.SizeCache } func (x *BatchGetUsersResponse) Reset() { @@ -6385,21 +6322,20 @@ func (x *BatchGetUsersResponse) GetUsers() map[int64]*User { // ActiveUserBanSummary 是后台用户列表读取的有效封禁摘要。 // expires_at_ms=0 只在 permanent=true 时表示永久;source 区分 admin、manager 和无新事实表记录的 legacy。 type ActiveUserBanSummary struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Active bool `protobuf:"varint,1,opt,name=active,proto3" json:"active,omitempty"` - Source string `protobuf:"bytes,2,opt,name=source,proto3" json:"source,omitempty"` - BanId string `protobuf:"bytes,3,opt,name=ban_id,json=banId,proto3" json:"ban_id,omitempty"` - Permanent bool `protobuf:"varint,4,opt,name=permanent,proto3" json:"permanent,omitempty"` - ExpiresAtMs int64 `protobuf:"varint,5,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - UserStatus UserStatus `protobuf:"varint,6,opt,name=user_status,json=userStatus,proto3,enum=hyapp.user.v1.UserStatus" json:"user_status,omitempty"` - OperatorType string `protobuf:"bytes,7,opt,name=operator_type,json=operatorType,proto3" json:"operator_type,omitempty"` - OperatorUserId int64 `protobuf:"varint,8,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - Reason string `protobuf:"bytes,9,opt,name=reason,proto3" json:"reason,omitempty"` - CreatedAtMs int64 `protobuf:"varint,10,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - ActiveBanCount int32 `protobuf:"varint,11,opt,name=active_ban_count,json=activeBanCount,proto3" json:"active_ban_count,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Active bool `protobuf:"varint,1,opt,name=active,proto3" json:"active,omitempty"` + Source string `protobuf:"bytes,2,opt,name=source,proto3" json:"source,omitempty"` + BanId string `protobuf:"bytes,3,opt,name=ban_id,json=banId,proto3" json:"ban_id,omitempty"` + Permanent bool `protobuf:"varint,4,opt,name=permanent,proto3" json:"permanent,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,5,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` + UserStatus UserStatus `protobuf:"varint,6,opt,name=user_status,json=userStatus,proto3,enum=hyapp.user.v1.UserStatus" json:"user_status,omitempty"` + OperatorType string `protobuf:"bytes,7,opt,name=operator_type,json=operatorType,proto3" json:"operator_type,omitempty"` + OperatorUserId int64 `protobuf:"varint,8,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + Reason string `protobuf:"bytes,9,opt,name=reason,proto3" json:"reason,omitempty"` + CreatedAtMs int64 `protobuf:"varint,10,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + ActiveBanCount int32 `protobuf:"varint,11,opt,name=active_ban_count,json=activeBanCount,proto3" json:"active_ban_count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ActiveUserBanSummary) Reset() { @@ -6512,20 +6448,19 @@ func (x *ActiveUserBanSummary) GetActiveBanCount() int32 { // UserAdminProfile 聚合后台用户列表和详情需要的 user-service owner 事实。 // roles 只返回当前有效身份:host、agency、bd、bd_leader、coin_seller、manager。 type UserAdminProfile struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` - Birth string `protobuf:"bytes,2,opt,name=birth,proto3" json:"birth,omitempty"` - RegisterDevice string `protobuf:"bytes,3,opt,name=register_device,json=registerDevice,proto3" json:"register_device,omitempty"` - LastSuccessLoginAtMs int64 `protobuf:"varint,4,opt,name=last_success_login_at_ms,json=lastSuccessLoginAtMs,proto3" json:"last_success_login_at_ms,omitempty"` - Roles []string `protobuf:"bytes,5,rep,name=roles,proto3" json:"roles,omitempty"` - Ban *ActiveUserBanSummary `protobuf:"bytes,6,opt,name=ban,proto3" json:"ban,omitempty"` - LastOperatorType string `protobuf:"bytes,7,opt,name=last_operator_type,json=lastOperatorType,proto3" json:"last_operator_type,omitempty"` - LastOperatorUserId int64 `protobuf:"varint,8,opt,name=last_operator_user_id,json=lastOperatorUserId,proto3" json:"last_operator_user_id,omitempty"` - LastOperationReason string `protobuf:"bytes,9,opt,name=last_operation_reason,json=lastOperationReason,proto3" json:"last_operation_reason,omitempty"` - LastOperationAtMs int64 `protobuf:"varint,10,opt,name=last_operation_at_ms,json=lastOperationAtMs,proto3" json:"last_operation_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` + Birth string `protobuf:"bytes,2,opt,name=birth,proto3" json:"birth,omitempty"` + RegisterDevice string `protobuf:"bytes,3,opt,name=register_device,json=registerDevice,proto3" json:"register_device,omitempty"` + LastSuccessLoginAtMs int64 `protobuf:"varint,4,opt,name=last_success_login_at_ms,json=lastSuccessLoginAtMs,proto3" json:"last_success_login_at_ms,omitempty"` + Roles []string `protobuf:"bytes,5,rep,name=roles,proto3" json:"roles,omitempty"` + Ban *ActiveUserBanSummary `protobuf:"bytes,6,opt,name=ban,proto3" json:"ban,omitempty"` + LastOperatorType string `protobuf:"bytes,7,opt,name=last_operator_type,json=lastOperatorType,proto3" json:"last_operator_type,omitempty"` + LastOperatorUserId int64 `protobuf:"varint,8,opt,name=last_operator_user_id,json=lastOperatorUserId,proto3" json:"last_operator_user_id,omitempty"` + LastOperationReason string `protobuf:"bytes,9,opt,name=last_operation_reason,json=lastOperationReason,proto3" json:"last_operation_reason,omitempty"` + LastOperationAtMs int64 `protobuf:"varint,10,opt,name=last_operation_at_ms,json=lastOperationAtMs,proto3" json:"last_operation_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *UserAdminProfile) Reset() { @@ -6629,12 +6564,11 @@ func (x *UserAdminProfile) GetLastOperationAtMs() int64 { } type BatchGetUserAdminProfilesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + UserIds []int64 `protobuf:"varint,2,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - UserIds []int64 `protobuf:"varint,2,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BatchGetUserAdminProfilesRequest) Reset() { @@ -6682,11 +6616,10 @@ func (x *BatchGetUserAdminProfilesRequest) GetUserIds() []int64 { } type BatchGetUserAdminProfilesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Profiles map[int64]*UserAdminProfile `protobuf:"bytes,1,rep,name=profiles,proto3" json:"profiles,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` unknownFields protoimpl.UnknownFields - - Profiles map[int64]*UserAdminProfile `protobuf:"bytes,1,rep,name=profiles,proto3" json:"profiles,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + sizeCache protoimpl.SizeCache } func (x *BatchGetUserAdminProfilesResponse) Reset() { @@ -6730,13 +6663,12 @@ func (x *BatchGetUserAdminProfilesResponse) GetProfiles() map[int64]*UserAdminPr // 该链路不写 login_audit,也不修改 session 行——后台取 token 不能污染用户“最近活跃/最近登录”事实; // 审计责任由 admin 侧操作日志承担。 type AdminIssueUserAccessTokenRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,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 - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,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"` + sizeCache protoimpl.SizeCache } func (x *AdminIssueUserAccessTokenRequest) Reset() { @@ -6793,16 +6725,15 @@ func (x *AdminIssueUserAccessTokenRequest) GetUserId() int64 { // AdminIssueUserAccessTokenResponse 返回重签的 access token 和所属 session 的定位信息。 // 不返回 refresh token:后台没有轮换会话的理由,refresh 原文也不允许离开登录主链路。 type AdminIssueUserAccessTokenResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"` - TokenType string `protobuf:"bytes,2,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"` - ExpiresInSec int64 `protobuf:"varint,3,opt,name=expires_in_sec,json=expiresInSec,proto3" json:"expires_in_sec,omitempty"` - SessionId string `protobuf:"bytes,4,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` - DeviceId string `protobuf:"bytes,5,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` - SessionLastHeartbeatAtMs int64 `protobuf:"varint,6,opt,name=session_last_heartbeat_at_ms,json=sessionLastHeartbeatAtMs,proto3" json:"session_last_heartbeat_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"` + TokenType string `protobuf:"bytes,2,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"` + ExpiresInSec int64 `protobuf:"varint,3,opt,name=expires_in_sec,json=expiresInSec,proto3" json:"expires_in_sec,omitempty"` + SessionId string `protobuf:"bytes,4,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + DeviceId string `protobuf:"bytes,5,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` + SessionLastHeartbeatAtMs int64 `protobuf:"varint,6,opt,name=session_last_heartbeat_at_ms,json=sessionLastHeartbeatAtMs,proto3" json:"session_last_heartbeat_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminIssueUserAccessTokenResponse) Reset() { @@ -6879,14 +6810,13 @@ func (x *AdminIssueUserAccessTokenResponse) GetSessionLastHeartbeatAtMs() int64 // RoomBasicUser 是房间首屏只需要的用户展示基础资料。 type RoomBasicUser struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` + Avatar string `protobuf:"bytes,3,opt,name=avatar,proto3" json:"avatar,omitempty"` + DisplayUserId string `protobuf:"bytes,4,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` unknownFields protoimpl.UnknownFields - - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` - Avatar string `protobuf:"bytes,3,opt,name=avatar,proto3" json:"avatar,omitempty"` - DisplayUserId string `protobuf:"bytes,4,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RoomBasicUser) Reset() { @@ -6949,12 +6879,11 @@ func (x *RoomBasicUser) GetDisplayUserId() string { // BatchGetRoomBasicUsersRequest 为房间进房 lite 首屏批量读取最小用户资料。 type BatchGetRoomBasicUsersRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + UserIds []int64 `protobuf:"varint,2,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - UserIds []int64 `protobuf:"varint,2,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BatchGetRoomBasicUsersRequest) Reset() { @@ -7003,11 +6932,10 @@ func (x *BatchGetRoomBasicUsersRequest) GetUserIds() []int64 { // BatchGetRoomBasicUsersResponse 返回按 user_id 索引的房间首屏基础资料。 type BatchGetRoomBasicUsersResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Users map[int64]*RoomBasicUser `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` unknownFields protoimpl.UnknownFields - - Users map[int64]*RoomBasicUser `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + sizeCache protoimpl.SizeCache } func (x *BatchGetRoomBasicUsersResponse) Reset() { @@ -7049,16 +6977,15 @@ func (x *BatchGetRoomBasicUsersResponse) GetUsers() map[int64]*RoomBasicUser { // ListUserIDsRequest 给低频后台 fanout/重算任务按 user_id 游标读取目标用户。 type ListUserIDsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + TargetScope string `protobuf:"bytes,2,opt,name=target_scope,json=targetScope,proto3" json:"target_scope,omitempty"` + CursorUserId int64 `protobuf:"varint,3,opt,name=cursor_user_id,json=cursorUserId,proto3" json:"cursor_user_id,omitempty"` + PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + RegionId int64 `protobuf:"varint,5,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + Country string `protobuf:"bytes,6,opt,name=country,proto3" json:"country,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - TargetScope string `protobuf:"bytes,2,opt,name=target_scope,json=targetScope,proto3" json:"target_scope,omitempty"` - CursorUserId int64 `protobuf:"varint,3,opt,name=cursor_user_id,json=cursorUserId,proto3" json:"cursor_user_id,omitempty"` - PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - RegionId int64 `protobuf:"varint,5,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - Country string `protobuf:"bytes,6,opt,name=country,proto3" json:"country,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListUserIDsRequest) Reset() { @@ -7135,13 +7062,12 @@ func (x *ListUserIDsRequest) GetCountry() string { // ListUserIDsResponse 返回一页递增 user_id,调用方必须用 next_cursor_user_id 继续。 type ListUserIDsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - UserIds []int64 `protobuf:"varint,1,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` - NextCursorUserId int64 `protobuf:"varint,2,opt,name=next_cursor_user_id,json=nextCursorUserId,proto3" json:"next_cursor_user_id,omitempty"` - Done bool `protobuf:"varint,3,opt,name=done,proto3" json:"done,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + UserIds []int64 `protobuf:"varint,1,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` + NextCursorUserId int64 `protobuf:"varint,2,opt,name=next_cursor_user_id,json=nextCursorUserId,proto3" json:"next_cursor_user_id,omitempty"` + Done bool `protobuf:"varint,3,opt,name=done,proto3" json:"done,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListUserIDsResponse) Reset() { @@ -7197,16 +7123,15 @@ func (x *ListUserIDsResponse) GetDone() bool { // UpdateUserProfileRequest 修改用户可自助维护的基础资料。 type UpdateUserProfileRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + Username *string `protobuf:"bytes,3,opt,name=username,proto3,oneof" json:"username,omitempty"` + Avatar *string `protobuf:"bytes,4,opt,name=avatar,proto3,oneof" json:"avatar,omitempty"` + Birth *string `protobuf:"bytes,5,opt,name=birth,proto3,oneof" json:"birth,omitempty"` + Gender *string `protobuf:"bytes,6,opt,name=gender,proto3,oneof" json:"gender,omitempty"` 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"` - Username *string `protobuf:"bytes,3,opt,name=username,proto3,oneof" json:"username,omitempty"` - Avatar *string `protobuf:"bytes,4,opt,name=avatar,proto3,oneof" json:"avatar,omitempty"` - Birth *string `protobuf:"bytes,5,opt,name=birth,proto3,oneof" json:"birth,omitempty"` - Gender *string `protobuf:"bytes,6,opt,name=gender,proto3,oneof" json:"gender,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UpdateUserProfileRequest) Reset() { @@ -7283,11 +7208,10 @@ func (x *UpdateUserProfileRequest) GetGender() string { // UpdateUserProfileResponse 返回更新后的用户资料投影。 type UpdateUserProfileResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` unknownFields protoimpl.UnknownFields - - User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UpdateUserProfileResponse) Reset() { @@ -7329,13 +7253,12 @@ func (x *UpdateUserProfileResponse) GetUser() *User { // UpdateUserProfileBackgroundRequest 只修改用户个人信息页背景图。 type UpdateUserProfileBackgroundRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + ProfileBgImg string `protobuf:"bytes,3,opt,name=profile_bg_img,json=profileBgImg,proto3" json:"profile_bg_img,omitempty"` 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"` - ProfileBgImg string `protobuf:"bytes,3,opt,name=profile_bg_img,json=profileBgImg,proto3" json:"profile_bg_img,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UpdateUserProfileBackgroundRequest) Reset() { @@ -7391,11 +7314,10 @@ func (x *UpdateUserProfileBackgroundRequest) GetProfileBgImg() string { // UpdateUserProfileBackgroundResponse 返回写入后的用户资料投影。 type UpdateUserProfileBackgroundResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` unknownFields protoimpl.UnknownFields - - User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UpdateUserProfileBackgroundResponse) Reset() { @@ -7437,13 +7359,12 @@ func (x *UpdateUserProfileBackgroundResponse) GetUser() *User { // UpdateUserContactInfoRequest 只修改用户主资料上的联系方式,供不同经营身份共用。 type UpdateUserContactInfoRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + ContactInfo string `protobuf:"bytes,3,opt,name=contact_info,json=contactInfo,proto3" json:"contact_info,omitempty"` 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"` - ContactInfo string `protobuf:"bytes,3,opt,name=contact_info,json=contactInfo,proto3" json:"contact_info,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UpdateUserContactInfoRequest) Reset() { @@ -7499,11 +7420,10 @@ func (x *UpdateUserContactInfoRequest) GetContactInfo() string { // UpdateUserContactInfoResponse 返回写入后的用户资料投影。 type UpdateUserContactInfoResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` unknownFields protoimpl.UnknownFields - - User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UpdateUserContactInfoResponse) Reset() { @@ -7545,13 +7465,12 @@ func (x *UpdateUserContactInfoResponse) GetUser() *User { // UpdateUserWithdrawAddressRequest 只修改用户默认提现地址,提现订单会在 wallet-service 另行快照。 type UpdateUserWithdrawAddressRequest struct { - 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"` - UsdtTrc20Address string `protobuf:"bytes,3,opt,name=usdt_trc20_address,json=usdtTrc20Address,proto3" json:"usdt_trc20_address,omitempty"` + 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"` + UsdtTrc20Address string `protobuf:"bytes,3,opt,name=usdt_trc20_address,json=usdtTrc20Address,proto3" json:"usdt_trc20_address,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *UpdateUserWithdrawAddressRequest) Reset() { @@ -7607,11 +7526,10 @@ func (x *UpdateUserWithdrawAddressRequest) GetUsdtTrc20Address() string { // UpdateUserWithdrawAddressResponse 返回写入后的用户资料投影。 type UpdateUserWithdrawAddressResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` unknownFields protoimpl.UnknownFields - - User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UpdateUserWithdrawAddressResponse) Reset() { @@ -7653,13 +7571,12 @@ func (x *UpdateUserWithdrawAddressResponse) GetUser() *User { // ChangeUserCountryRequest 是 App 用户自助修改国家入口;受限业务身份不允许自助修改。 type ChangeUserCountryRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + Country string `protobuf:"bytes,3,opt,name=country,proto3" json:"country,omitempty"` 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"` - Country string `protobuf:"bytes,3,opt,name=country,proto3" json:"country,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ChangeUserCountryRequest) Reset() { @@ -7715,15 +7632,14 @@ func (x *ChangeUserCountryRequest) GetCountry() string { // AdminChangeUserCountryRequest 是后台显式覆盖用户国家入口;它绕过 App 自助身份限制。 type AdminChangeUserCountryRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminChangeUserCountryRequest) Reset() { @@ -7793,15 +7709,14 @@ func (x *AdminChangeUserCountryRequest) GetReason() string { // ChangeUserCountryResponse 返回更新后的用户资料和下一次可修改时间。 type ChangeUserCountryResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` - NextChangeAllowedAtMs int64 `protobuf:"varint,2,opt,name=next_change_allowed_at_ms,json=nextChangeAllowedAtMs,proto3" json:"next_change_allowed_at_ms,omitempty"` - OldRegionId int64 `protobuf:"varint,3,opt,name=old_region_id,json=oldRegionId,proto3" json:"old_region_id,omitempty"` - NewRegionId int64 `protobuf:"varint,4,opt,name=new_region_id,json=newRegionId,proto3" json:"new_region_id,omitempty"` - RegionChanged bool `protobuf:"varint,5,opt,name=region_changed,json=regionChanged,proto3" json:"region_changed,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` + NextChangeAllowedAtMs int64 `protobuf:"varint,2,opt,name=next_change_allowed_at_ms,json=nextChangeAllowedAtMs,proto3" json:"next_change_allowed_at_ms,omitempty"` + OldRegionId int64 `protobuf:"varint,3,opt,name=old_region_id,json=oldRegionId,proto3" json:"old_region_id,omitempty"` + NewRegionId int64 `protobuf:"varint,4,opt,name=new_region_id,json=newRegionId,proto3" json:"new_region_id,omitempty"` + RegionChanged bool `protobuf:"varint,5,opt,name=region_changed,json=regionChanged,proto3" json:"region_changed,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ChangeUserCountryResponse) Reset() { @@ -7872,17 +7787,16 @@ func (x *ChangeUserCountryResponse) GetRegionChanged() bool { // SetUserStatusRequest 是封禁、停用和恢复用户的通用内部入口。 // 非 active 状态会同步吊销 refresh session,并把仍在有效期内的 access session 写入 gateway denylist。 type SetUserStatusRequest struct { - 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"` - Status UserStatus `protobuf:"varint,3,opt,name=status,proto3,enum=hyapp.user.v1.UserStatus" json:"status,omitempty"` - OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` + 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"` + Status UserStatus `protobuf:"varint,3,opt,name=status,proto3,enum=hyapp.user.v1.UserStatus" json:"status,omitempty"` + OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` // operator_type 区分 admin、app_user、system,避免不同身份体系共用一个整数 ID 后无法追溯。 - OperatorType string `protobuf:"bytes,6,opt,name=operator_type,json=operatorType,proto3" json:"operator_type,omitempty"` + OperatorType string `protobuf:"bytes,6,opt,name=operator_type,json=operatorType,proto3" json:"operator_type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SetUserStatusRequest) Reset() { @@ -7960,21 +7874,20 @@ func (x *SetUserStatusRequest) GetOperatorType() string { // SetUserStatusResponse 返回用户当前状态和封禁相关副作用结果。 // 外部副作用字段用于后台或 App 管理入口判断是否需要重试补偿。 type SetUserStatusResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` - RevokedSessionCount int64 `protobuf:"varint,2,opt,name=revoked_session_count,json=revokedSessionCount,proto3" json:"revoked_session_count,omitempty"` - ImKicked bool `protobuf:"varint,3,opt,name=im_kicked,json=imKicked,proto3" json:"im_kicked,omitempty"` - ImKickError string `protobuf:"bytes,4,opt,name=im_kick_error,json=imKickError,proto3" json:"im_kick_error,omitempty"` - RoomEvicted bool `protobuf:"varint,5,opt,name=room_evicted,json=roomEvicted,proto3" json:"room_evicted,omitempty"` - RoomId string `protobuf:"bytes,6,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - RtcKicked bool `protobuf:"varint,7,opt,name=rtc_kicked,json=rtcKicked,proto3" json:"rtc_kicked,omitempty"` - RoomEvictError string `protobuf:"bytes,8,opt,name=room_evict_error,json=roomEvictError,proto3" json:"room_evict_error,omitempty"` - RtcKickError string `protobuf:"bytes,9,opt,name=rtc_kick_error,json=rtcKickError,proto3" json:"rtc_kick_error,omitempty"` - AccessTokenRevoked bool `protobuf:"varint,10,opt,name=access_token_revoked,json=accessTokenRevoked,proto3" json:"access_token_revoked,omitempty"` - AccessTokenRevokeError string `protobuf:"bytes,11,opt,name=access_token_revoke_error,json=accessTokenRevokeError,proto3" json:"access_token_revoke_error,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` + RevokedSessionCount int64 `protobuf:"varint,2,opt,name=revoked_session_count,json=revokedSessionCount,proto3" json:"revoked_session_count,omitempty"` + ImKicked bool `protobuf:"varint,3,opt,name=im_kicked,json=imKicked,proto3" json:"im_kicked,omitempty"` + ImKickError string `protobuf:"bytes,4,opt,name=im_kick_error,json=imKickError,proto3" json:"im_kick_error,omitempty"` + RoomEvicted bool `protobuf:"varint,5,opt,name=room_evicted,json=roomEvicted,proto3" json:"room_evicted,omitempty"` + RoomId string `protobuf:"bytes,6,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + RtcKicked bool `protobuf:"varint,7,opt,name=rtc_kicked,json=rtcKicked,proto3" json:"rtc_kicked,omitempty"` + RoomEvictError string `protobuf:"bytes,8,opt,name=room_evict_error,json=roomEvictError,proto3" json:"room_evict_error,omitempty"` + RtcKickError string `protobuf:"bytes,9,opt,name=rtc_kick_error,json=rtcKickError,proto3" json:"rtc_kick_error,omitempty"` + AccessTokenRevoked bool `protobuf:"varint,10,opt,name=access_token_revoked,json=accessTokenRevoked,proto3" json:"access_token_revoked,omitempty"` + AccessTokenRevokeError string `protobuf:"bytes,11,opt,name=access_token_revoke_error,json=accessTokenRevokeError,proto3" json:"access_token_revoke_error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SetUserStatusResponse) Reset() { @@ -8086,23 +7999,22 @@ func (x *SetUserStatusResponse) GetAccessTokenRevokeError() string { // AdminUserBan 是后台管理员封禁的独立事实;expires_at_ms=0 表示永久封禁。 type AdminUserBan struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BanId string `protobuf:"bytes,1,opt,name=ban_id,json=banId,proto3" json:"ban_id,omitempty"` - CommandId string `protobuf:"bytes,2,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - ExpiresAtMs int64 `protobuf:"varint,4,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - Permanent bool `protobuf:"varint,5,opt,name=permanent,proto3" json:"permanent,omitempty"` - Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` - Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` - OperatorAdminId int64 `protobuf:"varint,8,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_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"` - ReleasedByAdminId int64 `protobuf:"varint,11,opt,name=released_by_admin_id,json=releasedByAdminId,proto3" json:"released_by_admin_id,omitempty"` - ReleasedReason string `protobuf:"bytes,12,opt,name=released_reason,json=releasedReason,proto3" json:"released_reason,omitempty"` - ReleasedAtMs int64 `protobuf:"varint,13,opt,name=released_at_ms,json=releasedAtMs,proto3" json:"released_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + BanId string `protobuf:"bytes,1,opt,name=ban_id,json=banId,proto3" json:"ban_id,omitempty"` + CommandId string `protobuf:"bytes,2,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,4,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` + Permanent bool `protobuf:"varint,5,opt,name=permanent,proto3" json:"permanent,omitempty"` + Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` + Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` + OperatorAdminId int64 `protobuf:"varint,8,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_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"` + ReleasedByAdminId int64 `protobuf:"varint,11,opt,name=released_by_admin_id,json=releasedByAdminId,proto3" json:"released_by_admin_id,omitempty"` + ReleasedReason string `protobuf:"bytes,12,opt,name=released_reason,json=releasedReason,proto3" json:"released_reason,omitempty"` + ReleasedAtMs int64 `protobuf:"varint,13,opt,name=released_at_ms,json=releasedAtMs,proto3" json:"released_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminUserBan) Reset() { @@ -8227,16 +8139,15 @@ func (x *AdminUserBan) GetReleasedAtMs() int64 { } type AdminBanUserRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - 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"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - ExpiresAtMs int64 `protobuf:"varint,4,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - OperatorAdminId int64 `protobuf:"varint,5,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` - Reason string `protobuf:"bytes,6,opt,name=reason,proto3" json:"reason,omitempty"` + 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"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,4,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` + OperatorAdminId int64 `protobuf:"varint,5,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + Reason string `protobuf:"bytes,6,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminBanUserRequest) Reset() { @@ -8312,12 +8223,11 @@ func (x *AdminBanUserRequest) GetReason() string { } type AdminBanUserResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Ban *AdminUserBan `protobuf:"bytes,1,opt,name=ban,proto3" json:"ban,omitempty"` + Status *SetUserStatusResponse `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` unknownFields protoimpl.UnknownFields - - Ban *AdminUserBan `protobuf:"bytes,1,opt,name=ban,proto3" json:"ban,omitempty"` - Status *SetUserStatusResponse `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AdminBanUserResponse) Reset() { @@ -8366,16 +8276,15 @@ func (x *AdminBanUserResponse) GetStatus() *SetUserStatusResponse { // AdminUnbanUserRequest 由后台管理员强制释放目标用户全部管理员、经理和 legacy 封禁来源。 type AdminUnbanUserRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` // ban_id 已废弃;保留字段号用于滚动发布兼容,强制解封始终按 target_user_id 处理全部有效事实。 BanId string `protobuf:"bytes,2,opt,name=ban_id,json=banId,proto3" json:"ban_id,omitempty"` TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` OperatorAdminId int64 `protobuf:"varint,4,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminUnbanUserRequest) Reset() { @@ -8444,16 +8353,15 @@ func (x *AdminUnbanUserRequest) GetReason() string { } type AdminUnbanUserResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // ban 仅为旧客户端保留;强制解封可能只释放经理或 legacy 来源,因此新调用方不应依赖该字段。 Ban *AdminUserBan `protobuf:"bytes,1,opt,name=ban,proto3" json:"ban,omitempty"` Status *SetUserStatusResponse `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` ReleasedAdminBanCount int64 `protobuf:"varint,3,opt,name=released_admin_ban_count,json=releasedAdminBanCount,proto3" json:"released_admin_ban_count,omitempty"` ReleasedManagerBlockCount int64 `protobuf:"varint,4,opt,name=released_manager_block_count,json=releasedManagerBlockCount,proto3" json:"released_manager_block_count,omitempty"` StatusRestored bool `protobuf:"varint,5,opt,name=status_restored,json=statusRestored,proto3" json:"status_restored,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminUnbanUserResponse) Reset() { @@ -8522,22 +8430,21 @@ func (x *AdminUnbanUserResponse) GetStatusRestored() bool { } type ManagerUserBlock struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BlockId string `protobuf:"bytes,1,opt,name=block_id,json=blockId,proto3" json:"block_id,omitempty"` - ManagerUserId int64 `protobuf:"varint,2,opt,name=manager_user_id,json=managerUserId,proto3" json:"manager_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - TargetDisplayUserId string `protobuf:"bytes,4,opt,name=target_display_user_id,json=targetDisplayUserId,proto3" json:"target_display_user_id,omitempty"` - TargetUsername string `protobuf:"bytes,5,opt,name=target_username,json=targetUsername,proto3" json:"target_username,omitempty"` - TargetAvatar string `protobuf:"bytes,6,opt,name=target_avatar,json=targetAvatar,proto3" json:"target_avatar,omitempty"` - Country string `protobuf:"bytes,7,opt,name=country,proto3" json:"country,omitempty"` - BlockedUntilMs int64 `protobuf:"varint,8,opt,name=blocked_until_ms,json=blockedUntilMs,proto3" json:"blocked_until_ms,omitempty"` - Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"` - Reason string `protobuf:"bytes,10,opt,name=reason,proto3" json:"reason,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"` + state protoimpl.MessageState `protogen:"open.v1"` + BlockId string `protobuf:"bytes,1,opt,name=block_id,json=blockId,proto3" json:"block_id,omitempty"` + ManagerUserId int64 `protobuf:"varint,2,opt,name=manager_user_id,json=managerUserId,proto3" json:"manager_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + TargetDisplayUserId string `protobuf:"bytes,4,opt,name=target_display_user_id,json=targetDisplayUserId,proto3" json:"target_display_user_id,omitempty"` + TargetUsername string `protobuf:"bytes,5,opt,name=target_username,json=targetUsername,proto3" json:"target_username,omitempty"` + TargetAvatar string `protobuf:"bytes,6,opt,name=target_avatar,json=targetAvatar,proto3" json:"target_avatar,omitempty"` + Country string `protobuf:"bytes,7,opt,name=country,proto3" json:"country,omitempty"` + BlockedUntilMs int64 `protobuf:"varint,8,opt,name=blocked_until_ms,json=blockedUntilMs,proto3" json:"blocked_until_ms,omitempty"` + Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"` + Reason string `protobuf:"bytes,10,opt,name=reason,proto3" json:"reason,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 } func (x *ManagerUserBlock) Reset() { @@ -8655,16 +8562,15 @@ func (x *ManagerUserBlock) GetUpdatedAtMs() int64 { } type CreateManagerUserBlockRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - 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"` - ManagerUserId int64 `protobuf:"varint,3,opt,name=manager_user_id,json=managerUserId,proto3" json:"manager_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,4,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - BlockedUntilMs int64 `protobuf:"varint,5,opt,name=blocked_until_ms,json=blockedUntilMs,proto3" json:"blocked_until_ms,omitempty"` - Reason string `protobuf:"bytes,6,opt,name=reason,proto3" json:"reason,omitempty"` + 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"` + ManagerUserId int64 `protobuf:"varint,3,opt,name=manager_user_id,json=managerUserId,proto3" json:"manager_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,4,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + BlockedUntilMs int64 `protobuf:"varint,5,opt,name=blocked_until_ms,json=blockedUntilMs,proto3" json:"blocked_until_ms,omitempty"` + Reason string `protobuf:"bytes,6,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CreateManagerUserBlockRequest) Reset() { @@ -8740,12 +8646,11 @@ func (x *CreateManagerUserBlockRequest) GetReason() string { } type CreateManagerUserBlockResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Block *ManagerUserBlock `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + Status *SetUserStatusResponse `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` unknownFields protoimpl.UnknownFields - - Block *ManagerUserBlock `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - Status *SetUserStatusResponse `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CreateManagerUserBlockResponse) Reset() { @@ -8793,14 +8698,13 @@ func (x *CreateManagerUserBlockResponse) GetStatus() *SetUserStatusResponse { } type ListManagerUserBlocksRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + ManagerUserId int64 `protobuf:"varint,2,opt,name=manager_user_id,json=managerUserId,proto3" json:"manager_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 - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - ManagerUserId int64 `protobuf:"varint,2,opt,name=manager_user_id,json=managerUserId,proto3" json:"manager_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"` + sizeCache protoimpl.SizeCache } func (x *ListManagerUserBlocksRequest) Reset() { @@ -8862,11 +8766,10 @@ func (x *ListManagerUserBlocksRequest) GetPageSize() int32 { } type ListManagerUserBlocksResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Blocks []*ManagerUserBlock `protobuf:"bytes,1,rep,name=blocks,proto3" json:"blocks,omitempty"` unknownFields protoimpl.UnknownFields - - Blocks []*ManagerUserBlock `protobuf:"bytes,1,rep,name=blocks,proto3" json:"blocks,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListManagerUserBlocksResponse) Reset() { @@ -8907,14 +8810,13 @@ func (x *ListManagerUserBlocksResponse) GetBlocks() []*ManagerUserBlock { } type UnblockManagerUserRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + ManagerUserId int64 `protobuf:"varint,2,opt,name=manager_user_id,json=managerUserId,proto3" json:"manager_user_id,omitempty"` + BlockId string `protobuf:"bytes,3,opt,name=block_id,json=blockId,proto3" json:"block_id,omitempty"` + Reason string `protobuf:"bytes,4,opt,name=reason,proto3" json:"reason,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - ManagerUserId int64 `protobuf:"varint,2,opt,name=manager_user_id,json=managerUserId,proto3" json:"manager_user_id,omitempty"` - BlockId string `protobuf:"bytes,3,opt,name=block_id,json=blockId,proto3" json:"block_id,omitempty"` - Reason string `protobuf:"bytes,4,opt,name=reason,proto3" json:"reason,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UnblockManagerUserRequest) Reset() { @@ -8976,12 +8878,11 @@ func (x *UnblockManagerUserRequest) GetReason() string { } type UnblockManagerUserResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Block *ManagerUserBlock `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + Status *SetUserStatusResponse `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` unknownFields protoimpl.UnknownFields - - Block *ManagerUserBlock `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - Status *SetUserStatusResponse `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UnblockManagerUserResponse) Reset() { @@ -9030,17 +8931,16 @@ func (x *UnblockManagerUserResponse) GetStatus() *SetUserStatusResponse { // CompleteOnboardingRequest 是注册页唯一资料提交入口。 type CompleteOnboardingRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"` + Avatar string `protobuf:"bytes,4,opt,name=avatar,proto3" json:"avatar,omitempty"` + Country string `protobuf:"bytes,5,opt,name=country,proto3" json:"country,omitempty"` + Gender string `protobuf:"bytes,6,opt,name=gender,proto3" json:"gender,omitempty"` + InviteCode string `protobuf:"bytes,7,opt,name=invite_code,json=inviteCode,proto3" json:"invite_code,omitempty"` 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"` - Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"` - Avatar string `protobuf:"bytes,4,opt,name=avatar,proto3" json:"avatar,omitempty"` - Country string `protobuf:"bytes,5,opt,name=country,proto3" json:"country,omitempty"` - Gender string `protobuf:"bytes,6,opt,name=gender,proto3" json:"gender,omitempty"` - InviteCode string `protobuf:"bytes,7,opt,name=invite_code,json=inviteCode,proto3" json:"invite_code,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CompleteOnboardingRequest) Reset() { @@ -9124,16 +9024,15 @@ func (x *CompleteOnboardingRequest) GetInviteCode() string { // CompleteOnboardingResponse 返回固化后的最小注册状态。 type CompleteOnboardingResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` - ProfileCompleted bool `protobuf:"varint,2,opt,name=profile_completed,json=profileCompleted,proto3" json:"profile_completed,omitempty"` - ProfileCompletedAtMs int64 `protobuf:"varint,3,opt,name=profile_completed_at_ms,json=profileCompletedAtMs,proto3" json:"profile_completed_at_ms,omitempty"` - OnboardingStatus string `protobuf:"bytes,4,opt,name=onboarding_status,json=onboardingStatus,proto3" json:"onboarding_status,omitempty"` - Token *AuthToken `protobuf:"bytes,5,opt,name=token,proto3" json:"token,omitempty"` - Invite *InviteBinding `protobuf:"bytes,6,opt,name=invite,proto3" json:"invite,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` + ProfileCompleted bool `protobuf:"varint,2,opt,name=profile_completed,json=profileCompleted,proto3" json:"profile_completed,omitempty"` + ProfileCompletedAtMs int64 `protobuf:"varint,3,opt,name=profile_completed_at_ms,json=profileCompletedAtMs,proto3" json:"profile_completed_at_ms,omitempty"` + OnboardingStatus string `protobuf:"bytes,4,opt,name=onboarding_status,json=onboardingStatus,proto3" json:"onboarding_status,omitempty"` + Token *AuthToken `protobuf:"bytes,5,opt,name=token,proto3" json:"token,omitempty"` + Invite *InviteBinding `protobuf:"bytes,6,opt,name=invite,proto3" json:"invite,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CompleteOnboardingResponse) Reset() { @@ -9210,13 +9109,12 @@ func (x *CompleteOnboardingResponse) GetInvite() *InviteBinding { // SearchInviteReferrerRequest 用当前用户国家约束可绑定邀请码的搜索范围。 type SearchInviteReferrerRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + InviteCode string `protobuf:"bytes,3,opt,name=invite_code,json=inviteCode,proto3" json:"invite_code,omitempty"` 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"` - InviteCode string `protobuf:"bytes,3,opt,name=invite_code,json=inviteCode,proto3" json:"invite_code,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SearchInviteReferrerRequest) Reset() { @@ -9271,11 +9169,10 @@ func (x *SearchInviteReferrerRequest) GetInviteCode() string { } type SearchInviteReferrerResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Inviter *User `protobuf:"bytes,1,opt,name=inviter,proto3" json:"inviter,omitempty"` unknownFields protoimpl.UnknownFields - - Inviter *User `protobuf:"bytes,1,opt,name=inviter,proto3" json:"inviter,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SearchInviteReferrerResponse) Reset() { @@ -9317,13 +9214,12 @@ func (x *SearchInviteReferrerResponse) GetInviter() *User { // BindInviteReferrerRequest 只接受用户输入的邀请码,归属由 user-service 事务内读取。 type BindInviteReferrerRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + InviteCode string `protobuf:"bytes,3,opt,name=invite_code,json=inviteCode,proto3" json:"invite_code,omitempty"` 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"` - InviteCode string `protobuf:"bytes,3,opt,name=invite_code,json=inviteCode,proto3" json:"invite_code,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BindInviteReferrerRequest) Reset() { @@ -9378,12 +9274,11 @@ func (x *BindInviteReferrerRequest) GetInviteCode() string { } type BindInviteReferrerResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Invite *InviteBinding `protobuf:"bytes,1,opt,name=invite,proto3" json:"invite,omitempty"` + Inviter *User `protobuf:"bytes,2,opt,name=inviter,proto3" json:"inviter,omitempty"` unknownFields protoimpl.UnknownFields - - Invite *InviteBinding `protobuf:"bytes,1,opt,name=invite,proto3" json:"invite,omitempty"` - Inviter *User `protobuf:"bytes,2,opt,name=inviter,proto3" json:"inviter,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BindInviteReferrerResponse) Reset() { @@ -9433,19 +9328,18 @@ func (x *BindInviteReferrerResponse) GetInviter() *User { // BindPushTokenRequest 绑定当前登录用户的系统推送 token。 // push token 只服务离线触达,不作为登录凭证或设备身份凭证。 type BindPushTokenRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + DeviceId string `protobuf:"bytes,3,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` + PushToken string `protobuf:"bytes,4,opt,name=push_token,json=pushToken,proto3" json:"push_token,omitempty"` + Provider string `protobuf:"bytes,5,opt,name=provider,proto3" json:"provider,omitempty"` + Platform string `protobuf:"bytes,6,opt,name=platform,proto3" json:"platform,omitempty"` + AppVersion string `protobuf:"bytes,7,opt,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"` + Language string `protobuf:"bytes,8,opt,name=language,proto3" json:"language,omitempty"` + Timezone string `protobuf:"bytes,9,opt,name=timezone,proto3" json:"timezone,omitempty"` 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"` - DeviceId string `protobuf:"bytes,3,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` - PushToken string `protobuf:"bytes,4,opt,name=push_token,json=pushToken,proto3" json:"push_token,omitempty"` - Provider string `protobuf:"bytes,5,opt,name=provider,proto3" json:"provider,omitempty"` - Platform string `protobuf:"bytes,6,opt,name=platform,proto3" json:"platform,omitempty"` - AppVersion string `protobuf:"bytes,7,opt,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"` - Language string `protobuf:"bytes,8,opt,name=language,proto3" json:"language,omitempty"` - Timezone string `protobuf:"bytes,9,opt,name=timezone,proto3" json:"timezone,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BindPushTokenRequest) Reset() { @@ -9542,12 +9436,11 @@ func (x *BindPushTokenRequest) GetTimezone() string { } type BindPushTokenResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Bound bool `protobuf:"varint,1,opt,name=bound,proto3" json:"bound,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,2,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` unknownFields protoimpl.UnknownFields - - Bound bool `protobuf:"varint,1,opt,name=bound,proto3" json:"bound,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,2,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BindPushTokenResponse) Reset() { @@ -9597,14 +9490,13 @@ func (x *BindPushTokenResponse) GetUpdatedAtMs() int64 { // DeletePushTokenRequest 删除或失效当前登录用户的系统推送 token。 // push_token 可为空;为空时按 user_id + device_id 失效该设备的 active token。 type DeletePushTokenRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + DeviceId string `protobuf:"bytes,3,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` + PushToken string `protobuf:"bytes,4,opt,name=push_token,json=pushToken,proto3" json:"push_token,omitempty"` 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"` - DeviceId string `protobuf:"bytes,3,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` - PushToken string `protobuf:"bytes,4,opt,name=push_token,json=pushToken,proto3" json:"push_token,omitempty"` + sizeCache protoimpl.SizeCache } func (x *DeletePushTokenRequest) Reset() { @@ -9666,12 +9558,11 @@ func (x *DeletePushTokenRequest) GetPushToken() string { } type DeletePushTokenResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,2,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` unknownFields protoimpl.UnknownFields - - Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,2,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *DeletePushTokenResponse) Reset() { @@ -9720,23 +9611,22 @@ func (x *DeletePushTokenResponse) GetUpdatedAtMs() int64 { // Country 是国家主数据投影,客户端和普通用户流程只提交 country_code。 type Country struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - CountryId int64 `protobuf:"varint,1,opt,name=country_id,json=countryId,proto3" json:"country_id,omitempty"` - CountryName string `protobuf:"bytes,2,opt,name=country_name,json=countryName,proto3" json:"country_name,omitempty"` - CountryCode string `protobuf:"bytes,3,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` - CountryDisplayName string `protobuf:"bytes,4,opt,name=country_display_name,json=countryDisplayName,proto3" json:"country_display_name,omitempty"` - SortOrder int32 `protobuf:"varint,6,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - CreatedAtMs int64 `protobuf:"varint,7,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,8,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - IsoAlpha3 string `protobuf:"bytes,9,opt,name=iso_alpha3,json=isoAlpha3,proto3" json:"iso_alpha3,omitempty"` - IsoNumeric string `protobuf:"bytes,10,opt,name=iso_numeric,json=isoNumeric,proto3" json:"iso_numeric,omitempty"` - PhoneCountryCode string `protobuf:"bytes,11,opt,name=phone_country_code,json=phoneCountryCode,proto3" json:"phone_country_code,omitempty"` - Enabled bool `protobuf:"varint,12,opt,name=enabled,proto3" json:"enabled,omitempty"` - Flag string `protobuf:"bytes,13,opt,name=flag,proto3" json:"flag,omitempty"` - AppCode string `protobuf:"bytes,14,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + CountryId int64 `protobuf:"varint,1,opt,name=country_id,json=countryId,proto3" json:"country_id,omitempty"` + CountryName string `protobuf:"bytes,2,opt,name=country_name,json=countryName,proto3" json:"country_name,omitempty"` + CountryCode string `protobuf:"bytes,3,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` + CountryDisplayName string `protobuf:"bytes,4,opt,name=country_display_name,json=countryDisplayName,proto3" json:"country_display_name,omitempty"` + SortOrder int32 `protobuf:"varint,6,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + CreatedAtMs int64 `protobuf:"varint,7,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,8,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + IsoAlpha3 string `protobuf:"bytes,9,opt,name=iso_alpha3,json=isoAlpha3,proto3" json:"iso_alpha3,omitempty"` + IsoNumeric string `protobuf:"bytes,10,opt,name=iso_numeric,json=isoNumeric,proto3" json:"iso_numeric,omitempty"` + PhoneCountryCode string `protobuf:"bytes,11,opt,name=phone_country_code,json=phoneCountryCode,proto3" json:"phone_country_code,omitempty"` + Enabled bool `protobuf:"varint,12,opt,name=enabled,proto3" json:"enabled,omitempty"` + Flag string `protobuf:"bytes,13,opt,name=flag,proto3" json:"flag,omitempty"` + AppCode string `protobuf:"bytes,14,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Country) Reset() { @@ -9862,19 +9752,18 @@ func (x *Country) GetAppCode() string { // Region 是区域主数据投影,countries 只包含当前 active 国家码。 type Region struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + RegionId int64 `protobuf:"varint,1,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + RegionCode string `protobuf:"bytes,2,opt,name=region_code,json=regionCode,proto3" json:"region_code,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + Countries []string `protobuf:"bytes,5,rep,name=countries,proto3" json:"countries,omitempty"` + SortOrder int32 `protobuf:"varint,6,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + CreatedAtMs int64 `protobuf:"varint,7,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,8,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + AppCode string `protobuf:"bytes,9,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` unknownFields protoimpl.UnknownFields - - RegionId int64 `protobuf:"varint,1,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - RegionCode string `protobuf:"bytes,2,opt,name=region_code,json=regionCode,proto3" json:"region_code,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` - Countries []string `protobuf:"bytes,5,rep,name=countries,proto3" json:"countries,omitempty"` - SortOrder int32 `protobuf:"varint,6,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - CreatedAtMs int64 `protobuf:"varint,7,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,8,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - AppCode string `protobuf:"bytes,9,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + sizeCache protoimpl.SizeCache } func (x *Region) Reset() { @@ -9971,12 +9860,11 @@ func (x *Region) GetAppCode() string { } type ListCountriesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Enabled *bool `protobuf:"varint,3,opt,name=enabled,proto3,oneof" json:"enabled,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Enabled *bool `protobuf:"varint,3,opt,name=enabled,proto3,oneof" json:"enabled,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListCountriesRequest) Reset() { @@ -10024,11 +9912,10 @@ func (x *ListCountriesRequest) GetEnabled() bool { } type ListCountriesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Countries []*Country `protobuf:"bytes,1,rep,name=countries,proto3" json:"countries,omitempty"` unknownFields protoimpl.UnknownFields - - Countries []*Country `protobuf:"bytes,1,rep,name=countries,proto3" json:"countries,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListCountriesResponse) Reset() { @@ -10070,20 +9957,19 @@ func (x *ListCountriesResponse) GetCountries() []*Country { // UpdateCountryRequest 只修改国家展示字段,不修改 country_code。 type UpdateCountryRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - CountryId int64 `protobuf:"varint,2,opt,name=country_id,json=countryId,proto3" json:"country_id,omitempty"` - CountryName string `protobuf:"bytes,3,opt,name=country_name,json=countryName,proto3" json:"country_name,omitempty"` - CountryDisplayName string `protobuf:"bytes,4,opt,name=country_display_name,json=countryDisplayName,proto3" json:"country_display_name,omitempty"` - SortOrder int32 `protobuf:"varint,5,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - OperatorUserId int64 `protobuf:"varint,6,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - IsoAlpha3 string `protobuf:"bytes,7,opt,name=iso_alpha3,json=isoAlpha3,proto3" json:"iso_alpha3,omitempty"` - IsoNumeric string `protobuf:"bytes,8,opt,name=iso_numeric,json=isoNumeric,proto3" json:"iso_numeric,omitempty"` - PhoneCountryCode string `protobuf:"bytes,9,opt,name=phone_country_code,json=phoneCountryCode,proto3" json:"phone_country_code,omitempty"` - Flag string `protobuf:"bytes,10,opt,name=flag,proto3" json:"flag,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + CountryId int64 `protobuf:"varint,2,opt,name=country_id,json=countryId,proto3" json:"country_id,omitempty"` + CountryName string `protobuf:"bytes,3,opt,name=country_name,json=countryName,proto3" json:"country_name,omitempty"` + CountryDisplayName string `protobuf:"bytes,4,opt,name=country_display_name,json=countryDisplayName,proto3" json:"country_display_name,omitempty"` + SortOrder int32 `protobuf:"varint,5,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + OperatorUserId int64 `protobuf:"varint,6,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + IsoAlpha3 string `protobuf:"bytes,7,opt,name=iso_alpha3,json=isoAlpha3,proto3" json:"iso_alpha3,omitempty"` + IsoNumeric string `protobuf:"bytes,8,opt,name=iso_numeric,json=isoNumeric,proto3" json:"iso_numeric,omitempty"` + PhoneCountryCode string `protobuf:"bytes,9,opt,name=phone_country_code,json=phoneCountryCode,proto3" json:"phone_country_code,omitempty"` + Flag string `protobuf:"bytes,10,opt,name=flag,proto3" json:"flag,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *UpdateCountryRequest) Reset() { @@ -10187,11 +10073,10 @@ func (x *UpdateCountryRequest) GetFlag() string { } type CountryResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Country *Country `protobuf:"bytes,1,opt,name=country,proto3" json:"country,omitempty"` unknownFields protoimpl.UnknownFields - - Country *Country `protobuf:"bytes,1,opt,name=country,proto3" json:"country,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CountryResponse) Reset() { @@ -10232,11 +10117,10 @@ func (x *CountryResponse) GetCountry() *Country { } type ListRegistrationCountriesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListRegistrationCountriesRequest) Reset() { @@ -10277,11 +10161,10 @@ func (x *ListRegistrationCountriesRequest) GetMeta() *RequestMeta { } type ListRegistrationCountriesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Countries []*Country `protobuf:"bytes,1,rep,name=countries,proto3" json:"countries,omitempty"` unknownFields protoimpl.UnknownFields - - Countries []*Country `protobuf:"bytes,1,rep,name=countries,proto3" json:"countries,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListRegistrationCountriesResponse) Reset() { @@ -10322,13 +10205,12 @@ func (x *ListRegistrationCountriesResponse) GetCountries() []*Country { } type LoginRiskBlockedCountry struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` + Keyword string `protobuf:"bytes,2,opt,name=keyword,proto3" json:"keyword,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,3,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` unknownFields protoimpl.UnknownFields - - CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` - Keyword string `protobuf:"bytes,2,opt,name=keyword,proto3" json:"keyword,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,3,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *LoginRiskBlockedCountry) Reset() { @@ -10383,11 +10265,10 @@ func (x *LoginRiskBlockedCountry) GetUpdatedAtMs() int64 { } type ListLoginRiskBlockedCountriesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListLoginRiskBlockedCountriesRequest) Reset() { @@ -10428,12 +10309,11 @@ func (x *ListLoginRiskBlockedCountriesRequest) GetMeta() *RequestMeta { } type ListLoginRiskBlockedCountriesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Countries []*LoginRiskBlockedCountry `protobuf:"bytes,1,rep,name=countries,proto3" json:"countries,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,2,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` unknownFields protoimpl.UnknownFields - - Countries []*LoginRiskBlockedCountry `protobuf:"bytes,1,rep,name=countries,proto3" json:"countries,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,2,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListLoginRiskBlockedCountriesResponse) Reset() { @@ -10481,12 +10361,11 @@ func (x *ListLoginRiskBlockedCountriesResponse) GetUpdatedAtMs() int64 { } type ListRegionsRequest struct { - state protoimpl.MessageState - 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"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListRegionsRequest) Reset() { @@ -10534,11 +10413,10 @@ func (x *ListRegionsRequest) GetStatus() string { } type ListRegionsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Regions []*Region `protobuf:"bytes,1,rep,name=regions,proto3" json:"regions,omitempty"` unknownFields protoimpl.UnknownFields - - Regions []*Region `protobuf:"bytes,1,rep,name=regions,proto3" json:"regions,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListRegionsResponse) Reset() { @@ -10579,12 +10457,11 @@ func (x *ListRegionsResponse) GetRegions() []*Region { } type GetRegionRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` unknownFields protoimpl.UnknownFields - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetRegionRequest) Reset() { @@ -10633,16 +10510,15 @@ func (x *GetRegionRequest) GetRegionId() int64 { // UpdateRegionRequest 只修改区域展示字段,不修改 countries。 type UpdateRegionRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - 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"` - RegionCode string `protobuf:"bytes,3,opt,name=region_code,json=regionCode,proto3" json:"region_code,omitempty"` - Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` - SortOrder int32 `protobuf:"varint,5,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - OperatorUserId int64 `protobuf:"varint,6,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + 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"` + RegionCode string `protobuf:"bytes,3,opt,name=region_code,json=regionCode,proto3" json:"region_code,omitempty"` + Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` + SortOrder int32 `protobuf:"varint,5,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + OperatorUserId int64 `protobuf:"varint,6,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *UpdateRegionRequest) Reset() { @@ -10718,14 +10594,13 @@ func (x *UpdateRegionRequest) GetOperatorUserId() int64 { } type ReplaceRegionCountriesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - 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"` - Countries []string `protobuf:"bytes,3,rep,name=countries,proto3" json:"countries,omitempty"` - OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + 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"` + Countries []string `protobuf:"bytes,3,rep,name=countries,proto3" json:"countries,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 *ReplaceRegionCountriesRequest) Reset() { @@ -10787,11 +10662,10 @@ func (x *ReplaceRegionCountriesRequest) GetOperatorUserId() int64 { } type RegionResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Region *Region `protobuf:"bytes,1,opt,name=region,proto3" json:"region,omitempty"` unknownFields protoimpl.UnknownFields - - Region *Region `protobuf:"bytes,1,opt,name=region,proto3" json:"region,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RegionResponse) Reset() { @@ -10833,19 +10707,18 @@ func (x *RegionResponse) GetRegion() *Region { // UserIdentity 是 user_id 和当前 active display_user_id 的绑定投影。 type UserIdentity struct { - 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"` - DisplayUserId string `protobuf:"bytes,2,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` - Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` - DefaultDisplayUserId string `protobuf:"bytes,4,opt,name=default_display_user_id,json=defaultDisplayUserId,proto3" json:"default_display_user_id,omitempty"` - DisplayUserIdKind string `protobuf:"bytes,5,opt,name=display_user_id_kind,json=displayUserIdKind,proto3" json:"display_user_id_kind,omitempty"` - DisplayUserIdExpiresAtMs int64 `protobuf:"varint,6,opt,name=display_user_id_expires_at_ms,json=displayUserIdExpiresAtMs,proto3" json:"display_user_id_expires_at_ms,omitempty"` - AppCode string `protobuf:"bytes,7,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - PrettyId string `protobuf:"bytes,8,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_id,omitempty"` - PrettyDisplayUserId string `protobuf:"bytes,9,opt,name=pretty_display_user_id,json=prettyDisplayUserId,proto3" json:"pretty_display_user_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + DisplayUserId string `protobuf:"bytes,2,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + DefaultDisplayUserId string `protobuf:"bytes,4,opt,name=default_display_user_id,json=defaultDisplayUserId,proto3" json:"default_display_user_id,omitempty"` + DisplayUserIdKind string `protobuf:"bytes,5,opt,name=display_user_id_kind,json=displayUserIdKind,proto3" json:"display_user_id_kind,omitempty"` + DisplayUserIdExpiresAtMs int64 `protobuf:"varint,6,opt,name=display_user_id_expires_at_ms,json=displayUserIdExpiresAtMs,proto3" json:"display_user_id_expires_at_ms,omitempty"` + AppCode string `protobuf:"bytes,7,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + PrettyId string `protobuf:"bytes,8,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_id,omitempty"` + PrettyDisplayUserId string `protobuf:"bytes,9,opt,name=pretty_display_user_id,json=prettyDisplayUserId,proto3" json:"pretty_display_user_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *UserIdentity) Reset() { @@ -10943,12 +10816,11 @@ func (x *UserIdentity) GetPrettyDisplayUserId() string { // GetUserIdentityRequest 按 user_id 查询当前短号。 type GetUserIdentityRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetUserIdentityRequest) Reset() { @@ -10997,11 +10869,10 @@ func (x *GetUserIdentityRequest) GetUserId() int64 { // GetUserIdentityResponse 返回当前短号绑定。 type GetUserIdentityResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` unknownFields protoimpl.UnknownFields - - Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetUserIdentityResponse) Reset() { @@ -11043,12 +10914,11 @@ func (x *GetUserIdentityResponse) GetIdentity() *UserIdentity { // ResolveDisplayUserIDRequest 把客户端展示短号解析成系统 user_id。 type ResolveDisplayUserIDRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + DisplayUserId string `protobuf:"bytes,2,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - DisplayUserId string `protobuf:"bytes,2,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ResolveDisplayUserIDRequest) Reset() { @@ -11097,11 +10967,10 @@ func (x *ResolveDisplayUserIDRequest) GetDisplayUserId() string { // ResolveDisplayUserIDResponse 返回 active 短号归属。 type ResolveDisplayUserIDResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` unknownFields protoimpl.UnknownFields - - Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ResolveDisplayUserIDResponse) Reset() { @@ -11143,15 +11012,14 @@ func (x *ResolveDisplayUserIDResponse) GetIdentity() *UserIdentity { // ChangeDisplayUserIDRequest 修改用户短号,必须由 user-service 保证事务一致。 type ChangeDisplayUserIDRequest struct { - 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"` - NewDisplayUserId string `protobuf:"bytes,3,opt,name=new_display_user_id,json=newDisplayUserId,proto3" json:"new_display_user_id,omitempty"` - Reason string `protobuf:"bytes,4,opt,name=reason,proto3" json:"reason,omitempty"` - OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + 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"` + NewDisplayUserId string `protobuf:"bytes,3,opt,name=new_display_user_id,json=newDisplayUserId,proto3" json:"new_display_user_id,omitempty"` + Reason string `protobuf:"bytes,4,opt,name=reason,proto3" json:"reason,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 } func (x *ChangeDisplayUserIDRequest) Reset() { @@ -11221,11 +11089,10 @@ func (x *ChangeDisplayUserIDRequest) GetOperatorUserId() int64 { // ChangeDisplayUserIDResponse 返回修改后的 active 绑定。 type ChangeDisplayUserIDResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` unknownFields protoimpl.UnknownFields - - Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ChangeDisplayUserIDResponse) Reset() { @@ -11267,15 +11134,14 @@ func (x *ChangeDisplayUserIDResponse) GetIdentity() *UserIdentity { // ApplyPrettyDisplayUserIDRequest 申请临时靓号并覆盖当前展示号。 type ApplyPrettyDisplayUserIDRequest struct { - 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"` - PrettyDisplayUserId string `protobuf:"bytes,3,opt,name=pretty_display_user_id,json=prettyDisplayUserId,proto3" json:"pretty_display_user_id,omitempty"` - LeaseDurationMs int64 `protobuf:"varint,4,opt,name=lease_duration_ms,json=leaseDurationMs,proto3" json:"lease_duration_ms,omitempty"` - PaymentReceiptId string `protobuf:"bytes,5,opt,name=payment_receipt_id,json=paymentReceiptId,proto3" json:"payment_receipt_id,omitempty"` + 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"` + PrettyDisplayUserId string `protobuf:"bytes,3,opt,name=pretty_display_user_id,json=prettyDisplayUserId,proto3" json:"pretty_display_user_id,omitempty"` + LeaseDurationMs int64 `protobuf:"varint,4,opt,name=lease_duration_ms,json=leaseDurationMs,proto3" json:"lease_duration_ms,omitempty"` + PaymentReceiptId string `protobuf:"bytes,5,opt,name=payment_receipt_id,json=paymentReceiptId,proto3" json:"payment_receipt_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ApplyPrettyDisplayUserIDRequest) Reset() { @@ -11345,12 +11211,11 @@ func (x *ApplyPrettyDisplayUserIDRequest) GetPaymentReceiptId() string { // ApplyPrettyDisplayUserIDResponse 返回申请成功后的当前展示号和租约。 type ApplyPrettyDisplayUserIDResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + LeaseId string `protobuf:"bytes,2,opt,name=lease_id,json=leaseId,proto3" json:"lease_id,omitempty"` unknownFields protoimpl.UnknownFields - - Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` - LeaseId string `protobuf:"bytes,2,opt,name=lease_id,json=leaseId,proto3" json:"lease_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ApplyPrettyDisplayUserIDResponse) Reset() { @@ -11399,13 +11264,12 @@ func (x *ApplyPrettyDisplayUserIDResponse) GetLeaseId() string { // ExpirePrettyDisplayUserIDRequest 主动触发靓号过期恢复。 type ExpirePrettyDisplayUserIDRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + LeaseId string `protobuf:"bytes,3,opt,name=lease_id,json=leaseId,proto3" json:"lease_id,omitempty"` 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"` - LeaseId string `protobuf:"bytes,3,opt,name=lease_id,json=leaseId,proto3" json:"lease_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ExpirePrettyDisplayUserIDRequest) Reset() { @@ -11461,11 +11325,10 @@ func (x *ExpirePrettyDisplayUserIDRequest) GetLeaseId() string { // ExpirePrettyDisplayUserIDResponse 返回恢复后的默认短号身份。 type ExpirePrettyDisplayUserIDResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` unknownFields protoimpl.UnknownFields - - Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ExpirePrettyDisplayUserIDResponse) Reset() { @@ -11507,24 +11370,23 @@ func (x *ExpirePrettyDisplayUserIDResponse) GetIdentity() *UserIdentity { // PrettyDisplayIDPool 是靓号池等级区间和生成规则配置。 type PrettyDisplayIDPool struct { - 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"` - PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - LevelTrack string `protobuf:"bytes,4,opt,name=level_track,json=levelTrack,proto3" json:"level_track,omitempty"` - MinLevel int32 `protobuf:"varint,5,opt,name=min_level,json=minLevel,proto3" json:"min_level,omitempty"` - MaxLevel int32 `protobuf:"varint,6,opt,name=max_level,json=maxLevel,proto3" json:"max_level,omitempty"` - RuleType string `protobuf:"bytes,7,opt,name=rule_type,json=ruleType,proto3" json:"rule_type,omitempty"` - RuleConfigJson string `protobuf:"bytes,8,opt,name=rule_config_json,json=ruleConfigJson,proto3" json:"rule_config_json,omitempty"` - Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"` - SortOrder int32 `protobuf:"varint,10,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - CreatedByAdminId int64 `protobuf:"varint,11,opt,name=created_by_admin_id,json=createdByAdminId,proto3" json:"created_by_admin_id,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"` + state protoimpl.MessageState `protogen:"open.v1"` + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + LevelTrack string `protobuf:"bytes,4,opt,name=level_track,json=levelTrack,proto3" json:"level_track,omitempty"` + MinLevel int32 `protobuf:"varint,5,opt,name=min_level,json=minLevel,proto3" json:"min_level,omitempty"` + MaxLevel int32 `protobuf:"varint,6,opt,name=max_level,json=maxLevel,proto3" json:"max_level,omitempty"` + RuleType string `protobuf:"bytes,7,opt,name=rule_type,json=ruleType,proto3" json:"rule_type,omitempty"` + RuleConfigJson string `protobuf:"bytes,8,opt,name=rule_config_json,json=ruleConfigJson,proto3" json:"rule_config_json,omitempty"` + Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"` + SortOrder int32 `protobuf:"varint,10,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + CreatedByAdminId int64 `protobuf:"varint,11,opt,name=created_by_admin_id,json=createdByAdminId,proto3" json:"created_by_admin_id,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 *PrettyDisplayIDPool) Reset() { @@ -11657,26 +11519,25 @@ func (x *PrettyDisplayIDPool) GetUpdatedAtMs() int64 { // PrettyDisplayID 是一个可申请或已发放的靓号记录。 type PrettyDisplayID struct { - 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"` - PrettyId string `protobuf:"bytes,2,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_id,omitempty"` - PoolId string `protobuf:"bytes,3,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - Source string `protobuf:"bytes,4,opt,name=source,proto3" json:"source,omitempty"` - DisplayUserId string `protobuf:"bytes,5,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` - Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` - AssignedUserId int64 `protobuf:"varint,7,opt,name=assigned_user_id,json=assignedUserId,proto3" json:"assigned_user_id,omitempty"` - AssignedLeaseId string `protobuf:"bytes,8,opt,name=assigned_lease_id,json=assignedLeaseId,proto3" json:"assigned_lease_id,omitempty"` - AssignedAtMs int64 `protobuf:"varint,9,opt,name=assigned_at_ms,json=assignedAtMs,proto3" json:"assigned_at_ms,omitempty"` - ReleasedAtMs int64 `protobuf:"varint,10,opt,name=released_at_ms,json=releasedAtMs,proto3" json:"released_at_ms,omitempty"` - ReleaseReason string `protobuf:"bytes,11,opt,name=release_reason,json=releaseReason,proto3" json:"release_reason,omitempty"` - GeneratedBatchId string `protobuf:"bytes,12,opt,name=generated_batch_id,json=generatedBatchId,proto3" json:"generated_batch_id,omitempty"` - CreatedByAdminId int64 `protobuf:"varint,13,opt,name=created_by_admin_id,json=createdByAdminId,proto3" json:"created_by_admin_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"` - Pool *PrettyDisplayIDPool `protobuf:"bytes,16,opt,name=pool,proto3" json:"pool,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + PrettyId string `protobuf:"bytes,2,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_id,omitempty"` + PoolId string `protobuf:"bytes,3,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + Source string `protobuf:"bytes,4,opt,name=source,proto3" json:"source,omitempty"` + DisplayUserId string `protobuf:"bytes,5,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` + Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` + AssignedUserId int64 `protobuf:"varint,7,opt,name=assigned_user_id,json=assignedUserId,proto3" json:"assigned_user_id,omitempty"` + AssignedLeaseId string `protobuf:"bytes,8,opt,name=assigned_lease_id,json=assignedLeaseId,proto3" json:"assigned_lease_id,omitempty"` + AssignedAtMs int64 `protobuf:"varint,9,opt,name=assigned_at_ms,json=assignedAtMs,proto3" json:"assigned_at_ms,omitempty"` + ReleasedAtMs int64 `protobuf:"varint,10,opt,name=released_at_ms,json=releasedAtMs,proto3" json:"released_at_ms,omitempty"` + ReleaseReason string `protobuf:"bytes,11,opt,name=release_reason,json=releaseReason,proto3" json:"release_reason,omitempty"` + GeneratedBatchId string `protobuf:"bytes,12,opt,name=generated_batch_id,json=generatedBatchId,proto3" json:"generated_batch_id,omitempty"` + CreatedByAdminId int64 `protobuf:"varint,13,opt,name=created_by_admin_id,json=createdByAdminId,proto3" json:"created_by_admin_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"` + Pool *PrettyDisplayIDPool `protobuf:"bytes,16,opt,name=pool,proto3" json:"pool,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *PrettyDisplayID) Reset() { @@ -11822,23 +11683,22 @@ func (x *PrettyDisplayID) GetPool() *PrettyDisplayIDPool { } type PrettyDisplayIDGenerationBatch struct { - 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"` - BatchId string `protobuf:"bytes,2,opt,name=batch_id,json=batchId,proto3" json:"batch_id,omitempty"` - PoolId string `protobuf:"bytes,3,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - RuleType string `protobuf:"bytes,4,opt,name=rule_type,json=ruleType,proto3" json:"rule_type,omitempty"` - RuleConfigJson string `protobuf:"bytes,5,opt,name=rule_config_json,json=ruleConfigJson,proto3" json:"rule_config_json,omitempty"` - RequestedCount int32 `protobuf:"varint,6,opt,name=requested_count,json=requestedCount,proto3" json:"requested_count,omitempty"` - GeneratedCount int32 `protobuf:"varint,7,opt,name=generated_count,json=generatedCount,proto3" json:"generated_count,omitempty"` - SkippedConflictCount int32 `protobuf:"varint,8,opt,name=skipped_conflict_count,json=skippedConflictCount,proto3" json:"skipped_conflict_count,omitempty"` - Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"` - OperatorAdminId int64 `protobuf:"varint,10,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` - RequestId string `protobuf:"bytes,11,opt,name=request_id,json=requestId,proto3" json:"request_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"` + state protoimpl.MessageState `protogen:"open.v1"` + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + BatchId string `protobuf:"bytes,2,opt,name=batch_id,json=batchId,proto3" json:"batch_id,omitempty"` + PoolId string `protobuf:"bytes,3,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + RuleType string `protobuf:"bytes,4,opt,name=rule_type,json=ruleType,proto3" json:"rule_type,omitempty"` + RuleConfigJson string `protobuf:"bytes,5,opt,name=rule_config_json,json=ruleConfigJson,proto3" json:"rule_config_json,omitempty"` + RequestedCount int32 `protobuf:"varint,6,opt,name=requested_count,json=requestedCount,proto3" json:"requested_count,omitempty"` + GeneratedCount int32 `protobuf:"varint,7,opt,name=generated_count,json=generatedCount,proto3" json:"generated_count,omitempty"` + SkippedConflictCount int32 `protobuf:"varint,8,opt,name=skipped_conflict_count,json=skippedConflictCount,proto3" json:"skipped_conflict_count,omitempty"` + Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"` + OperatorAdminId int64 `protobuf:"varint,10,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + RequestId string `protobuf:"bytes,11,opt,name=request_id,json=requestId,proto3" json:"request_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"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *PrettyDisplayIDGenerationBatch) Reset() { @@ -11963,14 +11823,13 @@ func (x *PrettyDisplayIDGenerationBatch) GetUpdatedAtMs() int64 { } type ListAvailablePrettyDisplayIDsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + 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 - - 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"` - 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"` + sizeCache protoimpl.SizeCache } func (x *ListAvailablePrettyDisplayIDsRequest) Reset() { @@ -12032,12 +11891,11 @@ func (x *ListAvailablePrettyDisplayIDsRequest) GetPageSize() int32 { } type ListAvailablePrettyDisplayIDsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Items []*PrettyDisplayID `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 - - Items []*PrettyDisplayID `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListAvailablePrettyDisplayIDsResponse) Reset() { @@ -12085,13 +11943,12 @@ func (x *ListAvailablePrettyDisplayIDsResponse) GetTotal() int64 { } type ApplyPrettyDisplayIDFromPoolRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + PrettyId string `protobuf:"bytes,3,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_id,omitempty"` 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"` - PrettyId string `protobuf:"bytes,3,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ApplyPrettyDisplayIDFromPoolRequest) Reset() { @@ -12146,13 +12003,12 @@ func (x *ApplyPrettyDisplayIDFromPoolRequest) GetPrettyId() string { } type ApplyPrettyDisplayIDFromPoolResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + PrettyId string `protobuf:"bytes,2,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_id,omitempty"` + LeaseId string `protobuf:"bytes,3,opt,name=lease_id,json=leaseId,proto3" json:"lease_id,omitempty"` unknownFields protoimpl.UnknownFields - - Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` - PrettyId string `protobuf:"bytes,2,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_id,omitempty"` - LeaseId string `protobuf:"bytes,3,opt,name=lease_id,json=leaseId,proto3" json:"lease_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ApplyPrettyDisplayIDFromPoolResponse) Reset() { @@ -12207,15 +12063,14 @@ func (x *ApplyPrettyDisplayIDFromPoolResponse) GetLeaseId() string { } type ListPrettyDisplayIDPoolsRequest struct { - state protoimpl.MessageState - 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"` + LevelTrack string `protobuf:"bytes,3,opt,name=level_track,json=levelTrack,proto3" json:"level_track,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 - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` - LevelTrack string `protobuf:"bytes,3,opt,name=level_track,json=levelTrack,proto3" json:"level_track,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"` + sizeCache protoimpl.SizeCache } func (x *ListPrettyDisplayIDPoolsRequest) Reset() { @@ -12284,12 +12139,11 @@ func (x *ListPrettyDisplayIDPoolsRequest) GetPageSize() int32 { } type ListPrettyDisplayIDPoolsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Items []*PrettyDisplayIDPool `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 - - Items []*PrettyDisplayIDPool `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListPrettyDisplayIDPoolsResponse) Reset() { @@ -12337,20 +12191,19 @@ func (x *ListPrettyDisplayIDPoolsResponse) GetTotal() int64 { } type CreatePrettyDisplayIDPoolRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - LevelTrack string `protobuf:"bytes,3,opt,name=level_track,json=levelTrack,proto3" json:"level_track,omitempty"` - MinLevel int32 `protobuf:"varint,4,opt,name=min_level,json=minLevel,proto3" json:"min_level,omitempty"` - MaxLevel int32 `protobuf:"varint,5,opt,name=max_level,json=maxLevel,proto3" json:"max_level,omitempty"` - RuleType string `protobuf:"bytes,6,opt,name=rule_type,json=ruleType,proto3" json:"rule_type,omitempty"` - RuleConfigJson string `protobuf:"bytes,7,opt,name=rule_config_json,json=ruleConfigJson,proto3" json:"rule_config_json,omitempty"` - Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` - SortOrder int32 `protobuf:"varint,9,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - OperatorAdminId int64 `protobuf:"varint,10,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + LevelTrack string `protobuf:"bytes,3,opt,name=level_track,json=levelTrack,proto3" json:"level_track,omitempty"` + MinLevel int32 `protobuf:"varint,4,opt,name=min_level,json=minLevel,proto3" json:"min_level,omitempty"` + MaxLevel int32 `protobuf:"varint,5,opt,name=max_level,json=maxLevel,proto3" json:"max_level,omitempty"` + RuleType string `protobuf:"bytes,6,opt,name=rule_type,json=ruleType,proto3" json:"rule_type,omitempty"` + RuleConfigJson string `protobuf:"bytes,7,opt,name=rule_config_json,json=ruleConfigJson,proto3" json:"rule_config_json,omitempty"` + Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` + SortOrder int32 `protobuf:"varint,9,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + OperatorAdminId int64 `protobuf:"varint,10,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CreatePrettyDisplayIDPoolRequest) Reset() { @@ -12454,21 +12307,20 @@ func (x *CreatePrettyDisplayIDPoolRequest) GetOperatorAdminId() int64 { } type UpdatePrettyDisplayIDPoolRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - LevelTrack string `protobuf:"bytes,4,opt,name=level_track,json=levelTrack,proto3" json:"level_track,omitempty"` - MinLevel int32 `protobuf:"varint,5,opt,name=min_level,json=minLevel,proto3" json:"min_level,omitempty"` - MaxLevel int32 `protobuf:"varint,6,opt,name=max_level,json=maxLevel,proto3" json:"max_level,omitempty"` - RuleType string `protobuf:"bytes,7,opt,name=rule_type,json=ruleType,proto3" json:"rule_type,omitempty"` - RuleConfigJson string `protobuf:"bytes,8,opt,name=rule_config_json,json=ruleConfigJson,proto3" json:"rule_config_json,omitempty"` - Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"` - SortOrder int32 `protobuf:"varint,10,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - OperatorAdminId int64 `protobuf:"varint,11,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + LevelTrack string `protobuf:"bytes,4,opt,name=level_track,json=levelTrack,proto3" json:"level_track,omitempty"` + MinLevel int32 `protobuf:"varint,5,opt,name=min_level,json=minLevel,proto3" json:"min_level,omitempty"` + MaxLevel int32 `protobuf:"varint,6,opt,name=max_level,json=maxLevel,proto3" json:"max_level,omitempty"` + RuleType string `protobuf:"bytes,7,opt,name=rule_type,json=ruleType,proto3" json:"rule_type,omitempty"` + RuleConfigJson string `protobuf:"bytes,8,opt,name=rule_config_json,json=ruleConfigJson,proto3" json:"rule_config_json,omitempty"` + Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"` + SortOrder int32 `protobuf:"varint,10,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + OperatorAdminId int64 `protobuf:"varint,11,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *UpdatePrettyDisplayIDPoolRequest) Reset() { @@ -12579,11 +12431,10 @@ func (x *UpdatePrettyDisplayIDPoolRequest) GetOperatorAdminId() int64 { } type PrettyDisplayIDPoolResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Pool *PrettyDisplayIDPool `protobuf:"bytes,1,opt,name=pool,proto3" json:"pool,omitempty"` unknownFields protoimpl.UnknownFields - - Pool *PrettyDisplayIDPool `protobuf:"bytes,1,opt,name=pool,proto3" json:"pool,omitempty"` + sizeCache protoimpl.SizeCache } func (x *PrettyDisplayIDPoolResponse) Reset() { @@ -12624,16 +12475,15 @@ func (x *PrettyDisplayIDPoolResponse) GetPool() *PrettyDisplayIDPool { } type GeneratePrettyDisplayIDsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - RuleType string `protobuf:"bytes,3,opt,name=rule_type,json=ruleType,proto3" json:"rule_type,omitempty"` - RuleConfigJson string `protobuf:"bytes,4,opt,name=rule_config_json,json=ruleConfigJson,proto3" json:"rule_config_json,omitempty"` - Count int32 `protobuf:"varint,5,opt,name=count,proto3" json:"count,omitempty"` - OperatorAdminId int64 `protobuf:"varint,6,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + RuleType string `protobuf:"bytes,3,opt,name=rule_type,json=ruleType,proto3" json:"rule_type,omitempty"` + RuleConfigJson string `protobuf:"bytes,4,opt,name=rule_config_json,json=ruleConfigJson,proto3" json:"rule_config_json,omitempty"` + Count int32 `protobuf:"varint,5,opt,name=count,proto3" json:"count,omitempty"` + OperatorAdminId int64 `protobuf:"varint,6,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GeneratePrettyDisplayIDsRequest) Reset() { @@ -12709,11 +12559,10 @@ func (x *GeneratePrettyDisplayIDsRequest) GetOperatorAdminId() int64 { } type GeneratePrettyDisplayIDsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Batch *PrettyDisplayIDGenerationBatch `protobuf:"bytes,1,opt,name=batch,proto3" json:"batch,omitempty"` unknownFields protoimpl.UnknownFields - - Batch *PrettyDisplayIDGenerationBatch `protobuf:"bytes,1,opt,name=batch,proto3" json:"batch,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GeneratePrettyDisplayIDsResponse) Reset() { @@ -12754,18 +12603,17 @@ func (x *GeneratePrettyDisplayIDsResponse) GetBatch() *PrettyDisplayIDGeneration } type ListPrettyDisplayIDsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - Source string `protobuf:"bytes,3,opt,name=source,proto3" json:"source,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"` - AssignedUserId int64 `protobuf:"varint,6,opt,name=assigned_user_id,json=assignedUserId,proto3" json:"assigned_user_id,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"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + PoolId string `protobuf:"bytes,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + Source string `protobuf:"bytes,3,opt,name=source,proto3" json:"source,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"` + AssignedUserId int64 `protobuf:"varint,6,opt,name=assigned_user_id,json=assignedUserId,proto3" json:"assigned_user_id,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 + sizeCache protoimpl.SizeCache } func (x *ListPrettyDisplayIDsRequest) Reset() { @@ -12855,12 +12703,11 @@ func (x *ListPrettyDisplayIDsRequest) GetPageSize() int32 { } type ListPrettyDisplayIDsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Items []*PrettyDisplayID `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 - - Items []*PrettyDisplayID `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListPrettyDisplayIDsResponse) Reset() { @@ -12908,15 +12755,14 @@ func (x *ListPrettyDisplayIDsResponse) GetTotal() int64 { } type SetPrettyDisplayIDStatusRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - PrettyId string `protobuf:"bytes,2,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_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"` - Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + PrettyId string `protobuf:"bytes,2,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_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"` + Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SetPrettyDisplayIDStatusRequest) Reset() { @@ -12985,14 +12831,13 @@ func (x *SetPrettyDisplayIDStatusRequest) GetReason() string { } type RecyclePrettyDisplayIDRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - PrettyId string `protobuf:"bytes,2,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_id,omitempty"` - Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"` - OperatorAdminId int64 `protobuf:"varint,4,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + PrettyId string `protobuf:"bytes,2,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_id,omitempty"` + Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,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 *RecyclePrettyDisplayIDRequest) Reset() { @@ -13054,11 +12899,10 @@ func (x *RecyclePrettyDisplayIDRequest) GetOperatorAdminId() int64 { } type PrettyDisplayIDResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Item *PrettyDisplayID `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` unknownFields protoimpl.UnknownFields - - Item *PrettyDisplayID `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` + sizeCache protoimpl.SizeCache } func (x *PrettyDisplayIDResponse) Reset() { @@ -13099,16 +12943,15 @@ func (x *PrettyDisplayIDResponse) GetItem() *PrettyDisplayID { } type AdminGrantPrettyDisplayIDRequest struct { - 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"` - DisplayUserId string `protobuf:"bytes,3,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` - DurationMs int64 `protobuf:"varint,4,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` - Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` - OperatorAdminId int64 `protobuf:"varint,6,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + 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"` + DisplayUserId string `protobuf:"bytes,3,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` + DurationMs int64 `protobuf:"varint,4,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` + Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` + OperatorAdminId int64 `protobuf:"varint,6,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminGrantPrettyDisplayIDRequest) Reset() { @@ -13184,13 +13027,12 @@ func (x *AdminGrantPrettyDisplayIDRequest) GetOperatorAdminId() int64 { } type AdminGrantPrettyDisplayIDResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + PrettyId string `protobuf:"bytes,2,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_id,omitempty"` + LeaseId string `protobuf:"bytes,3,opt,name=lease_id,json=leaseId,proto3" json:"lease_id,omitempty"` unknownFields protoimpl.UnknownFields - - Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` - PrettyId string `protobuf:"bytes,2,opt,name=pretty_id,json=prettyId,proto3" json:"pretty_id,omitempty"` - LeaseId string `protobuf:"bytes,3,opt,name=lease_id,json=leaseId,proto3" json:"lease_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AdminGrantPrettyDisplayIDResponse) Reset() { @@ -13244,18 +13086,190 @@ func (x *AdminGrantPrettyDisplayIDResponse) GetLeaseId() string { return "" } +// CPFormationGiftFeedItem 是组 CP 成立时所用礼物超过固定门槛的页面展示快照。 +type CPFormationGiftFeedItem struct { + state protoimpl.MessageState `protogen:"open.v1"` + FormationId string `protobuf:"bytes,1,opt,name=formation_id,json=formationId,proto3" json:"formation_id,omitempty"` + GiftCoinValue int64 `protobuf:"varint,2,opt,name=gift_coin_value,json=giftCoinValue,proto3" json:"gift_coin_value,omitempty"` + Requester *CPUserProfile `protobuf:"bytes,3,opt,name=requester,proto3" json:"requester,omitempty"` + Target *CPUserProfile `protobuf:"bytes,4,opt,name=target,proto3" json:"target,omitempty"` + FormedAtMs int64 `protobuf:"varint,5,opt,name=formed_at_ms,json=formedAtMs,proto3" json:"formed_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CPFormationGiftFeedItem) Reset() { + *x = CPFormationGiftFeedItem{} + mi := &file_proto_user_v1_user_proto_msgTypes[177] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CPFormationGiftFeedItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CPFormationGiftFeedItem) ProtoMessage() {} + +func (x *CPFormationGiftFeedItem) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_user_proto_msgTypes[177] + 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 CPFormationGiftFeedItem.ProtoReflect.Descriptor instead. +func (*CPFormationGiftFeedItem) Descriptor() ([]byte, []int) { + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{177} +} + +func (x *CPFormationGiftFeedItem) GetFormationId() string { + if x != nil { + return x.FormationId + } + return "" +} + +func (x *CPFormationGiftFeedItem) GetGiftCoinValue() int64 { + if x != nil { + return x.GiftCoinValue + } + return 0 +} + +func (x *CPFormationGiftFeedItem) GetRequester() *CPUserProfile { + if x != nil { + return x.Requester + } + return nil +} + +func (x *CPFormationGiftFeedItem) GetTarget() *CPUserProfile { + if x != nil { + return x.Target + } + return nil +} + +func (x *CPFormationGiftFeedItem) GetFormedAtMs() int64 { + if x != nil { + return x.FormedAtMs + } + return 0 +} + +type ListCPFormationGiftFeedRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Limit int32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListCPFormationGiftFeedRequest) Reset() { + *x = ListCPFormationGiftFeedRequest{} + mi := &file_proto_user_v1_user_proto_msgTypes[178] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListCPFormationGiftFeedRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListCPFormationGiftFeedRequest) ProtoMessage() {} + +func (x *ListCPFormationGiftFeedRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_user_proto_msgTypes[178] + 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 ListCPFormationGiftFeedRequest.ProtoReflect.Descriptor instead. +func (*ListCPFormationGiftFeedRequest) Descriptor() ([]byte, []int) { + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{178} +} + +func (x *ListCPFormationGiftFeedRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *ListCPFormationGiftFeedRequest) GetLimit() int32 { + if x != nil { + return x.Limit + } + return 0 +} + +type ListCPFormationGiftFeedResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Items []*CPFormationGiftFeedItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListCPFormationGiftFeedResponse) Reset() { + *x = ListCPFormationGiftFeedResponse{} + mi := &file_proto_user_v1_user_proto_msgTypes[179] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListCPFormationGiftFeedResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListCPFormationGiftFeedResponse) ProtoMessage() {} + +func (x *ListCPFormationGiftFeedResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_user_proto_msgTypes[179] + 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 ListCPFormationGiftFeedResponse.ProtoReflect.Descriptor instead. +func (*ListCPFormationGiftFeedResponse) Descriptor() ([]byte, []int) { + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{179} +} + +func (x *ListCPFormationGiftFeedResponse) GetItems() []*CPFormationGiftFeedItem { + if x != nil { + return x.Items + } + return nil +} + // ListAppsRequest 由内部调度器读取启用租户;不接受租户过滤,避免后台任务再次退化成单 App。 type ListAppsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListAppsRequest) Reset() { *x = ListAppsRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[177] + mi := &file_proto_user_v1_user_proto_msgTypes[180] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13267,7 +13281,7 @@ func (x *ListAppsRequest) String() string { func (*ListAppsRequest) ProtoMessage() {} func (x *ListAppsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[177] + mi := &file_proto_user_v1_user_proto_msgTypes[180] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13280,7 +13294,7 @@ func (x *ListAppsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAppsRequest.ProtoReflect.Descriptor instead. func (*ListAppsRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{177} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{180} } func (x *ListAppsRequest) GetMeta() *RequestMeta { @@ -13291,16 +13305,15 @@ func (x *ListAppsRequest) GetMeta() *RequestMeta { } type ListAppsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Apps []*App `protobuf:"bytes,1,rep,name=apps,proto3" json:"apps,omitempty"` unknownFields protoimpl.UnknownFields - - Apps []*App `protobuf:"bytes,1,rep,name=apps,proto3" json:"apps,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListAppsResponse) Reset() { *x = ListAppsResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[178] + mi := &file_proto_user_v1_user_proto_msgTypes[181] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13312,7 +13325,7 @@ func (x *ListAppsResponse) String() string { func (*ListAppsResponse) ProtoMessage() {} func (x *ListAppsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[178] + mi := &file_proto_user_v1_user_proto_msgTypes[181] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13325,7 +13338,7 @@ func (x *ListAppsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAppsResponse.ProtoReflect.Descriptor instead. func (*ListAppsResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{178} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{181} } func (x *ListAppsResponse) GetApps() []*App { @@ -13338,17 +13351,16 @@ func (x *ListAppsResponse) GetApps() []*App { // ResolveAdminUserIdentifierRequest 是后台精确查人的内部契约。与客户端展示号解析不同, // user_identifier 可以是永久默认短号、当前有效展示号或系统长 user_id。 type ResolveAdminUserIdentifierRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - UserIdentifier string `protobuf:"bytes,2,opt,name=user_identifier,json=userIdentifier,proto3" json:"user_identifier,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + UserIdentifier string `protobuf:"bytes,2,opt,name=user_identifier,json=userIdentifier,proto3" json:"user_identifier,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ResolveAdminUserIdentifierRequest) Reset() { *x = ResolveAdminUserIdentifierRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[179] + mi := &file_proto_user_v1_user_proto_msgTypes[182] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13360,7 +13372,7 @@ func (x *ResolveAdminUserIdentifierRequest) String() string { func (*ResolveAdminUserIdentifierRequest) ProtoMessage() {} func (x *ResolveAdminUserIdentifierRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[179] + mi := &file_proto_user_v1_user_proto_msgTypes[182] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13373,7 +13385,7 @@ func (x *ResolveAdminUserIdentifierRequest) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveAdminUserIdentifierRequest.ProtoReflect.Descriptor instead. func (*ResolveAdminUserIdentifierRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{179} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{182} } func (x *ResolveAdminUserIdentifierRequest) GetMeta() *RequestMeta { @@ -13392,16 +13404,15 @@ func (x *ResolveAdminUserIdentifierRequest) GetUserIdentifier() string { // ResolveAdminUserIdentifierResponse 返回匹配用户的当前有效身份投影。 type ResolveAdminUserIdentifierResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` unknownFields protoimpl.UnknownFields - - Identity *UserIdentity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ResolveAdminUserIdentifierResponse) Reset() { *x = ResolveAdminUserIdentifierResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[180] + mi := &file_proto_user_v1_user_proto_msgTypes[183] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13413,7 +13424,7 @@ func (x *ResolveAdminUserIdentifierResponse) String() string { func (*ResolveAdminUserIdentifierResponse) ProtoMessage() {} func (x *ResolveAdminUserIdentifierResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[180] + mi := &file_proto_user_v1_user_proto_msgTypes[183] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13426,7 +13437,7 @@ func (x *ResolveAdminUserIdentifierResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ResolveAdminUserIdentifierResponse.ProtoReflect.Descriptor instead. func (*ResolveAdminUserIdentifierResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{180} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{183} } func (x *ResolveAdminUserIdentifierResponse) GetIdentity() *UserIdentity { @@ -13438,2879 +13449,1256 @@ func (x *ResolveAdminUserIdentifierResponse) GetIdentity() *UserIdentity { var File_proto_user_v1_user_proto protoreflect.FileDescriptor -var file_proto_user_v1_user_proto_rawDesc = []byte{ - 0x0a, 0x18, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x22, 0xe0, 0x04, 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, 0x16, 0x0a, 0x06, 0x63, 0x61, 0x6c, 0x6c, - 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, - 0x12, 0x26, 0x0a, 0x0f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x6e, 0x6f, 0x64, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x67, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x0a, 0x73, 0x65, 0x6e, 0x74, - 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x73, 0x65, - 0x6e, 0x74, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, - 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, - 0x22, 0x0a, 0x0d, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x62, 0x79, 0x5f, 0x69, 0x70, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x42, - 0x79, 0x49, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, - 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, - 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, - 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, - 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, - 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x4e, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x2f, 0x0a, 0x13, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x18, - 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x6e, - 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x73, 0x5f, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, - 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x6d, 0x65, 0x69, - 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x6d, 0x65, 0x69, 0x22, 0xf1, 0x01, 0x0a, - 0x03, 0x41, 0x70, 0x70, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x70, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x61, 0x70, 0x70, 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, 0x61, 0x70, 0x70, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 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, - 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, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x07, 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, 0x08, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, - 0x22, 0x9d, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x41, 0x70, 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, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, - 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, - 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, - 0x74, 0x66, 0x6f, 0x72, 0x6d, 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, 0x3a, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x41, 0x70, 0x70, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x03, 0x61, 0x70, 0x70, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x03, 0x61, 0x70, 0x70, 0x22, 0x8b, 0x0a, 0x0a, - 0x04, 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, 0x31, - 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 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, 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, 0x12, 0x26, 0x0a, 0x0f, 0x64, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x35, 0x0a, 0x17, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x64, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x14, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x44, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x64, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x5f, 0x6b, 0x69, 0x6e, 0x64, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, - 0x73, 0x65, 0x72, 0x49, 0x64, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x3f, 0x0a, 0x1d, 0x64, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x5f, 0x65, 0x78, 0x70, - 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x18, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x45, - 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, - 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, - 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x18, - 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, - 0x61, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, - 0x12, 0x14, 0x0a, 0x05, 0x62, 0x69, 0x72, 0x74, 0x68, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x62, 0x69, 0x72, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, - 0x67, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, - 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x64, - 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x49, - 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, - 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x11, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x12, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, - 0x64, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, - 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x67, 0x69, 0x6f, - 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x10, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, - 0x65, 0x64, 0x12, 0x35, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x16, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x14, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x6e, 0x62, - 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x17, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x6f, 0x5f, 0x6e, 0x75, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x73, 0x6f, - 0x4e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x68, 0x6f, 0x6e, 0x65, - 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x19, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, - 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, - 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x19, - 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x69, 0x6e, 0x76, - 0x69, 0x74, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, - 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x52, 0x06, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, - 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x1d, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x49, 0x64, 0x12, 0x33, 0x0a, - 0x16, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x70, - 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x62, 0x67, - 0x5f, 0x69, 0x6d, 0x67, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x42, 0x67, 0x49, 0x6d, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x63, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3d, 0x0a, 0x1b, 0x77, - 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x75, 0x73, 0x64, 0x74, 0x5f, 0x74, 0x72, 0x63, - 0x32, 0x30, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x21, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x18, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x55, 0x73, 0x64, 0x74, 0x54, 0x72, - 0x63, 0x32, 0x30, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xed, 0x01, 0x0a, 0x0e, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x12, 0x24, 0x0a, - 0x0e, 0x6d, 0x79, 0x5f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x79, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x43, - 0x6f, 0x64, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x5f, 0x65, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x6e, 0x76, - 0x69, 0x74, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0b, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, - 0x12, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3d, 0x0a, 0x1b, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x5f, 0x74, 0x68, 0x72, 0x65, - 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x18, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x68, 0x72, - 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x22, 0x6e, 0x0a, 0x0d, 0x49, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x43, 0x6f, - 0x64, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x76, - 0x69, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xaa, 0x03, 0x0a, 0x11, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x05, 0x66, 0x6f, 0x75, 0x6e, 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, 0x26, 0x0a, 0x0f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x76, 0x69, - 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x69, 0x6e, 0x76, - 0x69, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x43, 0x6f, - 0x64, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, - 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x74, - 0x4d, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x69, 0x74, 0x79, 0x5f, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x47, 0x0a, 0x20, 0x61, - 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 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, 0x1d, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, - 0x65, 0x64, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x41, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 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, 0x09, 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, 0x1e, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0x75, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x49, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 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, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, - 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x26, 0x0a, 0x0f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, - 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0d, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x62, - 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, - 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0xad, 0x02, 0x0a, 0x14, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x69, 0x63, 0x4c, 0x69, - 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 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, 0x28, 0x0a, 0x10, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x6f, 0x63, 0x63, - 0x75, 0x70, 0x69, 0x65, 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, - 0x73, 0x65, 0x61, 0x74, 0x4f, 0x63, 0x63, 0x75, 0x70, 0x69, 0x65, 0x64, 0x4d, 0x73, 0x12, 0x22, - 0x0a, 0x0d, 0x6d, 0x69, 0x63, 0x5f, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6d, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6d, 0x69, 0x63, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x4d, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0f, 0x66, 0x69, 0x72, 0x73, 0x74, - 0x5f, 0x6d, 0x69, 0x63, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0c, 0x66, 0x69, 0x72, 0x73, 0x74, 0x4d, 0x69, 0x63, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x23, - 0x0a, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x69, 0x63, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x69, 0x63, 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, 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, 0x69, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x69, 0x63, - 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x5c, 0x0a, - 0x1f, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x69, 0x63, 0x4c, 0x69, 0x66, 0x65, 0x74, - 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x39, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x4d, 0x69, 0x63, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x22, 0xe9, 0x02, 0x0a, 0x10, - 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 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, 0x03, 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, 0x04, 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, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x74, - 0x6c, 0x4d, 0x73, 0x12, 0x3a, 0x0a, 0x1a, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x5f, 0x6d, - 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x4d, 0x61, 0x78, 0x41, 0x67, 0x65, 0x4d, 0x73, 0x12, - 0x40, 0x0a, 0x1d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x73, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x19, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x69, - 0x6e, 0x67, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x41, 0x67, 0x65, 0x4d, - 0x73, 0x12, 0x34, 0x0a, 0x17, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x13, 0x6f, 0x70, 0x65, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4d, - 0x61, 0x78, 0x41, 0x67, 0x65, 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, - 0x22, 0x96, 0x04, 0x0a, 0x09, 0x41, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 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, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x66, - 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x24, - 0x0a, 0x0e, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x63, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x49, - 0x6e, 0x53, 0x65, 0x63, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x69, - 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x35, 0x0a, 0x17, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x11, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x4b, - 0x69, 0x6e, 0x64, 0x12, 0x3f, 0x0a, 0x1d, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, - 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x64, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, - 0x41, 0x74, 0x4d, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, - 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x10, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, - 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x6e, - 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 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, 0x22, 0x59, 0x0a, 0x0e, 0x47, 0x65, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x3a, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, - 0x22, 0xbc, 0x01, 0x0a, 0x19, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x55, 0x73, 0x65, - 0x72, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 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, 0x75, 0x73, 0x65, 0x72, 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, 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, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x73, 0x63, 0x65, 0x6e, 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, 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, - 0x9f, 0x02, 0x0a, 0x16, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x55, 0x73, 0x65, 0x72, - 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 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, 0x26, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x69, - 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, - 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, - 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, - 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, - 0x31, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x19, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 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, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, - 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, - 0x65, 0x22, 0x59, 0x0a, 0x1a, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x55, 0x73, 0x65, - 0x72, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3b, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, - 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, - 0x70, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x22, 0xdf, 0x01, 0x0a, - 0x10, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, - 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, 0x25, 0x0a, 0x0e, 0x76, 0x69, - 0x73, 0x69, 0x74, 0x6f, 0x72, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0d, 0x76, 0x69, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x5f, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x66, 0x6f, 0x6c, 0x6c, - 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x72, - 0x69, 0x65, 0x6e, 0x64, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0c, 0x66, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, - 0x18, 0x05, 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, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x63, - 0x0a, 0x18, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, - 0x61, 0x74, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x52, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x35, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, - 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x22, 0x99, 0x01, 0x0a, 0x19, 0x52, 0x65, 0x63, 0x6f, - 0x72, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x56, 0x69, 0x73, 0x69, 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, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, - 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x26, 0x0a, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x74, 0x6f, 0x72, - 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, - 0x76, 0x69, 0x73, 0x69, 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, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x22, 0x7c, 0x0a, 0x1a, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x56, 0x69, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x65, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x65, 0x64, 0x12, 0x42, 0x0a, - 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x73, 0x52, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, - 0x73, 0x22, 0xb0, 0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x56, 0x69, 0x73, - 0x69, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x76, 0x69, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0d, 0x76, 0x69, 0x73, 0x69, 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, 0x1f, 0x0a, 0x0b, 0x76, 0x69, 0x73, 0x69, 0x74, 0x5f, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x69, 0x73, - 0x69, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2b, 0x0a, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x5f, - 0x76, 0x69, 0x73, 0x69, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x56, 0x69, 0x73, 0x69, 0x74, 0x65, 0x64, - 0x41, 0x74, 0x4d, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x56, 0x69, 0x73, 0x69, 0x74, 0x6f, 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, 0x75, 0x73, 0x65, 0x72, 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, 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, 0x70, 0x0a, - 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x56, 0x69, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x07, - 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x56, 0x69, 0x73, 0x69, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, - 0x52, 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, - 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, - 0x97, 0x01, 0x0a, 0x11, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 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, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, - 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, - 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x28, 0x0a, 0x10, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, - 0x77, 0x65, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x7a, 0x0a, 0x12, 0x46, 0x6f, 0x6c, - 0x6c, 0x6f, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x1c, 0x0a, 0x09, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x09, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x12, 0x46, 0x0a, - 0x0e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, - 0x53, 0x74, 0x61, 0x74, 0x73, 0x22, 0x99, 0x01, 0x0a, 0x13, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, - 0x6f, 0x77, 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, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x28, 0x0a, - 0x10, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, - 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, - 0x77, 0x65, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x22, 0x7c, 0x0a, 0x14, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x6f, 0x6c, - 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x66, 0x6f, - 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x12, 0x46, 0x0a, 0x0e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, - 0x77, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, - 0x52, 0x0d, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x22, - 0x88, 0x01, 0x0a, 0x0c, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, - 0x12, 0x28, 0x0a, 0x10, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x66, 0x6f, 0x6c, 0x6c, - 0x6f, 0x77, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x6f, - 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x55, 0x73, - 0x65, 0x72, 0x49, 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, 0x22, 0xe7, 0x01, 0x0a, 0x14, 0x4c, - 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 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, 0x75, 0x73, 0x65, 0x72, 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, 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, 0x2f, 0x0a, - 0x14, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x63, 0x75, 0x72, - 0x73, 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x24, - 0x0a, 0x0e, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x55, 0x73, - 0x65, 0x72, 0x49, 0x64, 0x22, 0x64, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, - 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, - 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x46, - 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x72, 0x65, 0x63, - 0x6f, 0x72, 0x64, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x96, 0x01, 0x0a, 0x12, 0x41, - 0x70, 0x70, 0x6c, 0x79, 0x46, 0x72, 0x69, 0x65, 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, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, - 0x61, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x22, 0x82, 0x01, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46, 0x72, 0x69, - 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0b, 0x61, - 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x27, 0x0a, 0x0f, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x66, 0x72, 0x69, 0x65, 0x6e, - 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, - 0x79, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x73, 0x22, 0xa6, 0x01, 0x0a, 0x1e, 0x41, 0x63, 0x63, - 0x65, 0x70, 0x74, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 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, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x28, 0x0a, 0x10, 0x61, - 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x72, 0x55, - 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x22, 0x56, 0x0a, 0x1f, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x46, 0x72, 0x69, 0x65, 0x6e, - 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x66, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x63, 0x6f, 0x72, - 0x64, 0x52, 0x06, 0x66, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x22, 0x84, 0x01, 0x0a, 0x13, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x46, 0x72, 0x69, 0x65, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x72, - 0x69, 0x65, 0x6e, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0c, 0x66, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, - 0x22, 0x30, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, - 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, 0x73, 0x0a, 0x0c, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x63, 0x6f, - 0x72, 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, 0x24, 0x0a, 0x0e, 0x66, - 0x72, 0x69, 0x65, 0x6e, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0c, 0x66, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x66, 0x72, 0x69, 0x65, 0x6e, - 0x64, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, - 0x46, 0x72, 0x69, 0x65, 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, 0x75, 0x73, 0x65, 0x72, 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, 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, 0x2f, 0x0a, 0x14, 0x63, 0x75, 0x72, 0x73, - 0x6f, 0x72, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x63, 0x75, 0x72, - 0x73, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, - 0x62, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x52, 0x65, - 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x14, 0x0a, - 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x22, 0xc5, 0x01, 0x0a, 0x11, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x41, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x16, 0x0a, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, - 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 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, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xb7, 0x01, 0x0a, 0x1d, - 0x4c, 0x69, 0x73, 0x74, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 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, 0x7c, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x72, 0x69, - 0x65, 0x6e, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0c, 0x61, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x72, - 0x69, 0x65, 0x6e, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0c, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 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, 0x84, 0x01, 0x0a, 0x0d, 0x43, 0x50, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 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, 0x26, - 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, - 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x22, 0x84, 0x02, 0x0a, 0x0e, 0x43, - 0x50, 0x47, 0x69, 0x66, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 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, 0x22, 0x0a, 0x0d, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x63, 0x6f, 0x6e, - 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x67, 0x69, 0x66, 0x74, - 0x49, 0x63, 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x66, 0x74, 0x5f, - 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x10, 0x67, 0x69, 0x66, 0x74, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x55, 0x72, 0x6c, 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, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x06, 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, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x10, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x49, - 0x64, 0x22, 0xe7, 0x03, 0x0a, 0x0d, 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x70, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 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, 0x3a, 0x0a, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x50, 0x55, 0x73, 0x65, - 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x65, 0x72, 0x12, 0x34, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x50, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 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, 0x24, 0x0a, 0x0e, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x6f, 0x6f, 0x6d, - 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x04, 0x67, 0x69, 0x66, 0x74, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x50, 0x47, 0x69, 0x66, 0x74, 0x53, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x67, 0x69, 0x66, 0x74, 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, 0x22, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, - 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x69, - 0x72, 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x64, 0x65, 0x63, 0x69, 0x64, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, - 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xad, 0x05, 0x0a, 0x0e, - 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x12, 0x27, - 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 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, 0x2c, 0x0a, 0x02, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x50, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x02, - 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x74, 0x6e, 0x65, 0x72, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x50, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x52, 0x07, 0x70, 0x61, 0x72, 0x74, 0x6e, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, - 0x74, 0x69, 0x6d, 0x61, 0x63, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x74, 0x69, 0x6d, 0x61, 0x63, 0x79, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x20, 0x0a, 0x0c, 0x66, 0x6f, 0x72, 0x6d, 0x65, - 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x66, - 0x6f, 0x72, 0x6d, 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, 0x36, 0x0a, - 0x17, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x74, - 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x68, 0x72, 0x65, - 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x6c, 0x65, - 0x76, 0x65, 0x6c, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x0c, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x12, 0x6e, 0x65, 0x78, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x68, - 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x31, 0x0a, 0x15, 0x6e, 0x65, 0x65, 0x64, 0x65, - 0x64, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, - 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x46, 0x6f, - 0x72, 0x4e, 0x65, 0x78, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x34, 0x0a, 0x16, 0x6c, 0x65, - 0x76, 0x65, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x70, 0x65, 0x72, - 0x63, 0x65, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x6c, 0x65, 0x76, 0x65, - 0x6c, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, - 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x0f, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x2c, 0x0a, - 0x12, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x75, 0x70, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x6f, - 0x69, 0x6e, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x62, 0x72, 0x65, 0x61, 0x6b, - 0x75, 0x70, 0x43, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x65, - 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x09, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x4a, 0x04, 0x08, 0x08, 0x10, - 0x09, 0x52, 0x08, 0x65, 0x71, 0x75, 0x69, 0x70, 0x70, 0x65, 0x64, 0x22, 0xf9, 0x01, 0x0a, 0x15, - 0x43, 0x50, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 0x46, 0x72, 0x61, 0x6d, 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, 0x22, 0xd9, 0x01, 0x0a, 0x19, 0x43, 0x50, 0x49, 0x6e, - 0x74, 0x69, 0x6d, 0x61, 0x63, 0x79, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, - 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, 0x26, - 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, - 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x47, 0x0a, 0x0c, 0x61, 0x76, - 0x61, 0x74, 0x61, 0x72, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x50, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6e, - 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x0b, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x46, 0x72, - 0x61, 0x6d, 0x65, 0x22, 0x82, 0x03, 0x0a, 0x19, 0x43, 0x50, 0x49, 0x6e, 0x74, 0x69, 0x6d, 0x61, - 0x63, 0x79, 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, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, 0x12, 0x23, - 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x69, 0x6d, 0x61, 0x63, 0x79, 0x5f, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x74, - 0x69, 0x6d, 0x61, 0x63, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, - 0x76, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, - 0x12, 0x3f, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x50, 0x49, 0x6e, 0x74, 0x69, 0x6d, 0x61, 0x63, 0x79, 0x4c, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, - 0x41, 0x12, 0x3f, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x50, 0x49, 0x6e, 0x74, 0x69, 0x6d, 0x61, 0x63, 0x79, 0x4c, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, - 0x72, 0x42, 0x12, 0x20, 0x0a, 0x0c, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, - 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x66, 0x6f, 0x72, 0x6d, 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, 0x22, 0xab, 0x03, 0x0a, 0x11, 0x43, 0x50, 0x57, - 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, - 0x0a, 0x04, 0x72, 0x61, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x72, 0x61, - 0x6e, 0x6b, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, - 0x69, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x50, 0x49, 0x6e, 0x74, 0x69, 0x6d, 0x61, 0x63, - 0x79, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x55, 0x73, 0x65, 0x72, - 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x41, 0x12, 0x3f, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x62, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x50, 0x49, 0x6e, 0x74, 0x69, 0x6d, 0x61, - 0x63, 0x79, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x42, 0x12, 0x20, 0x0a, 0x0c, 0x66, 0x6f, 0x72, 0x6d, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, - 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x2b, - 0x0a, 0x12, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x64, 0x5f, 0x61, - 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x66, 0x69, 0x72, 0x73, - 0x74, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x29, 0x0a, 0x11, 0x6c, - 0x61, 0x73, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x63, 0x6f, 0x72, - 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xbd, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x45, 0x6e, 0x74, 0x72, 0x69, - 0x65, 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, - 0x75, 0x73, 0x65, 0x72, 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, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, - 0x0a, 0x08, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4d, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x65, 0x6e, 0x64, - 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x65, 0x6e, 0x64, 0x4d, 0x73, - 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x83, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x45, 0x6e, 0x74, 0x72, 0x69, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x65, 0x6e, - 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x50, 0x57, 0x65, - 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, - 0x6e, 0x74, 0x72, 0x69, 0x65, 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, 0xcb, 0x01, 0x0a, - 0x19, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 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, 0x9a, 0x01, 0x0a, 0x1a, 0x4c, - 0x69, 0x73, 0x74, 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0c, 0x61, 0x70, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x61, - 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 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, 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, 0x8c, 0x01, 0x0a, 0x1a, 0x41, 0x63, 0x63, 0x65, - 0x70, 0x74, 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 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, 0x75, 0x73, 0x65, - 0x72, 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, 0x12, - 0x25, 0x0a, 0x0e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xa0, 0x01, 0x0a, 0x1b, 0x41, 0x63, 0x63, 0x65, 0x70, - 0x74, 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x50, 0x41, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x50, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0c, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x22, 0xa4, 0x01, 0x0a, 0x1a, 0x52, 0x65, - 0x6a, 0x65, 0x63, 0x74, 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 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, 0x75, - 0x73, 0x65, 0x72, 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, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, - 0x22, 0x5d, 0x0a, 0x1b, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3e, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0xbb, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 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, 0x9a, 0x01, - 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x68, 0x69, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, - 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x68, 0x69, 0x70, 0x52, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, - 0x70, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x52, 0x1a, - 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x5f, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0xa8, 0x01, 0x0a, 0x20, 0x4c, - 0x69, 0x73, 0x74, 0x43, 0x50, 0x49, 0x6e, 0x74, 0x69, 0x6d, 0x61, 0x63, 0x79, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x79, 0x70, 0x65, 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, 0xd0, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, - 0x49, 0x6e, 0x74, 0x69, 0x6d, 0x61, 0x63, 0x79, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, - 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x05, 0x69, - 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x50, 0x49, 0x6e, 0x74, - 0x69, 0x6d, 0x61, 0x63, 0x79, 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, 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, 0xb4, 0x01, 0x0a, 0x21, 0x50, 0x72, 0x65, - 0x70, 0x61, 0x72, 0x65, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, - 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x22, - 0xae, 0x02, 0x0a, 0x22, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x72, 0x65, 0x61, 0x6b, - 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x50, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0c, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 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, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x2c, 0x0a, 0x12, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x75, 0x70, 0x5f, 0x63, 0x6f, 0x73, 0x74, - 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x62, 0x72, - 0x65, 0x61, 0x6b, 0x75, 0x70, 0x43, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x69, 0x6e, 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, 0x05, 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, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, - 0x63, 0x6f, 0x69, 0x6e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, - 0x22, 0xc0, 0x02, 0x0a, 0x21, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x42, 0x72, 0x65, 0x61, - 0x6b, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 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, 0x75, 0x73, 0x65, - 0x72, 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, 0x12, - 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 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, 0x05, 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, 0x28, 0x0a, 0x10, 0x70, - 0x61, 0x69, 0x64, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x61, 0x69, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x41, - 0x6d, 0x6f, 0x75, 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, 0x07, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x10, 0x63, 0x6f, 0x69, 0x6e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, - 0x74, 0x65, 0x72, 0x22, 0xf7, 0x01, 0x0a, 0x22, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x42, - 0x72, 0x65, 0x61, 0x6b, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, - 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, - 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x12, 0x2c, 0x0a, - 0x12, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x75, 0x70, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x6f, - 0x69, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x62, 0x72, 0x65, 0x61, 0x6b, - 0x75, 0x70, 0x43, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x69, 0x6e, 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, 0x03, 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, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x63, 0x6f, 0x69, - 0x6e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x22, 0xcb, 0x01, - 0x0a, 0x20, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x43, 0x50, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x27, 0x0a, 0x0f, 0x72, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, - 0x69, 0x70, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, - 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, - 0x64, 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, 0x22, 0x5a, 0x0a, 0x21, 0x43, - 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 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, - 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x99, 0x05, 0x0a, 0x0f, 0x52, 0x6f, 0x6f, 0x6d, - 0x47, 0x69, 0x66, 0x74, 0x43, 0x50, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, - 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 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, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 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, 0x03, 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, - 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, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 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, 0x07, 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, - 0x08, 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, 0x09, 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, 0x0a, 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, 0x0b, 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, 0x0c, - 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, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x74, 0x79, 0x70, - 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x69, - 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x70, - 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0f, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x70, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x69, 0x66, 0x74, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x75, - 0x72, 0x6c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x67, 0x69, 0x66, 0x74, 0x49, 0x63, - 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x61, 0x6e, - 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x12, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x10, 0x67, 0x69, 0x66, 0x74, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x55, 0x72, 0x6c, 0x22, 0x85, 0x01, 0x0a, 0x1d, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x52, - 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x43, 0x50, 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, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, - 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x34, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x43, 0x50, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0xbf, 0x01, 0x0a, 0x1e, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x43, - 0x50, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, - 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x12, 0x3e, 0x0a, 0x0b, 0x61, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, - 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0c, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, - 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x22, 0xba, 0x02, - 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x09, - 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x54, 0x79, 0x70, 0x65, 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, 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, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 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, - 0x1d, 0x0a, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x73, 0x18, 0x08, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x72, 0x6c, 0x73, 0x12, 0x16, - 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 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, 0xf9, 0x01, 0x0a, 0x13, 0x53, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 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, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, - 0x74, 0x61, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 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, 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, 0x1f, - 0x0a, 0x0b, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 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, 0x1d, 0x0a, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, - 0x5f, 0x75, 0x72, 0x6c, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6d, 0x61, - 0x67, 0x65, 0x55, 0x72, 0x6c, 0x73, 0x22, 0x49, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, - 0x0a, 0x06, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x06, 0x72, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x22, 0x61, 0x0a, 0x14, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 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, - 0x75, 0x73, 0x65, 0x72, 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, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x03, 0x52, 0x07, 0x75, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x73, 0x22, 0xad, 0x01, 0x0a, 0x15, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, - 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, - 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, - 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, - 0x75, 0x73, 0x65, 0x72, 0x73, 0x1a, 0x4d, 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0x90, 0x03, 0x0a, 0x14, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x55, - 0x73, 0x65, 0x72, 0x42, 0x61, 0x6e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x16, 0x0a, - 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x15, 0x0a, - 0x06, 0x62, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, - 0x61, 0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, - 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, - 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, - 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x3a, 0x0a, 0x0b, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x70, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 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, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x72, 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, 0x28, 0x0a, - 0x10, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, - 0x61, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc5, 0x03, 0x0a, 0x10, 0x55, 0x73, 0x65, 0x72, - 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x27, 0x0a, 0x04, - 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, - 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x69, 0x72, 0x74, 0x68, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x69, 0x72, 0x74, 0x68, 0x12, 0x27, 0x0a, 0x0f, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x18, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x75, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x75, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x14, 0x0a, 0x05, - 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x72, 0x6f, 0x6c, - 0x65, 0x73, 0x12, 0x35, 0x0a, 0x03, 0x62, 0x61, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x55, 0x73, 0x65, 0x72, 0x42, 0x61, 0x6e, 0x53, 0x75, 0x6d, - 0x6d, 0x61, 0x72, 0x79, 0x52, 0x03, 0x62, 0x61, 0x6e, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x61, 0x73, - 0x74, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x31, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, - 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x4f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x6c, 0x61, - 0x73, 0x74, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x4f, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x2f, - 0x0a, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6c, 0x61, - 0x73, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x74, 0x4d, 0x73, 0x22, - 0x6d, 0x0a, 0x20, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x03, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0xdd, - 0x01, 0x0a, 0x21, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, - 0x1a, 0x5c, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x35, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x86, - 0x01, 0x0a, 0x20, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 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, 0x75, 0x73, 0x65, 0x72, 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, 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, 0x87, 0x02, 0x0a, 0x21, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, - 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x24, 0x0a, 0x0e, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x65, - 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, - 0x49, 0x6e, 0x53, 0x65, 0x63, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, - 0x64, 0x12, 0x3e, 0x0a, 0x1c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x61, 0x73, - 0x74, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, - 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x4c, 0x61, 0x73, 0x74, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x41, 0x74, 0x4d, - 0x73, 0x22, 0x84, 0x01, 0x0a, 0x0d, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x73, 0x69, 0x63, 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, 0x1a, 0x0a, 0x08, - 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, - 0x61, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, - 0x12, 0x26, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x6a, 0x0a, 0x1d, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x73, 0x69, 0x63, 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, - 0x75, 0x73, 0x65, 0x72, 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, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x03, 0x52, 0x07, 0x75, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x73, 0x22, 0xc8, 0x01, 0x0a, 0x1e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, - 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x73, 0x69, 0x63, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x52, - 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x73, 0x69, 0x63, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x1a, 0x56, 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x73, 0x69, 0x63, - 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, - 0xe1, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 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, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, - 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x63, 0x75, 0x72, - 0x73, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 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, 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, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x72, 0x79, 0x22, 0x73, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x03, 0x52, 0x07, 0x75, 0x73, - 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x63, 0x75, - 0x72, 0x73, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x10, 0x6e, 0x65, 0x78, 0x74, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x55, 0x73, - 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x6f, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x04, 0x64, 0x6f, 0x6e, 0x65, 0x22, 0x86, 0x02, 0x0a, 0x18, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 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, 0x75, 0x73, 0x65, 0x72, - 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, 0x12, 0x1f, - 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, - 0x1b, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x01, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, - 0x62, 0x69, 0x72, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x05, 0x62, - 0x69, 0x72, 0x74, 0x68, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x67, 0x65, 0x6e, 0x64, 0x65, - 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x06, 0x67, 0x65, 0x6e, 0x64, 0x65, - 0x72, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, - 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x42, 0x08, 0x0a, 0x06, - 0x5f, 0x62, 0x69, 0x72, 0x74, 0x68, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x67, 0x65, 0x6e, 0x64, 0x65, - 0x72, 0x22, 0x44, 0x0a, 0x19, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, - 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x93, 0x01, 0x0a, 0x22, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x5f, 0x62, 0x67, 0x5f, 0x69, 0x6d, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x67, 0x49, 0x6d, 0x67, 0x22, 0x4e, 0x0a, - 0x23, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x8a, 0x01, - 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x63, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x48, 0x0a, 0x1d, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x04, 0x75, - 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, - 0x75, 0x73, 0x65, 0x72, 0x22, 0x99, 0x01, 0x0a, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, - 0x73, 0x65, 0x72, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 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, - 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x2c, 0x0a, 0x12, 0x75, 0x73, 0x64, 0x74, 0x5f, 0x74, 0x72, 0x63, 0x32, 0x30, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, - 0x75, 0x73, 0x64, 0x74, 0x54, 0x72, 0x63, 0x32, 0x30, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x22, 0x4c, 0x0a, 0x21, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x57, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x7d, - 0x0a, 0x18, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x72, 0x79, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xcb, 0x01, - 0x0a, 0x1d, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x22, 0x0a, 0x0d, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, - 0x72, 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, 0x22, 0xed, 0x01, 0x0a, 0x19, - 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x04, 0x75, 0x73, 0x65, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, - 0x65, 0x72, 0x12, 0x38, 0x0a, 0x19, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x6e, 0x65, 0x78, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, - 0x6f, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6f, 0x6c, 0x64, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x52, 0x65, 0x67, 0x69, - 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x72, 0x65, - 0x67, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x86, 0x02, 0x0a, 0x14, - 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x31, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 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, 0x04, 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, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, - 0x23, 0x0a, 0x0d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, - 0x54, 0x79, 0x70, 0x65, 0x22, 0xcd, 0x03, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, - 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x15, 0x72, 0x65, 0x76, 0x6f, 0x6b, - 0x65, 0x64, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x69, - 0x6d, 0x5f, 0x6b, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, - 0x69, 0x6d, 0x4b, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x69, 0x6d, 0x5f, 0x6b, - 0x69, 0x63, 0x6b, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x69, 0x6d, 0x4b, 0x69, 0x63, 0x6b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x21, 0x0a, 0x0c, - 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x65, 0x76, 0x69, 0x63, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0b, 0x72, 0x6f, 0x6f, 0x6d, 0x45, 0x76, 0x69, 0x63, 0x74, 0x65, 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, 0x1d, 0x0a, 0x0a, 0x72, 0x74, 0x63, 0x5f, - 0x6b, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x74, - 0x63, 0x4b, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, - 0x65, 0x76, 0x69, 0x63, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x6f, 0x6d, 0x45, 0x76, 0x69, 0x63, 0x74, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x74, 0x63, 0x5f, 0x6b, 0x69, 0x63, 0x6b, 0x5f, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x74, 0x63, 0x4b, 0x69, - 0x63, 0x6b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x30, 0x0a, 0x14, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x12, 0x39, 0x0a, 0x19, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, - 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x22, 0xd0, 0x03, 0x0a, 0x0c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, - 0x65, 0x72, 0x42, 0x61, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x61, 0x6e, 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, 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, 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, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, - 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, - 0x65, 0x6e, 0x74, 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, 0x16, 0x0a, 0x06, 0x72, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, - 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 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, 0x2f, 0x0a, 0x14, 0x72, 0x65, 0x6c, 0x65, 0x61, - 0x73, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x42, - 0x79, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x65, - 0x61, 0x73, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x52, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x5f, 0x6d, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x65, 0x61, - 0x73, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xf2, 0x01, 0x0a, 0x13, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x42, 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, 0x75, 0x73, 0x65, 0x72, 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, 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, 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, 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, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x6d, - 0x69, 0x6e, 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, 0x22, 0x83, 0x01, 0x0a, - 0x14, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x42, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x03, 0x62, 0x61, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x42, 0x61, 0x6e, 0x52, - 0x03, 0x62, 0x61, 0x6e, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x22, 0xc8, 0x01, 0x0a, 0x15, 0x41, 0x64, 0x6d, 0x69, 0x6e, 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, 0x75, 0x73, 0x65, 0x72, 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, - 0x62, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x61, - 0x6e, 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, 0x2a, 0x0a, 0x11, 0x6f, 0x70, 0x65, - 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, - 0x6d, 0x69, 0x6e, 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, 0x22, 0xa8, 0x02, - 0x0a, 0x16, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x03, 0x62, 0x61, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x42, - 0x61, 0x6e, 0x52, 0x03, 0x62, 0x61, 0x6e, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x37, 0x0a, 0x18, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x64, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x62, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x64, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x42, 0x61, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3f, - 0x0a, 0x1c, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x19, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x4d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x27, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, - 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x22, 0xba, 0x03, 0x0a, 0x10, 0x4d, 0x61, 0x6e, - 0x61, 0x67, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x19, 0x0a, - 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x6e, 0x61, - 0x67, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0d, 0x6d, 0x61, 0x6e, 0x61, 0x67, 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, 0x33, 0x0a, 0x16, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x69, - 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x61, - 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x28, 0x0a, 0x10, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x75, - 0x6e, 0x74, 0x69, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x4d, 0x73, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 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, 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, 0xfe, 0x01, 0x0a, 0x1d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x42, 0x6c, 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, 0x75, 0x73, - 0x65, 0x72, 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, 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, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, - 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0d, 0x6d, 0x61, 0x6e, 0x61, 0x67, 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, 0x28, 0x0a, 0x10, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, - 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x4d, 0x73, 0x12, 0x16, - 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x95, 0x01, 0x0a, 0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x05, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, - 0x55, 0x73, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xab, - 0x01, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x55, 0x73, - 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 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, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, - 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, - 0x72, 0x55, 0x73, 0x65, 0x72, 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, - 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, 0x58, 0x0a, 0x1d, - 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, - 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x06, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x22, 0xa6, 0x01, 0x0a, 0x19, 0x55, 0x6e, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 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, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, - 0x6d, 0x65, 0x74, 0x61, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x5f, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6d, - 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 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, 0x22, - 0x91, 0x01, 0x0a, 0x1a, 0x55, 0x6e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, - 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x05, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0xeb, 0x01, 0x0a, 0x19, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, - 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, - 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, - 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x18, - 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, - 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x64, - 0x65, 0x22, 0xbc, 0x02, 0x0a, 0x1a, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, - 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x27, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6d, - 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x2b, 0x0a, - 0x11, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, - 0x64, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x05, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x34, 0x0a, 0x06, 0x69, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, - 0x65, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, - 0x22, 0x87, 0x01, 0x0a, 0x1b, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x49, 0x6e, 0x76, 0x69, 0x74, - 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x72, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x76, - 0x69, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x4d, 0x0a, 0x1c, 0x53, 0x65, - 0x61, 0x72, 0x63, 0x68, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x72, - 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x07, 0x69, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, - 0x52, 0x07, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x72, 0x22, 0x85, 0x01, 0x0a, 0x19, 0x42, 0x69, - 0x6e, 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x72, 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, 0x75, 0x73, - 0x65, 0x72, 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, - 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x64, - 0x65, 0x22, 0x81, 0x01, 0x0a, 0x1a, 0x42, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, - 0x52, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x34, 0x0a, 0x06, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x06, - 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x12, 0x2d, 0x0a, 0x07, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x07, 0x69, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x72, 0x22, 0xac, 0x02, 0x0a, 0x14, 0x42, 0x69, 0x6e, 0x64, 0x50, 0x75, - 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x73, 0x68, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, - 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x61, - 0x70, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x61, 0x70, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, - 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, - 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, - 0x7a, 0x6f, 0x6e, 0x65, 0x22, 0x51, 0x0a, 0x15, 0x42, 0x69, 0x6e, 0x64, 0x50, 0x75, 0x73, 0x68, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, - 0x05, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 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, 0x9d, 0x01, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x50, 0x75, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x1b, 0x0a, 0x09, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x73, 0x68, - 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, - 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x57, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x50, 0x75, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 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, 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, 0xbe, 0x03, 0x0a, 0x07, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x1d, 0x0a, 0x0a, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, - 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, - 0x65, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x64, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x12, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, - 0x61, 0x6d, 0x65, 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, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x5f, 0x6d, 0x73, 0x18, 0x07, 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, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, - 0x6f, 0x5f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x33, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x69, 0x73, 0x6f, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x33, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x6f, - 0x5f, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x69, 0x73, 0x6f, 0x4e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x68, - 0x6f, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6c, 0x61, 0x67, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x66, 0x6c, 0x61, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, - 0x64, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, - 0x65, 0x22, 0x92, 0x02, 0x0a, 0x06, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 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, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x67, - 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 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, 0x16, - 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x72, 0x69, 0x65, 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, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, - 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x07, 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, 0x08, 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, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, - 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x71, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 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, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x1d, - 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x48, - 0x00, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, - 0x08, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x4d, 0x0a, 0x15, 0x4c, 0x69, 0x73, - 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x34, 0x0a, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0x85, 0x03, 0x0a, 0x14, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, - 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x64, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x12, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, - 0x64, 0x65, 0x72, 0x18, 0x05, 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, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, - 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, - 0x0a, 0x0a, 0x69, 0x73, 0x6f, 0x5f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x33, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x69, 0x73, 0x6f, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x33, 0x12, 0x1f, 0x0a, - 0x0b, 0x69, 0x73, 0x6f, 0x5f, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x69, 0x73, 0x6f, 0x4e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x12, 0x2c, - 0x0a, 0x12, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, - 0x63, 0x6f, 0x64, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x68, 0x6f, 0x6e, - 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x66, 0x6c, 0x61, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x6c, 0x61, 0x67, - 0x22, 0x43, 0x0a, 0x0f, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x52, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, - 0x65, 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, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, - 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x59, 0x0a, 0x21, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, - 0x0a, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x22, 0x7a, 0x0a, 0x17, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x69, 0x73, - 0x6b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, - 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 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, 0x56, 0x0a, 0x24, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x69, 0x73, - 0x6b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, - 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, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, - 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x91, 0x01, 0x0a, 0x25, 0x4c, 0x69, 0x73, - 0x74, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x69, 0x73, 0x6b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, - 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x44, 0x0a, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x69, 0x73, 0x6b, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 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, 0x5c, 0x0a, 0x12, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x46, 0x0a, 0x13, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x72, 0x65, 0x67, 0x69, 0x6f, - 0x6e, 0x73, 0x22, 0x5f, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 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, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, - 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x22, 0xe0, 0x01, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, - 0x67, 0x69, 0x6f, 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, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x72, - 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, - 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x67, 0x69, - 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, - 0x65, 0x67, 0x69, 0x6f, 0x6e, 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, 0x1d, 0x0a, - 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x05, 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, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, - 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xb4, 0x01, 0x0a, 0x1d, 0x52, 0x65, 0x70, 0x6c, 0x61, - 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, - 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, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, - 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, - 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, - 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, - 0x69, 0x65, 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, 0x3f, 0x0a, - 0x0e, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x2d, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x22, 0xfd, - 0x02, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 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, 0x26, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 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, 0x35, 0x0a, 0x17, 0x64, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x64, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x2f, 0x0a, 0x14, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x64, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x4b, 0x69, 0x6e, 0x64, - 0x12, 0x3f, 0x0a, 0x1d, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x5f, 0x6d, - 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, - 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x4d, - 0x73, 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, - 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x16, 0x70, 0x72, 0x65, - 0x74, 0x74, 0x79, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x70, 0x72, 0x65, 0x74, 0x74, - 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x61, - 0x0a, 0x16, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 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, 0x75, - 0x73, 0x65, 0x72, 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, 0x52, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x08, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x75, 0x0a, 0x1b, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 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, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, - 0x6d, 0x65, 0x74, 0x61, 0x12, 0x26, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x57, 0x0a, 0x1c, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, - 0x65, 0x72, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x08, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0xd6, 0x01, 0x0a, 0x1a, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x2d, 0x0a, - 0x13, 0x6e, 0x65, 0x77, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6e, 0x65, 0x77, 0x44, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 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, 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, 0x56, - 0x0a, 0x1b, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, - 0x73, 0x65, 0x72, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, - 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0xf9, 0x01, 0x0a, 0x1f, 0x41, 0x70, 0x70, 0x6c, 0x79, - 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, - 0x72, 0x49, 0x44, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x33, 0x0a, 0x16, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, 0x64, 0x69, - 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x13, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x65, 0x61, 0x73, - 0x65, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, - 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x10, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, - 0x49, 0x64, 0x22, 0x76, 0x0a, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, 0x72, 0x65, 0x74, 0x74, - 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, - 0x19, 0x0a, 0x08, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x22, 0x86, 0x01, 0x0a, 0x20, 0x45, - 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x19, 0x0a, 0x08, 0x6c, 0x65, 0x61, 0x73, - 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, 0x65, 0x61, 0x73, - 0x65, 0x49, 0x64, 0x22, 0x5c, 0x0a, 0x21, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, - 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x22, 0xdc, 0x03, 0x0a, 0x13, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 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, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x6b, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x72, 0x61, - 0x63, 0x6b, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6d, 0x69, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, - 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1b, 0x0a, 0x09, - 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x72, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x75, 0x6c, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4a, - 0x73, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x09, 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, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x2d, 0x0a, 0x13, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x42, 0x79, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 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, 0xe0, 0x04, 0x0a, 0x0f, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x49, 0x44, 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, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, - 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, - 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x26, 0x0a, - 0x0f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, - 0x73, 0x65, 0x72, 0x49, 0x64, 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, 0x28, 0x0a, - 0x10, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x61, 0x73, 0x73, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0f, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4c, 0x65, 0x61, 0x73, - 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x61, 0x73, 0x73, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x65, 0x6c, - 0x65, 0x61, 0x73, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, - 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, - 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, - 0x74, 0x65, 0x64, 0x5f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x10, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x42, 0x61, 0x74, - 0x63, 0x68, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x13, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, - 0x62, 0x79, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x10, 0x63, 0x72, 0x65, 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, 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, 0x12, 0x36, 0x0a, 0x04, 0x70, - 0x6f, 0x6f, 0x6c, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x04, 0x70, - 0x6f, 0x6f, 0x6c, 0x22, 0xe9, 0x03, 0x0a, 0x1e, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, - 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 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, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x74, 0x63, 0x68, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, - 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, - 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x75, 0x6c, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x75, - 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x34, - 0x0a, 0x16, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, - 0x63, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, - 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x0a, 0x11, - 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 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, 0x22, - 0xa0, 0x01, 0x0a, 0x24, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, - 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, - 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, 0x75, - 0x73, 0x65, 0x72, 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, 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, 0x73, 0x0a, 0x25, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, - 0x62, 0x6c, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, - 0x49, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x69, - 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x74, 0x74, - 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 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, 0x8b, 0x01, 0x0a, 0x23, 0x41, 0x70, 0x70, 0x6c, - 0x79, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, - 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, 0x65, 0x74, - 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x65, - 0x74, 0x74, 0x79, 0x49, 0x64, 0x22, 0x97, 0x01, 0x0a, 0x24, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, - 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x46, 0x72, - 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, - 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, 0x65, 0x74, 0x74, - 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x65, 0x74, - 0x74, 0x79, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x64, 0x22, - 0xbb, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, - 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 0x6c, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, - 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x6b, 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, 0x72, 0x0a, - 0x20, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x38, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, - 0x50, 0x6f, 0x6f, 0x6c, 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, 0xeb, 0x02, 0x0a, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x74, - 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 0x6c, 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, 0x75, 0x73, 0x65, - 0x72, 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, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x65, - 0x76, 0x65, 0x6c, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x12, 0x1b, 0x0a, 0x09, 0x6d, - 0x69, 0x6e, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, - 0x6d, 0x69, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, - 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6d, 0x61, 0x78, - 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x75, 0x6c, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x75, - 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4a, 0x73, 0x6f, 0x6e, 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, 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, 0x2a, 0x0a, 0x11, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, - 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x22, - 0x84, 0x03, 0x0a, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 0x6c, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x6b, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x72, 0x61, - 0x63, 0x6b, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6d, 0x69, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, - 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1b, 0x0a, 0x09, - 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x72, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x75, 0x6c, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4a, - 0x73, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x09, 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, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x55, 0x0a, 0x1b, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x04, 0x70, 0x6f, 0x6f, 0x6c, 0x22, 0xf3, 0x01, - 0x0a, 0x1f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x75, - 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, - 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x75, 0x6c, 0x65, 0x5f, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x72, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4a, 0x73, 0x6f, - 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x70, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x49, 0x64, 0x22, 0x67, 0x0a, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x50, - 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x05, 0x62, 0x61, 0x74, 0x63, 0x68, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x05, 0x62, 0x61, 0x74, 0x63, 0x68, 0x22, 0x8b, 0x02, 0x0a, - 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x49, 0x44, 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, 0x75, 0x73, 0x65, 0x72, 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, - 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, - 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 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, - 0x28, 0x0a, 0x10, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x61, 0x73, 0x73, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x49, 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, 0x6a, 0x0a, 0x1c, 0x4c, 0x69, - 0x73, 0x74, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, - 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x69, 0x74, - 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 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, 0xca, 0x01, 0x0a, 0x1f, 0x53, 0x65, 0x74, 0x50, 0x72, - 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x53, 0x74, 0x61, - 0x74, 0x75, 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, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, - 0x65, 0x74, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, - 0x72, 0x65, 0x74, 0x74, 0x79, 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, - 0x2a, 0x0a, 0x11, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x6d, 0x69, 0x6e, 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, 0x22, 0xb0, 0x01, 0x0a, 0x1d, 0x52, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x50, - 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 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, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, - 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, - 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, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x4d, 0x0a, 0x17, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x32, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x52, - 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x85, 0x02, 0x0a, 0x20, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, - 0x72, 0x61, 0x6e, 0x74, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x49, 0x44, 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, 0x75, 0x73, 0x65, 0x72, 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, 0x26, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x04, 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, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x94, 0x01, - 0x0a, 0x21, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x50, 0x72, 0x65, 0x74, - 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1b, 0x0a, 0x09, - 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6c, 0x65, 0x61, - 0x73, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, 0x65, 0x61, - 0x73, 0x65, 0x49, 0x64, 0x22, 0x41, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 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, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, - 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x3a, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x41, - 0x70, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x61, - 0x70, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x04, 0x61, - 0x70, 0x70, 0x73, 0x22, 0x7c, 0x0a, 0x21, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x41, 0x64, - 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 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, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, - 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x27, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, - 0x72, 0x22, 0x5d, 0x0a, 0x22, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x2a, 0x73, 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, - 0x0a, 0x17, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x55, - 0x53, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, - 0x45, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, - 0x55, 0x53, 0x5f, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x12, 0x16, 0x0a, - 0x12, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x42, 0x41, 0x4e, - 0x4e, 0x45, 0x44, 0x10, 0x03, 0x32, 0xac, 0x15, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, - 0x12, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x6f, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, - 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x69, 0x0a, 0x12, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x55, 0x73, 0x65, 0x72, - 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x55, - 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x6f, - 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x11, 0x47, - 0x65, 0x74, 0x4d, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, - 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0d, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x73, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, - 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x7e, 0x0a, 0x19, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x2f, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, - 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, - 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x7e, 0x0a, 0x19, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2f, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, - 0x69, 0x6e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, - 0x6d, 0x69, 0x6e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x75, 0x0a, 0x16, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, - 0x61, 0x73, 0x69, 0x63, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, - 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x73, 0x69, 0x63, 0x55, 0x73, 0x65, 0x72, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, - 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x73, 0x69, 0x63, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x49, 0x44, 0x73, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x49, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x17, - 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x69, 0x63, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, - 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, - 0x69, 0x63, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x69, - 0x63, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x27, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x84, - 0x01, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x31, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, - 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2b, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, 0x19, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, - 0x65, 0x72, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x11, 0x43, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x27, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x55, 0x73, - 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x70, 0x0a, 0x16, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x2c, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x57, 0x0a, 0x0c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x42, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x12, - 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x42, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x42, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, - 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x55, - 0x73, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x55, 0x73, 0x65, - 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, - 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x55, 0x73, 0x65, - 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x6e, 0x61, - 0x67, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, - 0x55, 0x73, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x55, 0x6e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x61, 0x6e, - 0x61, 0x67, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, - 0x72, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, - 0x12, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, - 0x69, 0x6e, 0x67, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x62, 0x6f, - 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x53, 0x65, 0x61, 0x72, - 0x63, 0x68, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x72, - 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x52, 0x65, 0x66, - 0x65, 0x72, 0x72, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, - 0x72, 0x63, 0x68, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x42, 0x69, 0x6e, - 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x72, 0x12, - 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x42, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x72, - 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x69, 0x6e, 0x64, 0x49, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc3, 0x08, 0x0a, 0x11, 0x55, 0x73, 0x65, 0x72, 0x53, 0x6f, 0x63, - 0x69, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x52, 0x65, - 0x63, 0x6f, 0x72, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x56, 0x69, 0x73, 0x69, 0x74, - 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x56, 0x69, - 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, - 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x56, 0x69, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x56, 0x69, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x29, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x56, 0x69, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x56, 0x69, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0a, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x55, 0x73, 0x65, - 0x72, 0x12, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, - 0x6f, 0x77, 0x55, 0x73, 0x65, 0x72, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x66, 0x6f, 0x6c, - 0x6c, 0x6f, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x5a, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, - 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, - 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x41, - 0x70, 0x70, 0x6c, 0x79, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, - 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, - 0x70, 0x6c, 0x79, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x78, 0x0a, 0x17, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x46, 0x72, 0x69, 0x65, 0x6e, - 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, - 0x65, 0x70, 0x74, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, - 0x70, 0x74, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x12, 0x22, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x72, 0x69, 0x65, - 0x6e, 0x64, 0x73, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x72, 0x69, 0x65, 0x6e, - 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x16, 0x4c, 0x69, - 0x73, 0x74, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x41, - 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x41, 0x70, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xcc, 0x07, 0x0a, 0x0d, 0x55, - 0x73, 0x65, 0x72, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x69, 0x0a, 0x12, - 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x41, 0x63, 0x63, 0x65, 0x70, - 0x74, 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, - 0x63, 0x63, 0x65, 0x70, 0x74, 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, - 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x43, - 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6a, - 0x65, 0x63, 0x74, 0x43, 0x50, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x50, - 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x52, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x7e, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x49, 0x6e, 0x74, 0x69, 0x6d, - 0x61, 0x63, 0x79, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, 0x2f, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x43, 0x50, 0x49, 0x6e, 0x74, 0x69, 0x6d, 0x61, 0x63, 0x79, 0x4c, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x49, 0x6e, 0x74, 0x69, 0x6d, 0x61, 0x63, 0x79, 0x4c, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x81, 0x01, 0x0a, 0x1a, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x72, 0x65, - 0x61, 0x6b, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, - 0x12, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x43, 0x50, 0x52, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x43, - 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x1a, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, - 0x6d, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x68, 0x69, 0x70, 0x12, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x42, 0x72, 0x65, 0x61, - 0x6b, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x42, 0x72, - 0x65, 0x61, 0x6b, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, - 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, 0x19, 0x43, 0x61, 0x6e, - 0x63, 0x65, 0x6c, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x72, 0x65, - 0x61, 0x6b, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x72, - 0x65, 0x61, 0x6b, 0x43, 0x50, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, - 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x88, 0x02, 0x0a, 0x15, 0x55, 0x73, - 0x65, 0x72, 0x43, 0x50, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x75, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x52, 0x6f, - 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x43, 0x50, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2c, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x43, 0x50, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x43, 0x50, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x17, 0x4c, 0x69, - 0x73, 0x74, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x45, 0x6e, - 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, - 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, - 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xab, 0x05, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x43, 0x72, 0x6f, - 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5c, 0x0a, 0x17, 0x50, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x49, 0x50, 0x52, 0x69, 0x73, 0x6b, 0x42, 0x61, - 0x74, 0x63, 0x68, 0x12, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x19, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, - 0x73, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x61, - 0x74, 0x63, 0x68, 0x12, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x19, 0x43, 0x6f, 0x6d, 0x70, 0x65, 0x6e, - 0x73, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x63, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x1a, 0x43, 0x6f, 0x6d, 0x70, 0x65, 0x6e, - 0x73, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x17, 0x45, 0x78, 0x70, 0x69, 0x72, - 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x73, 0x12, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x13, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x42, 0x61, 0x6e, 0x73, 0x12, 0x1f, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, - 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, - 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x61, 0x0a, 0x1c, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x43, 0x50, 0x49, 0x6e, 0x74, 0x69, - 0x6d, 0x61, 0x63, 0x79, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, - 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x32, 0xd1, 0x01, 0x0a, 0x11, 0x55, 0x73, 0x65, 0x72, 0x44, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5a, 0x0a, 0x0d, 0x42, 0x69, 0x6e, 0x64, - 0x50, 0x75, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x69, 0x6e, 0x64, 0x50, 0x75, - 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, - 0x69, 0x6e, 0x64, 0x50, 0x75, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x75, - 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x75, - 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x75, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xb4, 0x01, 0x0a, 0x12, 0x41, 0x70, 0x70, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, 0x0a, - 0x0a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x41, 0x70, 0x70, 0x12, 0x20, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x4b, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x12, 0x1e, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc7, 0x01, - 0x0a, 0x13, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5a, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x54, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xa2, 0x02, 0x0a, 0x13, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x72, 0x79, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x7e, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2f, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x8a, 0x01, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x69, 0x73, - 0x6b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, - 0x73, 0x12, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x69, 0x73, 0x6b, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x69, 0x6e, - 0x52, 0x69, 0x73, 0x6b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xf1, 0x02, 0x0a, - 0x12, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x09, 0x47, 0x65, 0x74, - 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x16, 0x52, 0x65, 0x70, - 0x6c, 0x61, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, - 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x32, 0xee, 0x07, 0x0a, 0x13, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x25, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x52, 0x65, - 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, - 0x49, 0x44, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, - 0x72, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x1a, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x6c, 0x0a, 0x13, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, - 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x44, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, - 0x73, 0x65, 0x72, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7b, 0x0a, - 0x18, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, - 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, - 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, - 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, - 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8a, 0x01, 0x0a, 0x1d, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, 0x65, 0x74, - 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x73, 0x12, 0x33, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x50, - 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x87, 0x01, 0x0a, 0x1c, 0x41, 0x70, 0x70, 0x6c, - 0x79, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, - 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, 0x72, - 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x46, 0x72, 0x6f, - 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, - 0x6c, 0x79, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, - 0x44, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x7e, 0x0a, 0x19, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, - 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x2f, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, - 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x32, 0xe4, 0x07, 0x0a, 0x1f, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7b, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, - 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 0x6c, - 0x73, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x78, 0x0a, 0x19, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x74, - 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 0x6c, 0x12, - 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, - 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x19, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x50, - 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x74, 0x74, - 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7b, 0x0a, 0x18, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, - 0x74, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, - 0x44, 0x73, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, - 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, - 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x74, 0x74, - 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x73, 0x12, 0x2a, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x74, - 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x18, 0x53, 0x65, 0x74, 0x50, 0x72, 0x65, 0x74, 0x74, - 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x65, 0x74, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x49, 0x44, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x16, 0x52, 0x65, 0x63, 0x79, - 0x63, 0x6c, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, - 0x49, 0x44, 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, 0x19, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x49, 0x44, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x72, 0x61, 0x6e, 0x74, - 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x72, 0x61, 0x6e, - 0x74, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x49, 0x44, - 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, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x75, 0x73, 0x65, 0x72, 0x76, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +const file_proto_user_v1_user_proto_rawDesc = "" + + "\n" + + "\x18proto/user/v1/user.proto\x12\rhyapp.user.v1\"\xe0\x04\n" + + "\vRequestMeta\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x16\n" + + "\x06caller\x18\x02 \x01(\tR\x06caller\x12&\n" + + "\x0fgateway_node_id\x18\x03 \x01(\tR\rgatewayNodeId\x12\x1c\n" + + "\n" + + "sent_at_ms\x18\x04 \x01(\x03R\bsentAtMs\x12\x1b\n" + + "\tdevice_id\x18\x05 \x01(\tR\bdeviceId\x12\x1b\n" + + "\tclient_ip\x18\x06 \x01(\tR\bclientIp\x12\x1d\n" + + "\n" + + "user_agent\x18\a \x01(\tR\tuserAgent\x12\"\n" + + "\rcountry_by_ip\x18\b \x01(\tR\vcountryByIp\x12\x1d\n" + + "\n" + + "session_id\x18\t \x01(\tR\tsessionId\x12\x19\n" + + "\bapp_code\x18\n" + + " \x01(\tR\aappCode\x12\x1a\n" + + "\bplatform\x18\v \x01(\tR\bplatform\x12\x1a\n" + + "\blanguage\x18\f \x01(\tR\blanguage\x12\x1a\n" + + "\btimezone\x18\r \x01(\tR\btimezone\x12\x1f\n" + + "\vapp_version\x18\x0e \x01(\tR\n" + + "appVersion\x12!\n" + + "\fbuild_number\x18\x0f \x01(\tR\vbuildNumber\x12!\n" + + "\fdevice_model\x18\x10 \x01(\tR\vdeviceModel\x12/\n" + + "\x13device_manufacturer\x18\x11 \x01(\tR\x12deviceManufacturer\x12\x1d\n" + + "\n" + + "os_version\x18\x12 \x01(\tR\tosVersion\x12\x12\n" + + "\x04imei\x18\x13 \x01(\tR\x04imei\"\xf1\x01\n" + + "\x03App\x12\x15\n" + + "\x06app_id\x18\x01 \x01(\x03R\x05appId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x19\n" + + "\bapp_name\x18\x03 \x01(\tR\aappName\x12!\n" + + "\fpackage_name\x18\x04 \x01(\tR\vpackageName\x12\x1a\n" + + "\bplatform\x18\x05 \x01(\tR\bplatform\x12\x16\n" + + "\x06status\x18\x06 \x01(\tR\x06status\x12\"\n" + + "\rcreated_at_ms\x18\a \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\b \x01(\x03R\vupdatedAtMs\"\x9d\x01\n" + + "\x11ResolveAppRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12!\n" + + "\fpackage_name\x18\x02 \x01(\tR\vpackageName\x12\x1a\n" + + "\bplatform\x18\x03 \x01(\tR\bplatform\x12\x19\n" + + "\bapp_code\x18\x04 \x01(\tR\aappCode\":\n" + + "\x12ResolveAppResponse\x12$\n" + + "\x03app\x18\x01 \x01(\v2\x12.hyapp.user.v1.AppR\x03app\"\x8b\n" + + "\n" + + "\x04User\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x03R\x06userId\x121\n" + + "\x06status\x18\x02 \x01(\x0e2\x19.hyapp.user.v1.UserStatusR\x06status\x12\"\n" + + "\rcreated_at_ms\x18\x03 \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x04 \x01(\x03R\vupdatedAtMs\x12&\n" + + "\x0fdisplay_user_id\x18\x05 \x01(\tR\rdisplayUserId\x125\n" + + "\x17default_display_user_id\x18\x06 \x01(\tR\x14defaultDisplayUserId\x12/\n" + + "\x14display_user_id_kind\x18\a \x01(\tR\x11displayUserIdKind\x12?\n" + + "\x1ddisplay_user_id_expires_at_ms\x18\b \x01(\x03R\x18displayUserIdExpiresAtMs\x12\x1a\n" + + "\busername\x18\t \x01(\tR\busername\x12\x16\n" + + "\x06gender\x18\n" + + " \x01(\tR\x06gender\x12\x18\n" + + "\acountry\x18\v \x01(\tR\acountry\x12\x16\n" + + "\x06avatar\x18\f \x01(\tR\x06avatar\x12\x14\n" + + "\x05birth\x18\r \x01(\tR\x05birth\x12\x1a\n" + + "\blanguage\x18\x0e \x01(\tR\blanguage\x12\x1d\n" + + "\n" + + "country_id\x18\x0f \x01(\x03R\tcountryId\x12!\n" + + "\fcountry_name\x18\x10 \x01(\tR\vcountryName\x120\n" + + "\x14country_display_name\x18\x11 \x01(\tR\x12countryDisplayName\x12\x1b\n" + + "\tregion_id\x18\x12 \x01(\x03R\bregionId\x12\x1f\n" + + "\vregion_code\x18\x13 \x01(\tR\n" + + "regionCode\x12\x1f\n" + + "\vregion_name\x18\x14 \x01(\tR\n" + + "regionName\x12+\n" + + "\x11profile_completed\x18\x15 \x01(\bR\x10profileCompleted\x125\n" + + "\x17profile_completed_at_ms\x18\x16 \x01(\x03R\x14profileCompletedAtMs\x12+\n" + + "\x11onboarding_status\x18\x17 \x01(\tR\x10onboardingStatus\x12\x1f\n" + + "\viso_numeric\x18\x18 \x01(\tR\n" + + "isoNumeric\x12,\n" + + "\x12phone_country_code\x18\x19 \x01(\tR\x10phoneCountryCode\x12'\n" + + "\x0fcountry_enabled\x18\x1a \x01(\bR\x0ecountryEnabled\x12\x19\n" + + "\bapp_code\x18\x1b \x01(\tR\aappCode\x125\n" + + "\x06invite\x18\x1c \x01(\v2\x1d.hyapp.user.v1.InviteOverviewR\x06invite\x12\x1b\n" + + "\tpretty_id\x18\x1d \x01(\tR\bprettyId\x123\n" + + "\x16pretty_display_user_id\x18\x1e \x01(\tR\x13prettyDisplayUserId\x12$\n" + + "\x0eprofile_bg_img\x18\x1f \x01(\tR\fprofileBgImg\x12!\n" + + "\fcontact_info\x18 \x01(\tR\vcontactInfo\x12=\n" + + "\x1bwithdraw_usdt_trc20_address\x18! \x01(\tR\x18withdrawUsdtTrc20Address\"\xed\x01\n" + + "\x0eInviteOverview\x12$\n" + + "\x0emy_invite_code\x18\x01 \x01(\tR\fmyInviteCode\x12%\n" + + "\x0einvite_enabled\x18\x02 \x01(\bR\rinviteEnabled\x12!\n" + + "\finvite_count\x18\x03 \x01(\x03R\vinviteCount\x12,\n" + + "\x12valid_invite_count\x18\x04 \x01(\x03R\x10validInviteCount\x12=\n" + + "\x1bvalid_invite_threshold_coin\x18\x05 \x01(\x03R\x18validInviteThresholdCoin\"n\n" + + "\rInviteBinding\x12\x14\n" + + "\x05bound\x18\x01 \x01(\bR\x05bound\x12\x1f\n" + + "\vinvite_code\x18\x02 \x01(\tR\n" + + "inviteCode\x12&\n" + + "\x0finviter_user_id\x18\x03 \x01(\x03R\rinviterUserId\"\xaa\x03\n" + + "\x11InviteAttribution\x12\x14\n" + + "\x05found\x18\x01 \x01(\bR\x05found\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12&\n" + + "\x0finvited_user_id\x18\x03 \x01(\x03R\rinvitedUserId\x12&\n" + + "\x0finviter_user_id\x18\x04 \x01(\x03R\rinviterUserId\x12\x1f\n" + + "\vinvite_code\x18\x05 \x01(\tR\n" + + "inviteCode\x12\x1e\n" + + "\vbound_at_ms\x18\x06 \x01(\x03R\tboundAtMs\x12'\n" + + "\x0fvalidity_status\x18\a \x01(\tR\x0evalidityStatus\x12G\n" + + " accumulated_recharge_coin_amount\x18\b \x01(\x03R\x1daccumulatedRechargeCoinAmount\x12A\n" + + "\x1drequired_recharge_coin_amount\x18\t \x01(\x03R\x1arequiredRechargeCoinAmount\x12\x1e\n" + + "\vvalid_at_ms\x18\n" + + " \x01(\x03R\tvalidAtMs\"u\n" + + "\x1bGetInviteAttributionRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12&\n" + + "\x0finvited_user_id\x18\x02 \x01(\x03R\rinvitedUserId\"b\n" + + "\x1cGetInviteAttributionResponse\x12B\n" + + "\vattribution\x18\x01 \x01(\v2 .hyapp.user.v1.InviteAttributionR\vattribution\"\xad\x02\n" + + "\x14UserMicLifetimeStats\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12(\n" + + "\x10seat_occupied_ms\x18\x02 \x01(\x03R\x0eseatOccupiedMs\x12\"\n" + + "\rmic_online_ms\x18\x03 \x01(\x03R\vmicOnlineMs\x12#\n" + + "\rsession_count\x18\x04 \x01(\x03R\fsessionCount\x12%\n" + + "\x0ffirst_mic_at_ms\x18\x05 \x01(\x03R\ffirstMicAtMs\x12#\n" + + "\x0elast_mic_at_ms\x18\x06 \x01(\x03R\vlastMicAtMs\x12\"\n" + + "\rupdated_at_ms\x18\a \x01(\x03R\vupdatedAtMs\x12\x19\n" + + "\bapp_code\x18\b \x01(\tR\aappCode\"i\n" + + "\x1eGetUserMicLifetimeStatsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\"\\\n" + + "\x1fGetUserMicLifetimeStatsResponse\x129\n" + + "\x05stats\x18\x01 \x01(\v2#.hyapp.user.v1.UserMicLifetimeStatsR\x05stats\"\xe9\x02\n" + + "\x10CronBatchRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x15\n" + + "\x06run_id\x18\x02 \x01(\tR\x05runId\x12\x1b\n" + + "\tworker_id\x18\x03 \x01(\tR\bworkerId\x12\x1d\n" + + "\n" + + "batch_size\x18\x04 \x01(\x05R\tbatchSize\x12\x1e\n" + + "\vlock_ttl_ms\x18\x05 \x01(\x03R\tlockTtlMs\x12:\n" + + "\x1apending_publish_max_age_ms\x18\x06 \x01(\x03R\x16pendingPublishMaxAgeMs\x12@\n" + + "\x1dpublishing_session_max_age_ms\x18\a \x01(\x03R\x19publishingSessionMaxAgeMs\x124\n" + + "\x17open_session_max_age_ms\x18\b \x01(\x03R\x13openSessionMaxAgeMs\"\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\ahasMore\"\x96\x04\n" + + "\tAuthToken\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x1d\n" + + "\n" + + "session_id\x18\x02 \x01(\tR\tsessionId\x12!\n" + + "\faccess_token\x18\x03 \x01(\tR\vaccessToken\x12#\n" + + "\rrefresh_token\x18\x04 \x01(\tR\frefreshToken\x12$\n" + + "\x0eexpires_in_sec\x18\x05 \x01(\x03R\fexpiresInSec\x12\x1d\n" + + "\n" + + "token_type\x18\x06 \x01(\tR\ttokenType\x12&\n" + + "\x0fdisplay_user_id\x18\a \x01(\tR\rdisplayUserId\x125\n" + + "\x17default_display_user_id\x18\b \x01(\tR\x14defaultDisplayUserId\x12/\n" + + "\x14display_user_id_kind\x18\t \x01(\tR\x11displayUserIdKind\x12?\n" + + "\x1ddisplay_user_id_expires_at_ms\x18\n" + + " \x01(\x03R\x18displayUserIdExpiresAtMs\x12+\n" + + "\x11profile_completed\x18\v \x01(\bR\x10profileCompleted\x12+\n" + + "\x11onboarding_status\x18\f \x01(\tR\x10onboardingStatus\x12\x19\n" + + "\bapp_code\x18\r \x01(\tR\aappCode\"Y\n" + + "\x0eGetUserRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\":\n" + + "\x0fGetUserResponse\x12'\n" + + "\x04user\x18\x01 \x01(\v2\x13.hyapp.user.v1.UserR\x04user\"\xbc\x01\n" + + "\x19BusinessUserLookupRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\"\n" + + "\ractor_user_id\x18\x02 \x01(\x03R\vactorUserId\x12\x14\n" + + "\x05scene\x18\x03 \x01(\tR\x05scene\x12\x18\n" + + "\akeyword\x18\x04 \x01(\tR\akeyword\x12\x1b\n" + + "\tpage_size\x18\x05 \x01(\x05R\bpageSize\"\x9f\x02\n" + + "\x16BusinessUserLookupItem\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12&\n" + + "\x0fdisplay_user_id\x18\x02 \x01(\tR\rdisplayUserId\x12\x1a\n" + + "\busername\x18\x03 \x01(\tR\busername\x12\x16\n" + + "\x06avatar\x18\x04 \x01(\tR\x06avatar\x121\n" + + "\x06status\x18\x05 \x01(\x0e2\x19.hyapp.user.v1.UserStatusR\x06status\x12\x1b\n" + + "\tregion_id\x18\x06 \x01(\x03R\bregionId\x12\x1f\n" + + "\vregion_code\x18\a \x01(\tR\n" + + "regionCode\x12\x1f\n" + + "\vregion_name\x18\b \x01(\tR\n" + + "regionName\"Y\n" + + "\x1aBusinessUserLookupResponse\x12;\n" + + "\x05users\x18\x01 \x03(\v2%.hyapp.user.v1.BusinessUserLookupItemR\x05users\"\xdf\x01\n" + + "\x10UserProfileStats\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12%\n" + + "\x0evisitors_count\x18\x02 \x01(\x03R\rvisitorsCount\x12'\n" + + "\x0ffollowing_count\x18\x03 \x01(\x03R\x0efollowingCount\x12#\n" + + "\rfriends_count\x18\x04 \x01(\x03R\ffriendsCount\x12\"\n" + + "\rupdated_at_ms\x18\x05 \x01(\x03R\vupdatedAtMs\x12\x19\n" + + "\bapp_code\x18\x06 \x01(\tR\aappCode\"c\n" + + "\x18GetMyProfileStatsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\"R\n" + + "\x19GetMyProfileStatsResponse\x125\n" + + "\x05stats\x18\x01 \x01(\v2\x1f.hyapp.user.v1.UserProfileStatsR\x05stats\"\x99\x01\n" + + "\x19RecordProfileVisitRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12&\n" + + "\x0fvisitor_user_id\x18\x02 \x01(\x03R\rvisitorUserId\x12$\n" + + "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\"|\n" + + "\x1aRecordProfileVisitResponse\x12\x1a\n" + + "\brecorded\x18\x01 \x01(\bR\brecorded\x12B\n" + + "\ftarget_stats\x18\x02 \x01(\v2\x1f.hyapp.user.v1.UserProfileStatsR\vtargetStats\"\xb0\x01\n" + + "\x12ProfileVisitRecord\x12&\n" + + "\x0fvisitor_user_id\x18\x01 \x01(\x03R\rvisitorUserId\x12$\n" + + "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x1f\n" + + "\vvisit_count\x18\x03 \x01(\x03R\n" + + "visitCount\x12+\n" + + "\x12last_visited_at_ms\x18\x04 \x01(\x03R\x0flastVisitedAtMs\"\x96\x01\n" + + "\x1aListProfileVisitorsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x12\n" + + "\x04page\x18\x03 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\x04 \x01(\x05R\bpageSize\"p\n" + + "\x1bListProfileVisitorsResponse\x12;\n" + + "\arecords\x18\x01 \x03(\v2!.hyapp.user.v1.ProfileVisitRecordR\arecords\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\x97\x01\n" + + "\x11FollowUserRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12(\n" + + "\x10follower_user_id\x18\x02 \x01(\x03R\x0efollowerUserId\x12(\n" + + "\x10followee_user_id\x18\x03 \x01(\x03R\x0efolloweeUserId\"z\n" + + "\x12FollowUserResponse\x12\x1c\n" + + "\tfollowing\x18\x01 \x01(\bR\tfollowing\x12F\n" + + "\x0efollower_stats\x18\x02 \x01(\v2\x1f.hyapp.user.v1.UserProfileStatsR\rfollowerStats\"\x99\x01\n" + + "\x13UnfollowUserRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12(\n" + + "\x10follower_user_id\x18\x02 \x01(\x03R\x0efollowerUserId\x12(\n" + + "\x10followee_user_id\x18\x03 \x01(\x03R\x0efolloweeUserId\"|\n" + + "\x14UnfollowUserResponse\x12\x1c\n" + + "\tfollowing\x18\x01 \x01(\bR\tfollowing\x12F\n" + + "\x0efollower_stats\x18\x02 \x01(\v2\x1f.hyapp.user.v1.UserProfileStatsR\rfollowerStats\"\x88\x01\n" + + "\fFollowRecord\x12(\n" + + "\x10follower_user_id\x18\x01 \x01(\x03R\x0efollowerUserId\x12(\n" + + "\x10followee_user_id\x18\x02 \x01(\x03R\x0efolloweeUserId\x12$\n" + + "\x0efollowed_at_ms\x18\x03 \x01(\x03R\ffollowedAtMs\"\xe7\x01\n" + + "\x14ListFollowingRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x12\n" + + "\x04page\x18\x03 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\x04 \x01(\x05R\bpageSize\x12/\n" + + "\x14cursor_updated_at_ms\x18\x05 \x01(\x03R\x11cursorUpdatedAtMs\x12$\n" + + "\x0ecursor_user_id\x18\x06 \x01(\x03R\fcursorUserId\"d\n" + + "\x15ListFollowingResponse\x125\n" + + "\arecords\x18\x01 \x03(\v2\x1b.hyapp.user.v1.FollowRecordR\arecords\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\x96\x01\n" + + "\x12ApplyFriendRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12*\n" + + "\x11requester_user_id\x18\x02 \x01(\x03R\x0frequesterUserId\x12$\n" + + "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\"\x82\x01\n" + + "\x13ApplyFriendResponse\x12B\n" + + "\vapplication\x18\x01 \x01(\v2 .hyapp.user.v1.FriendApplicationR\vapplication\x12'\n" + + "\x0falready_friends\x18\x02 \x01(\bR\x0ealreadyFriends\"\xa6\x01\n" + + "\x1eAcceptFriendApplicationRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12(\n" + + "\x10accepter_user_id\x18\x02 \x01(\x03R\x0eaccepterUserId\x12*\n" + + "\x11requester_user_id\x18\x03 \x01(\x03R\x0frequesterUserId\"V\n" + + "\x1fAcceptFriendApplicationResponse\x123\n" + + "\x06friend\x18\x01 \x01(\v2\x1b.hyapp.user.v1.FriendRecordR\x06friend\"\x84\x01\n" + + "\x13DeleteFriendRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12$\n" + + "\x0efriend_user_id\x18\x03 \x01(\x03R\ffriendUserId\"0\n" + + "\x14DeleteFriendResponse\x12\x18\n" + + "\adeleted\x18\x01 \x01(\bR\adeleted\"s\n" + + "\fFriendRecord\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12$\n" + + "\x0efriend_user_id\x18\x02 \x01(\x03R\ffriendUserId\x12$\n" + + "\x0efriended_at_ms\x18\x03 \x01(\x03R\ffriendedAtMs\"\xe5\x01\n" + + "\x12ListFriendsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x12\n" + + "\x04page\x18\x03 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\x04 \x01(\x05R\bpageSize\x12/\n" + + "\x14cursor_updated_at_ms\x18\x05 \x01(\x03R\x11cursorUpdatedAtMs\x12$\n" + + "\x0ecursor_user_id\x18\x06 \x01(\x03R\fcursorUserId\"b\n" + + "\x13ListFriendsResponse\x125\n" + + "\arecords\x18\x01 \x03(\v2\x1b.hyapp.user.v1.FriendRecordR\arecords\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\xc5\x01\n" + + "\x11FriendApplication\x12*\n" + + "\x11requester_user_id\x18\x01 \x01(\x03R\x0frequesterUserId\x12$\n" + + "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x16\n" + + "\x06status\x18\x03 \x01(\tR\x06status\x12\"\n" + + "\rcreated_at_ms\x18\x04 \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x05 \x01(\x03R\vupdatedAtMs\"\xb7\x01\n" + + "\x1dListFriendApplicationsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1c\n" + + "\tdirection\x18\x03 \x01(\tR\tdirection\x12\x12\n" + + "\x04page\x18\x04 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\x05 \x01(\x05R\bpageSize\"|\n" + + "\x1eListFriendApplicationsResponse\x12D\n" + + "\fapplications\x18\x01 \x03(\v2 .hyapp.user.v1.FriendApplicationR\fapplications\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\x84\x01\n" + + "\rCPUserProfile\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12&\n" + + "\x0fdisplay_user_id\x18\x02 \x01(\tR\rdisplayUserId\x12\x1a\n" + + "\busername\x18\x03 \x01(\tR\busername\x12\x16\n" + + "\x06avatar\x18\x04 \x01(\tR\x06avatar\"\xa3\x02\n" + + "\x0eCPGiftSnapshot\x12\x17\n" + + "\agift_id\x18\x01 \x01(\tR\x06giftId\x12\x1b\n" + + "\tgift_name\x18\x02 \x01(\tR\bgiftName\x12\"\n" + + "\rgift_icon_url\x18\x03 \x01(\tR\vgiftIconUrl\x12,\n" + + "\x12gift_animation_url\x18\x04 \x01(\tR\x10giftAnimationUrl\x12\x1d\n" + + "\n" + + "gift_count\x18\x05 \x01(\x05R\tgiftCount\x12\x1d\n" + + "\n" + + "gift_value\x18\x06 \x01(\x03R\tgiftValue\x12,\n" + + "\x12billing_receipt_id\x18\a \x01(\tR\x10billingReceiptId\x12\x1d\n" + + "\n" + + "coin_spent\x18\b \x01(\x03R\tcoinSpent\"\xe7\x03\n" + + "\rCPApplication\x12%\n" + + "\x0eapplication_id\x18\x01 \x01(\tR\rapplicationId\x12#\n" + + "\rrelation_type\x18\x02 \x01(\tR\frelationType\x12\x16\n" + + "\x06status\x18\x03 \x01(\tR\x06status\x12:\n" + + "\trequester\x18\x04 \x01(\v2\x1c.hyapp.user.v1.CPUserProfileR\trequester\x124\n" + + "\x06target\x18\x05 \x01(\v2\x1c.hyapp.user.v1.CPUserProfileR\x06target\x12\x17\n" + + "\aroom_id\x18\x06 \x01(\tR\x06roomId\x12$\n" + + "\x0eroom_region_id\x18\a \x01(\x03R\froomRegionId\x121\n" + + "\x04gift\x18\b \x01(\v2\x1d.hyapp.user.v1.CPGiftSnapshotR\x04gift\x12\"\n" + + "\rcreated_at_ms\x18\t \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\n" + + " \x01(\x03R\vupdatedAtMs\x12\"\n" + + "\rexpires_at_ms\x18\v \x01(\x03R\vexpiresAtMs\x12\"\n" + + "\rdecided_at_ms\x18\f \x01(\x03R\vdecidedAtMs\"\xad\x05\n" + + "\x0eCPRelationship\x12'\n" + + "\x0frelationship_id\x18\x01 \x01(\tR\x0erelationshipId\x12#\n" + + "\rrelation_type\x18\x02 \x01(\tR\frelationType\x12\x16\n" + + "\x06status\x18\x03 \x01(\tR\x06status\x12,\n" + + "\x02me\x18\x04 \x01(\v2\x1c.hyapp.user.v1.CPUserProfileR\x02me\x126\n" + + "\apartner\x18\x05 \x01(\v2\x1c.hyapp.user.v1.CPUserProfileR\apartner\x12%\n" + + "\x0eintimacy_value\x18\x06 \x01(\x03R\rintimacyValue\x12\x14\n" + + "\x05level\x18\a \x01(\x05R\x05level\x12 \n" + + "\fformed_at_ms\x18\t \x01(\x03R\n" + + "formedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\n" + + " \x01(\x03R\vupdatedAtMs\x126\n" + + "\x17current_level_threshold\x18\v \x01(\x03R\x15currentLevelThreshold\x120\n" + + "\x14next_level_threshold\x18\f \x01(\x03R\x12nextLevelThreshold\x121\n" + + "\x15needed_for_next_level\x18\r \x01(\x03R\x12neededForNextLevel\x124\n" + + "\x16level_progress_percent\x18\x0e \x01(\x05R\x14levelProgressPercent\x12\x1b\n" + + "\tmax_level\x18\x0f \x01(\bR\bmaxLevel\x12,\n" + + "\x12breakup_cost_coins\x18\x10 \x01(\x03R\x10breakupCostCoins\x12\x1e\n" + + "\vended_at_ms\x18\x11 \x01(\x03R\tendedAtMsJ\x04\b\b\x10\tR\bequipped\"\xf9\x01\n" + + "\x15CPAvatarFrameSnapshot\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\"\xd9\x01\n" + + "\x19CPIntimacyLeaderboardUser\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12&\n" + + "\x0fdisplay_user_id\x18\x02 \x01(\tR\rdisplayUserId\x12\x1a\n" + + "\busername\x18\x03 \x01(\tR\busername\x12\x16\n" + + "\x06avatar\x18\x04 \x01(\tR\x06avatar\x12G\n" + + "\favatar_frame\x18\x05 \x01(\v2$.hyapp.user.v1.CPAvatarFrameSnapshotR\vavatarFrame\"\x82\x03\n" + + "\x19CPIntimacyLeaderboardItem\x12\x12\n" + + "\x04rank\x18\x01 \x01(\x03R\x04rank\x12'\n" + + "\x0frelationship_id\x18\x02 \x01(\tR\x0erelationshipId\x12#\n" + + "\rrelation_type\x18\x03 \x01(\tR\frelationType\x12%\n" + + "\x0eintimacy_value\x18\x04 \x01(\x03R\rintimacyValue\x12\x14\n" + + "\x05level\x18\x05 \x01(\x05R\x05level\x12?\n" + + "\x06user_a\x18\x06 \x01(\v2(.hyapp.user.v1.CPIntimacyLeaderboardUserR\x05userA\x12?\n" + + "\x06user_b\x18\a \x01(\v2(.hyapp.user.v1.CPIntimacyLeaderboardUserR\x05userB\x12 \n" + + "\fformed_at_ms\x18\b \x01(\x03R\n" + + "formedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\t \x01(\x03R\vupdatedAtMs\"\xab\x03\n" + + "\x11CPWeeklyRankEntry\x12\x12\n" + + "\x04rank\x18\x01 \x01(\x03R\x04rank\x12'\n" + + "\x0frelationship_id\x18\x02 \x01(\tR\x0erelationshipId\x12#\n" + + "\rrelation_type\x18\x03 \x01(\tR\frelationType\x12\x14\n" + + "\x05score\x18\x04 \x01(\x03R\x05score\x12?\n" + + "\x06user_a\x18\x05 \x01(\v2(.hyapp.user.v1.CPIntimacyLeaderboardUserR\x05userA\x12?\n" + + "\x06user_b\x18\x06 \x01(\v2(.hyapp.user.v1.CPIntimacyLeaderboardUserR\x05userB\x12 \n" + + "\fformed_at_ms\x18\a \x01(\x03R\n" + + "formedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\b \x01(\x03R\vupdatedAtMs\x12+\n" + + "\x12first_scored_at_ms\x18\t \x01(\x03R\x0ffirstScoredAtMs\x12)\n" + + "\x11last_scored_at_ms\x18\n" + + " \x01(\x03R\x0elastScoredAtMs\"\xbd\x01\n" + + "\x1eListCPWeeklyRankEntriesRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12#\n" + + "\rrelation_type\x18\x02 \x01(\tR\frelationType\x12\x19\n" + + "\bstart_ms\x18\x03 \x01(\x03R\astartMs\x12\x15\n" + + "\x06end_ms\x18\x04 \x01(\x03R\x05endMs\x12\x14\n" + + "\x05limit\x18\x05 \x01(\x05R\x05limit\"\x83\x01\n" + + "\x1fListCPWeeklyRankEntriesResponse\x12:\n" + + "\aentries\x18\x01 \x03(\v2 .hyapp.user.v1.CPWeeklyRankEntryR\aentries\x12$\n" + + "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xcb\x01\n" + + "\x19ListCPApplicationsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1c\n" + + "\tdirection\x18\x03 \x01(\tR\tdirection\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\"\x9a\x01\n" + + "\x1aListCPApplicationsResponse\x12@\n" + + "\fapplications\x18\x01 \x03(\v2\x1c.hyapp.user.v1.CPApplicationR\fapplications\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\x12$\n" + + "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\x8c\x01\n" + + "\x1aAcceptCPApplicationRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12%\n" + + "\x0eapplication_id\x18\x03 \x01(\tR\rapplicationId\"\xa0\x01\n" + + "\x1bAcceptCPApplicationResponse\x12>\n" + + "\vapplication\x18\x01 \x01(\v2\x1c.hyapp.user.v1.CPApplicationR\vapplication\x12A\n" + + "\frelationship\x18\x02 \x01(\v2\x1d.hyapp.user.v1.CPRelationshipR\frelationship\"\xa4\x01\n" + + "\x1aRejectCPApplicationRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12%\n" + + "\x0eapplication_id\x18\x03 \x01(\tR\rapplicationId\x12\x16\n" + + "\x06reason\x18\x04 \x01(\tR\x06reason\"]\n" + + "\x1bRejectCPApplicationResponse\x12>\n" + + "\vapplication\x18\x01 \x01(\v2\x1c.hyapp.user.v1.CPApplicationR\vapplication\"\xbb\x01\n" + + "\x1aListCPRelationshipsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12#\n" + + "\rrelation_type\x18\x03 \x01(\tR\frelationType\x12\x12\n" + + "\x04page\x18\x04 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\x05 \x01(\x05R\bpageSize\"\x9a\x01\n" + + "\x1bListCPRelationshipsResponse\x12C\n" + + "\rrelationships\x18\x01 \x03(\v2\x1d.hyapp.user.v1.CPRelationshipR\rrelationships\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05totalJ\x04\b\x03\x10\x04R\x1amax_count_by_relation_type\"\xa8\x01\n" + + " ListCPIntimacyLeaderboardRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12#\n" + + "\rrelation_type\x18\x02 \x01(\tR\frelationType\x12\x12\n" + + "\x04page\x18\x03 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\x04 \x01(\x05R\bpageSize\"\xd0\x01\n" + + "!ListCPIntimacyLeaderboardResponse\x12>\n" + + "\x05items\x18\x01 \x03(\v2(.hyapp.user.v1.CPIntimacyLeaderboardItemR\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\"\xb4\x01\n" + + "!PrepareBreakCPRelationshipRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12'\n" + + "\x0frelationship_id\x18\x03 \x01(\tR\x0erelationshipId\x12\x1d\n" + + "\n" + + "command_id\x18\x04 \x01(\tR\tcommandId\"\xae\x02\n" + + "\"PrepareBreakCPRelationshipResponse\x12A\n" + + "\frelationship\x18\x01 \x01(\v2\x1d.hyapp.user.v1.CPRelationshipR\frelationship\x12\x1d\n" + + "\n" + + "command_id\x18\x02 \x01(\tR\tcommandId\x12\x16\n" + + "\x06status\x18\x03 \x01(\tR\x06status\x12,\n" + + "\x12breakup_cost_coins\x18\x04 \x01(\x03R\x10breakupCostCoins\x122\n" + + "\x15wallet_transaction_id\x18\x05 \x01(\tR\x13walletTransactionId\x12,\n" + + "\x12coin_balance_after\x18\x06 \x01(\x03R\x10coinBalanceAfter\"\xc0\x02\n" + + "!ConfirmBreakCPRelationshipRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12'\n" + + "\x0frelationship_id\x18\x03 \x01(\tR\x0erelationshipId\x12\x1d\n" + + "\n" + + "command_id\x18\x04 \x01(\tR\tcommandId\x122\n" + + "\x15wallet_transaction_id\x18\x05 \x01(\tR\x13walletTransactionId\x12(\n" + + "\x10paid_coin_amount\x18\x06 \x01(\x03R\x0epaidCoinAmount\x12,\n" + + "\x12coin_balance_after\x18\a \x01(\x03R\x10coinBalanceAfter\"\xf7\x01\n" + + "\"ConfirmBreakCPRelationshipResponse\x12A\n" + + "\frelationship\x18\x01 \x01(\v2\x1d.hyapp.user.v1.CPRelationshipR\frelationship\x12,\n" + + "\x12breakup_cost_coins\x18\x02 \x01(\x03R\x10breakupCostCoins\x122\n" + + "\x15wallet_transaction_id\x18\x03 \x01(\tR\x13walletTransactionId\x12,\n" + + "\x12coin_balance_after\x18\x04 \x01(\x03R\x10coinBalanceAfter\"\xcb\x01\n" + + " CancelBreakCPRelationshipRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12'\n" + + "\x0frelationship_id\x18\x03 \x01(\tR\x0erelationshipId\x12\x1d\n" + + "\n" + + "command_id\x18\x04 \x01(\tR\tcommandId\x12\x16\n" + + "\x06reason\x18\x05 \x01(\tR\x06reason\"Z\n" + + "!CancelBreakCPRelationshipResponse\x12\x1d\n" + + "\n" + + "command_id\x18\x01 \x01(\tR\tcommandId\x12\x16\n" + + "\x06status\x18\x02 \x01(\tR\x06status\"\xb8\x05\n" + + "\x0fRoomGiftCPEvent\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x19\n" + + "\bevent_id\x18\x02 \x01(\tR\aeventId\x12\x17\n" + + "\aroom_id\x18\x03 \x01(\tR\x06roomId\x12!\n" + + "\froom_version\x18\x04 \x01(\x03R\vroomVersion\x12$\n" + + "\x0eoccurred_at_ms\x18\x05 \x01(\x03R\foccurredAtMs\x12$\n" + + "\x0esender_user_id\x18\x06 \x01(\x03R\fsenderUserId\x12$\n" + + "\x0etarget_user_id\x18\a \x01(\x03R\ftargetUserId\x12\x17\n" + + "\agift_id\x18\b \x01(\tR\x06giftId\x12\x1d\n" + + "\n" + + "gift_count\x18\t \x01(\x05R\tgiftCount\x12\x1d\n" + + "\n" + + "gift_value\x18\n" + + " \x01(\x03R\tgiftValue\x12,\n" + + "\x12billing_receipt_id\x18\v \x01(\tR\x10billingReceiptId\x12*\n" + + "\x11visible_region_id\x18\f \x01(\x03R\x0fvisibleRegionId\x12\x1d\n" + + "\n" + + "command_id\x18\r \x01(\tR\tcommandId\x12$\n" + + "\x0egift_type_code\x18\x0e \x01(\tR\fgiftTypeCode\x12(\n" + + "\x10cp_relation_type\x18\x0f \x01(\tR\x0ecpRelationType\x12\x1b\n" + + "\tgift_name\x18\x10 \x01(\tR\bgiftName\x12\"\n" + + "\rgift_icon_url\x18\x11 \x01(\tR\vgiftIconUrl\x12,\n" + + "\x12gift_animation_url\x18\x12 \x01(\tR\x10giftAnimationUrl\x12\x1d\n" + + "\n" + + "coin_spent\x18\x13 \x01(\x03R\tcoinSpent\"\x85\x01\n" + + "\x1dConsumeRoomGiftCPEventRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x124\n" + + "\x05event\x18\x02 \x01(\v2\x1e.hyapp.user.v1.RoomGiftCPEventR\x05event\"\xbf\x01\n" + + "\x1eConsumeRoomGiftCPEventResponse\x12\x1a\n" + + "\bconsumed\x18\x01 \x01(\bR\bconsumed\x12>\n" + + "\vapplication\x18\x02 \x01(\v2\x1c.hyapp.user.v1.CPApplicationR\vapplication\x12A\n" + + "\frelationship\x18\x03 \x01(\v2\x1d.hyapp.user.v1.CPRelationshipR\frelationship\"\xba\x02\n" + + "\n" + + "UserReport\x12\x1b\n" + + "\treport_id\x18\x01 \x01(\tR\breportId\x12(\n" + + "\x10reporter_user_id\x18\x02 \x01(\x03R\x0ereporterUserId\x12\x1f\n" + + "\vtarget_type\x18\x03 \x01(\tR\n" + + "targetType\x12\x17\n" + + "\auser_id\x18\x04 \x01(\x03R\x06userId\x12\x17\n" + + "\aroom_id\x18\x05 \x01(\tR\x06roomId\x12\x1f\n" + + "\vreport_type\x18\x06 \x01(\tR\n" + + "reportType\x12\x16\n" + + "\x06reason\x18\a \x01(\tR\x06reason\x12\x1d\n" + + "\n" + + "image_urls\x18\b \x03(\tR\timageUrls\x12\x16\n" + + "\x06status\x18\t \x01(\tR\x06status\x12\"\n" + + "\rcreated_at_ms\x18\n" + + " \x01(\x03R\vcreatedAtMs\"\xf9\x01\n" + + "\x13SubmitReportRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12(\n" + + "\x10reporter_user_id\x18\x02 \x01(\x03R\x0ereporterUserId\x12\x17\n" + + "\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x17\n" + + "\aroom_id\x18\x04 \x01(\tR\x06roomId\x12\x1f\n" + + "\vreport_type\x18\x05 \x01(\tR\n" + + "reportType\x12\x16\n" + + "\x06reason\x18\x06 \x01(\tR\x06reason\x12\x1d\n" + + "\n" + + "image_urls\x18\a \x03(\tR\timageUrls\"I\n" + + "\x14SubmitReportResponse\x121\n" + + "\x06report\x18\x01 \x01(\v2\x19.hyapp.user.v1.UserReportR\x06report\"a\n" + + "\x14BatchGetUsersRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x19\n" + + "\buser_ids\x18\x02 \x03(\x03R\auserIds\"\xad\x01\n" + + "\x15BatchGetUsersResponse\x12E\n" + + "\x05users\x18\x01 \x03(\v2/.hyapp.user.v1.BatchGetUsersResponse.UsersEntryR\x05users\x1aM\n" + + "\n" + + "UsersEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\x03R\x03key\x12)\n" + + "\x05value\x18\x02 \x01(\v2\x13.hyapp.user.v1.UserR\x05value:\x028\x01\"\x90\x03\n" + + "\x14ActiveUserBanSummary\x12\x16\n" + + "\x06active\x18\x01 \x01(\bR\x06active\x12\x16\n" + + "\x06source\x18\x02 \x01(\tR\x06source\x12\x15\n" + + "\x06ban_id\x18\x03 \x01(\tR\x05banId\x12\x1c\n" + + "\tpermanent\x18\x04 \x01(\bR\tpermanent\x12\"\n" + + "\rexpires_at_ms\x18\x05 \x01(\x03R\vexpiresAtMs\x12:\n" + + "\vuser_status\x18\x06 \x01(\x0e2\x19.hyapp.user.v1.UserStatusR\n" + + "userStatus\x12#\n" + + "\roperator_type\x18\a \x01(\tR\foperatorType\x12(\n" + + "\x10operator_user_id\x18\b \x01(\x03R\x0eoperatorUserId\x12\x16\n" + + "\x06reason\x18\t \x01(\tR\x06reason\x12\"\n" + + "\rcreated_at_ms\x18\n" + + " \x01(\x03R\vcreatedAtMs\x12(\n" + + "\x10active_ban_count\x18\v \x01(\x05R\x0eactiveBanCount\"\xc5\x03\n" + + "\x10UserAdminProfile\x12'\n" + + "\x04user\x18\x01 \x01(\v2\x13.hyapp.user.v1.UserR\x04user\x12\x14\n" + + "\x05birth\x18\x02 \x01(\tR\x05birth\x12'\n" + + "\x0fregister_device\x18\x03 \x01(\tR\x0eregisterDevice\x126\n" + + "\x18last_success_login_at_ms\x18\x04 \x01(\x03R\x14lastSuccessLoginAtMs\x12\x14\n" + + "\x05roles\x18\x05 \x03(\tR\x05roles\x125\n" + + "\x03ban\x18\x06 \x01(\v2#.hyapp.user.v1.ActiveUserBanSummaryR\x03ban\x12,\n" + + "\x12last_operator_type\x18\a \x01(\tR\x10lastOperatorType\x121\n" + + "\x15last_operator_user_id\x18\b \x01(\x03R\x12lastOperatorUserId\x122\n" + + "\x15last_operation_reason\x18\t \x01(\tR\x13lastOperationReason\x12/\n" + + "\x14last_operation_at_ms\x18\n" + + " \x01(\x03R\x11lastOperationAtMs\"m\n" + + " BatchGetUserAdminProfilesRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x19\n" + + "\buser_ids\x18\x02 \x03(\x03R\auserIds\"\xdd\x01\n" + + "!BatchGetUserAdminProfilesResponse\x12Z\n" + + "\bprofiles\x18\x01 \x03(\v2>.hyapp.user.v1.BatchGetUserAdminProfilesResponse.ProfilesEntryR\bprofiles\x1a\\\n" + + "\rProfilesEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\x03R\x03key\x125\n" + + "\x05value\x18\x02 \x01(\v2\x1f.hyapp.user.v1.UserAdminProfileR\x05value:\x028\x01\"\x86\x01\n" + + " AdminIssueUserAccessTokenRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + + "\auser_id\x18\x03 \x01(\x03R\x06userId\"\x87\x02\n" + + "!AdminIssueUserAccessTokenResponse\x12!\n" + + "\faccess_token\x18\x01 \x01(\tR\vaccessToken\x12\x1d\n" + + "\n" + + "token_type\x18\x02 \x01(\tR\ttokenType\x12$\n" + + "\x0eexpires_in_sec\x18\x03 \x01(\x03R\fexpiresInSec\x12\x1d\n" + + "\n" + + "session_id\x18\x04 \x01(\tR\tsessionId\x12\x1b\n" + + "\tdevice_id\x18\x05 \x01(\tR\bdeviceId\x12>\n" + + "\x1csession_last_heartbeat_at_ms\x18\x06 \x01(\x03R\x18sessionLastHeartbeatAtMs\"\x84\x01\n" + + "\rRoomBasicUser\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x1a\n" + + "\busername\x18\x02 \x01(\tR\busername\x12\x16\n" + + "\x06avatar\x18\x03 \x01(\tR\x06avatar\x12&\n" + + "\x0fdisplay_user_id\x18\x04 \x01(\tR\rdisplayUserId\"j\n" + + "\x1dBatchGetRoomBasicUsersRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x19\n" + + "\buser_ids\x18\x02 \x03(\x03R\auserIds\"\xc8\x01\n" + + "\x1eBatchGetRoomBasicUsersResponse\x12N\n" + + "\x05users\x18\x01 \x03(\v28.hyapp.user.v1.BatchGetRoomBasicUsersResponse.UsersEntryR\x05users\x1aV\n" + + "\n" + + "UsersEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\x03R\x03key\x122\n" + + "\x05value\x18\x02 \x01(\v2\x1c.hyapp.user.v1.RoomBasicUserR\x05value:\x028\x01\"\xe1\x01\n" + + "\x12ListUserIDsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12!\n" + + "\ftarget_scope\x18\x02 \x01(\tR\vtargetScope\x12$\n" + + "\x0ecursor_user_id\x18\x03 \x01(\x03R\fcursorUserId\x12\x1b\n" + + "\tpage_size\x18\x04 \x01(\x05R\bpageSize\x12\x1b\n" + + "\tregion_id\x18\x05 \x01(\x03R\bregionId\x12\x18\n" + + "\acountry\x18\x06 \x01(\tR\acountry\"s\n" + + "\x13ListUserIDsResponse\x12\x19\n" + + "\buser_ids\x18\x01 \x03(\x03R\auserIds\x12-\n" + + "\x13next_cursor_user_id\x18\x02 \x01(\x03R\x10nextCursorUserId\x12\x12\n" + + "\x04done\x18\x03 \x01(\bR\x04done\"\x86\x02\n" + + "\x18UpdateUserProfileRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1f\n" + + "\busername\x18\x03 \x01(\tH\x00R\busername\x88\x01\x01\x12\x1b\n" + + "\x06avatar\x18\x04 \x01(\tH\x01R\x06avatar\x88\x01\x01\x12\x19\n" + + "\x05birth\x18\x05 \x01(\tH\x02R\x05birth\x88\x01\x01\x12\x1b\n" + + "\x06gender\x18\x06 \x01(\tH\x03R\x06gender\x88\x01\x01B\v\n" + + "\t_usernameB\t\n" + + "\a_avatarB\b\n" + + "\x06_birthB\t\n" + + "\a_gender\"D\n" + + "\x19UpdateUserProfileResponse\x12'\n" + + "\x04user\x18\x01 \x01(\v2\x13.hyapp.user.v1.UserR\x04user\"\x93\x01\n" + + "\"UpdateUserProfileBackgroundRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12$\n" + + "\x0eprofile_bg_img\x18\x03 \x01(\tR\fprofileBgImg\"N\n" + + "#UpdateUserProfileBackgroundResponse\x12'\n" + + "\x04user\x18\x01 \x01(\v2\x13.hyapp.user.v1.UserR\x04user\"\x8a\x01\n" + + "\x1cUpdateUserContactInfoRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12!\n" + + "\fcontact_info\x18\x03 \x01(\tR\vcontactInfo\"H\n" + + "\x1dUpdateUserContactInfoResponse\x12'\n" + + "\x04user\x18\x01 \x01(\v2\x13.hyapp.user.v1.UserR\x04user\"\x99\x01\n" + + " UpdateUserWithdrawAddressRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12,\n" + + "\x12usdt_trc20_address\x18\x03 \x01(\tR\x10usdtTrc20Address\"L\n" + + "!UpdateUserWithdrawAddressResponse\x12'\n" + + "\x04user\x18\x01 \x01(\v2\x13.hyapp.user.v1.UserR\x04user\"}\n" + + "\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\"\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" + + "\rold_region_id\x18\x03 \x01(\x03R\voldRegionId\x12\"\n" + + "\rnew_region_id\x18\x04 \x01(\x03R\vnewRegionId\x12%\n" + + "\x0eregion_changed\x18\x05 \x01(\bR\rregionChanged\"\x86\x02\n" + + "\x14SetUserStatusRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12$\n" + + "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x121\n" + + "\x06status\x18\x03 \x01(\x0e2\x19.hyapp.user.v1.UserStatusR\x06status\x12(\n" + + "\x10operator_user_id\x18\x04 \x01(\x03R\x0eoperatorUserId\x12\x16\n" + + "\x06reason\x18\x05 \x01(\tR\x06reason\x12#\n" + + "\roperator_type\x18\x06 \x01(\tR\foperatorType\"\xcd\x03\n" + + "\x15SetUserStatusResponse\x12'\n" + + "\x04user\x18\x01 \x01(\v2\x13.hyapp.user.v1.UserR\x04user\x122\n" + + "\x15revoked_session_count\x18\x02 \x01(\x03R\x13revokedSessionCount\x12\x1b\n" + + "\tim_kicked\x18\x03 \x01(\bR\bimKicked\x12\"\n" + + "\rim_kick_error\x18\x04 \x01(\tR\vimKickError\x12!\n" + + "\froom_evicted\x18\x05 \x01(\bR\vroomEvicted\x12\x17\n" + + "\aroom_id\x18\x06 \x01(\tR\x06roomId\x12\x1d\n" + + "\n" + + "rtc_kicked\x18\a \x01(\bR\trtcKicked\x12(\n" + + "\x10room_evict_error\x18\b \x01(\tR\x0eroomEvictError\x12$\n" + + "\x0ertc_kick_error\x18\t \x01(\tR\frtcKickError\x120\n" + + "\x14access_token_revoked\x18\n" + + " \x01(\bR\x12accessTokenRevoked\x129\n" + + "\x19access_token_revoke_error\x18\v \x01(\tR\x16accessTokenRevokeError\"\xd0\x03\n" + + "\fAdminUserBan\x12\x15\n" + + "\x06ban_id\x18\x01 \x01(\tR\x05banId\x12\x1d\n" + + "\n" + + "command_id\x18\x02 \x01(\tR\tcommandId\x12$\n" + + "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x12\"\n" + + "\rexpires_at_ms\x18\x04 \x01(\x03R\vexpiresAtMs\x12\x1c\n" + + "\tpermanent\x18\x05 \x01(\bR\tpermanent\x12\x16\n" + + "\x06status\x18\x06 \x01(\tR\x06status\x12\x16\n" + + "\x06reason\x18\a \x01(\tR\x06reason\x12*\n" + + "\x11operator_admin_id\x18\b \x01(\x03R\x0foperatorAdminId\x12\"\n" + + "\rcreated_at_ms\x18\t \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\n" + + " \x01(\x03R\vupdatedAtMs\x12/\n" + + "\x14released_by_admin_id\x18\v \x01(\x03R\x11releasedByAdminId\x12'\n" + + "\x0freleased_reason\x18\f \x01(\tR\x0ereleasedReason\x12$\n" + + "\x0ereleased_at_ms\x18\r \x01(\x03R\freleasedAtMs\"\xf2\x01\n" + + "\x13AdminBanUserRequest\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" + + "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x12\"\n" + + "\rexpires_at_ms\x18\x04 \x01(\x03R\vexpiresAtMs\x12*\n" + + "\x11operator_admin_id\x18\x05 \x01(\x03R\x0foperatorAdminId\x12\x16\n" + + "\x06reason\x18\x06 \x01(\tR\x06reason\"\x83\x01\n" + + "\x14AdminBanUserResponse\x12-\n" + + "\x03ban\x18\x01 \x01(\v2\x1b.hyapp.user.v1.AdminUserBanR\x03ban\x12<\n" + + "\x06status\x18\x02 \x01(\v2$.hyapp.user.v1.SetUserStatusResponseR\x06status\"\xc8\x01\n" + + "\x15AdminUnbanUserRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x15\n" + + "\x06ban_id\x18\x02 \x01(\tR\x05banId\x12$\n" + + "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x12*\n" + + "\x11operator_admin_id\x18\x04 \x01(\x03R\x0foperatorAdminId\x12\x16\n" + + "\x06reason\x18\x05 \x01(\tR\x06reason\"\xa8\x02\n" + + "\x16AdminUnbanUserResponse\x12-\n" + + "\x03ban\x18\x01 \x01(\v2\x1b.hyapp.user.v1.AdminUserBanR\x03ban\x12<\n" + + "\x06status\x18\x02 \x01(\v2$.hyapp.user.v1.SetUserStatusResponseR\x06status\x127\n" + + "\x18released_admin_ban_count\x18\x03 \x01(\x03R\x15releasedAdminBanCount\x12?\n" + + "\x1creleased_manager_block_count\x18\x04 \x01(\x03R\x19releasedManagerBlockCount\x12'\n" + + "\x0fstatus_restored\x18\x05 \x01(\bR\x0estatusRestored\"\xba\x03\n" + + "\x10ManagerUserBlock\x12\x19\n" + + "\bblock_id\x18\x01 \x01(\tR\ablockId\x12&\n" + + "\x0fmanager_user_id\x18\x02 \x01(\x03R\rmanagerUserId\x12$\n" + + "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x123\n" + + "\x16target_display_user_id\x18\x04 \x01(\tR\x13targetDisplayUserId\x12'\n" + + "\x0ftarget_username\x18\x05 \x01(\tR\x0etargetUsername\x12#\n" + + "\rtarget_avatar\x18\x06 \x01(\tR\ftargetAvatar\x12\x18\n" + + "\acountry\x18\a \x01(\tR\acountry\x12(\n" + + "\x10blocked_until_ms\x18\b \x01(\x03R\x0eblockedUntilMs\x12\x16\n" + + "\x06status\x18\t \x01(\tR\x06status\x12\x16\n" + + "\x06reason\x18\n" + + " \x01(\tR\x06reason\x12\"\n" + + "\rcreated_at_ms\x18\v \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\f \x01(\x03R\vupdatedAtMs\"\xfe\x01\n" + + "\x1dCreateManagerUserBlockRequest\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" + + "\x0fmanager_user_id\x18\x03 \x01(\x03R\rmanagerUserId\x12$\n" + + "\x0etarget_user_id\x18\x04 \x01(\x03R\ftargetUserId\x12(\n" + + "\x10blocked_until_ms\x18\x05 \x01(\x03R\x0eblockedUntilMs\x12\x16\n" + + "\x06reason\x18\x06 \x01(\tR\x06reason\"\x95\x01\n" + + "\x1eCreateManagerUserBlockResponse\x125\n" + + "\x05block\x18\x01 \x01(\v2\x1f.hyapp.user.v1.ManagerUserBlockR\x05block\x12<\n" + + "\x06status\x18\x02 \x01(\v2$.hyapp.user.v1.SetUserStatusResponseR\x06status\"\xab\x01\n" + + "\x1cListManagerUserBlocksRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12&\n" + + "\x0fmanager_user_id\x18\x02 \x01(\x03R\rmanagerUserId\x12\x16\n" + + "\x06status\x18\x03 \x01(\tR\x06status\x12\x1b\n" + + "\tpage_size\x18\x04 \x01(\x05R\bpageSize\"X\n" + + "\x1dListManagerUserBlocksResponse\x127\n" + + "\x06blocks\x18\x01 \x03(\v2\x1f.hyapp.user.v1.ManagerUserBlockR\x06blocks\"\xa6\x01\n" + + "\x19UnblockManagerUserRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12&\n" + + "\x0fmanager_user_id\x18\x02 \x01(\x03R\rmanagerUserId\x12\x19\n" + + "\bblock_id\x18\x03 \x01(\tR\ablockId\x12\x16\n" + + "\x06reason\x18\x04 \x01(\tR\x06reason\"\x91\x01\n" + + "\x1aUnblockManagerUserResponse\x125\n" + + "\x05block\x18\x01 \x01(\v2\x1f.hyapp.user.v1.ManagerUserBlockR\x05block\x12<\n" + + "\x06status\x18\x02 \x01(\v2$.hyapp.user.v1.SetUserStatusResponseR\x06status\"\xeb\x01\n" + + "\x19CompleteOnboardingRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1a\n" + + "\busername\x18\x03 \x01(\tR\busername\x12\x16\n" + + "\x06avatar\x18\x04 \x01(\tR\x06avatar\x12\x18\n" + + "\acountry\x18\x05 \x01(\tR\acountry\x12\x16\n" + + "\x06gender\x18\x06 \x01(\tR\x06gender\x12\x1f\n" + + "\vinvite_code\x18\a \x01(\tR\n" + + "inviteCode\"\xbc\x02\n" + + "\x1aCompleteOnboardingResponse\x12'\n" + + "\x04user\x18\x01 \x01(\v2\x13.hyapp.user.v1.UserR\x04user\x12+\n" + + "\x11profile_completed\x18\x02 \x01(\bR\x10profileCompleted\x125\n" + + "\x17profile_completed_at_ms\x18\x03 \x01(\x03R\x14profileCompletedAtMs\x12+\n" + + "\x11onboarding_status\x18\x04 \x01(\tR\x10onboardingStatus\x12.\n" + + "\x05token\x18\x05 \x01(\v2\x18.hyapp.user.v1.AuthTokenR\x05token\x124\n" + + "\x06invite\x18\x06 \x01(\v2\x1c.hyapp.user.v1.InviteBindingR\x06invite\"\x87\x01\n" + + "\x1bSearchInviteReferrerRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1f\n" + + "\vinvite_code\x18\x03 \x01(\tR\n" + + "inviteCode\"M\n" + + "\x1cSearchInviteReferrerResponse\x12-\n" + + "\ainviter\x18\x01 \x01(\v2\x13.hyapp.user.v1.UserR\ainviter\"\x85\x01\n" + + "\x19BindInviteReferrerRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1f\n" + + "\vinvite_code\x18\x03 \x01(\tR\n" + + "inviteCode\"\x81\x01\n" + + "\x1aBindInviteReferrerResponse\x124\n" + + "\x06invite\x18\x01 \x01(\v2\x1c.hyapp.user.v1.InviteBindingR\x06invite\x12-\n" + + "\ainviter\x18\x02 \x01(\v2\x13.hyapp.user.v1.UserR\ainviter\"\xac\x02\n" + + "\x14BindPushTokenRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1b\n" + + "\tdevice_id\x18\x03 \x01(\tR\bdeviceId\x12\x1d\n" + + "\n" + + "push_token\x18\x04 \x01(\tR\tpushToken\x12\x1a\n" + + "\bprovider\x18\x05 \x01(\tR\bprovider\x12\x1a\n" + + "\bplatform\x18\x06 \x01(\tR\bplatform\x12\x1f\n" + + "\vapp_version\x18\a \x01(\tR\n" + + "appVersion\x12\x1a\n" + + "\blanguage\x18\b \x01(\tR\blanguage\x12\x1a\n" + + "\btimezone\x18\t \x01(\tR\btimezone\"Q\n" + + "\x15BindPushTokenResponse\x12\x14\n" + + "\x05bound\x18\x01 \x01(\bR\x05bound\x12\"\n" + + "\rupdated_at_ms\x18\x02 \x01(\x03R\vupdatedAtMs\"\x9d\x01\n" + + "\x16DeletePushTokenRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1b\n" + + "\tdevice_id\x18\x03 \x01(\tR\bdeviceId\x12\x1d\n" + + "\n" + + "push_token\x18\x04 \x01(\tR\tpushToken\"W\n" + + "\x17DeletePushTokenResponse\x12\x18\n" + + "\adeleted\x18\x01 \x01(\bR\adeleted\x12\"\n" + + "\rupdated_at_ms\x18\x02 \x01(\x03R\vupdatedAtMs\"\xbe\x03\n" + + "\aCountry\x12\x1d\n" + + "\n" + + "country_id\x18\x01 \x01(\x03R\tcountryId\x12!\n" + + "\fcountry_name\x18\x02 \x01(\tR\vcountryName\x12!\n" + + "\fcountry_code\x18\x03 \x01(\tR\vcountryCode\x120\n" + + "\x14country_display_name\x18\x04 \x01(\tR\x12countryDisplayName\x12\x1d\n" + + "\n" + + "sort_order\x18\x06 \x01(\x05R\tsortOrder\x12\"\n" + + "\rcreated_at_ms\x18\a \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\b \x01(\x03R\vupdatedAtMs\x12\x1d\n" + + "\n" + + "iso_alpha3\x18\t \x01(\tR\tisoAlpha3\x12\x1f\n" + + "\viso_numeric\x18\n" + + " \x01(\tR\n" + + "isoNumeric\x12,\n" + + "\x12phone_country_code\x18\v \x01(\tR\x10phoneCountryCode\x12\x18\n" + + "\aenabled\x18\f \x01(\bR\aenabled\x12\x12\n" + + "\x04flag\x18\r \x01(\tR\x04flag\x12\x19\n" + + "\bapp_code\x18\x0e \x01(\tR\aappCode\"\x92\x02\n" + + "\x06Region\x12\x1b\n" + + "\tregion_id\x18\x01 \x01(\x03R\bregionId\x12\x1f\n" + + "\vregion_code\x18\x02 \x01(\tR\n" + + "regionCode\x12\x12\n" + + "\x04name\x18\x03 \x01(\tR\x04name\x12\x16\n" + + "\x06status\x18\x04 \x01(\tR\x06status\x12\x1c\n" + + "\tcountries\x18\x05 \x03(\tR\tcountries\x12\x1d\n" + + "\n" + + "sort_order\x18\x06 \x01(\x05R\tsortOrder\x12\"\n" + + "\rcreated_at_ms\x18\a \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\b \x01(\x03R\vupdatedAtMs\x12\x19\n" + + "\bapp_code\x18\t \x01(\tR\aappCode\"q\n" + + "\x14ListCountriesRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1d\n" + + "\aenabled\x18\x03 \x01(\bH\x00R\aenabled\x88\x01\x01B\n" + + "\n" + + "\b_enabled\"M\n" + + "\x15ListCountriesResponse\x124\n" + + "\tcountries\x18\x01 \x03(\v2\x16.hyapp.user.v1.CountryR\tcountries\"\x85\x03\n" + + "\x14UpdateCountryRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1d\n" + + "\n" + + "country_id\x18\x02 \x01(\x03R\tcountryId\x12!\n" + + "\fcountry_name\x18\x03 \x01(\tR\vcountryName\x120\n" + + "\x14country_display_name\x18\x04 \x01(\tR\x12countryDisplayName\x12\x1d\n" + + "\n" + + "sort_order\x18\x05 \x01(\x05R\tsortOrder\x12(\n" + + "\x10operator_user_id\x18\x06 \x01(\x03R\x0eoperatorUserId\x12\x1d\n" + + "\n" + + "iso_alpha3\x18\a \x01(\tR\tisoAlpha3\x12\x1f\n" + + "\viso_numeric\x18\b \x01(\tR\n" + + "isoNumeric\x12,\n" + + "\x12phone_country_code\x18\t \x01(\tR\x10phoneCountryCode\x12\x12\n" + + "\x04flag\x18\n" + + " \x01(\tR\x04flag\"C\n" + + "\x0fCountryResponse\x120\n" + + "\acountry\x18\x01 \x01(\v2\x16.hyapp.user.v1.CountryR\acountry\"R\n" + + " ListRegistrationCountriesRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\"Y\n" + + "!ListRegistrationCountriesResponse\x124\n" + + "\tcountries\x18\x01 \x03(\v2\x16.hyapp.user.v1.CountryR\tcountries\"z\n" + + "\x17LoginRiskBlockedCountry\x12!\n" + + "\fcountry_code\x18\x01 \x01(\tR\vcountryCode\x12\x18\n" + + "\akeyword\x18\x02 \x01(\tR\akeyword\x12\"\n" + + "\rupdated_at_ms\x18\x03 \x01(\x03R\vupdatedAtMs\"V\n" + + "$ListLoginRiskBlockedCountriesRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\"\x91\x01\n" + + "%ListLoginRiskBlockedCountriesResponse\x12D\n" + + "\tcountries\x18\x01 \x03(\v2&.hyapp.user.v1.LoginRiskBlockedCountryR\tcountries\x12\"\n" + + "\rupdated_at_ms\x18\x02 \x01(\x03R\vupdatedAtMs\"\\\n" + + "\x12ListRegionsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x16\n" + + "\x06status\x18\x02 \x01(\tR\x06status\"F\n" + + "\x13ListRegionsResponse\x12/\n" + + "\aregions\x18\x01 \x03(\v2\x15.hyapp.user.v1.RegionR\aregions\"_\n" + + "\x10GetRegionRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1b\n" + + "\tregion_id\x18\x02 \x01(\x03R\bregionId\"\xe0\x01\n" + + "\x13UpdateRegionRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1b\n" + + "\tregion_id\x18\x02 \x01(\x03R\bregionId\x12\x1f\n" + + "\vregion_code\x18\x03 \x01(\tR\n" + + "regionCode\x12\x12\n" + + "\x04name\x18\x04 \x01(\tR\x04name\x12\x1d\n" + + "\n" + + "sort_order\x18\x05 \x01(\x05R\tsortOrder\x12(\n" + + "\x10operator_user_id\x18\x06 \x01(\x03R\x0eoperatorUserId\"\xb4\x01\n" + + "\x1dReplaceRegionCountriesRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1b\n" + + "\tregion_id\x18\x02 \x01(\x03R\bregionId\x12\x1c\n" + + "\tcountries\x18\x03 \x03(\tR\tcountries\x12(\n" + + "\x10operator_user_id\x18\x04 \x01(\x03R\x0eoperatorUserId\"?\n" + + "\x0eRegionResponse\x12-\n" + + "\x06region\x18\x01 \x01(\v2\x15.hyapp.user.v1.RegionR\x06region\"\xfd\x02\n" + + "\fUserIdentity\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12&\n" + + "\x0fdisplay_user_id\x18\x02 \x01(\tR\rdisplayUserId\x12\x16\n" + + "\x06status\x18\x03 \x01(\tR\x06status\x125\n" + + "\x17default_display_user_id\x18\x04 \x01(\tR\x14defaultDisplayUserId\x12/\n" + + "\x14display_user_id_kind\x18\x05 \x01(\tR\x11displayUserIdKind\x12?\n" + + "\x1ddisplay_user_id_expires_at_ms\x18\x06 \x01(\x03R\x18displayUserIdExpiresAtMs\x12\x19\n" + + "\bapp_code\x18\a \x01(\tR\aappCode\x12\x1b\n" + + "\tpretty_id\x18\b \x01(\tR\bprettyId\x123\n" + + "\x16pretty_display_user_id\x18\t \x01(\tR\x13prettyDisplayUserId\"a\n" + + "\x16GetUserIdentityRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\"R\n" + + "\x17GetUserIdentityResponse\x127\n" + + "\bidentity\x18\x01 \x01(\v2\x1b.hyapp.user.v1.UserIdentityR\bidentity\"u\n" + + "\x1bResolveDisplayUserIDRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12&\n" + + "\x0fdisplay_user_id\x18\x02 \x01(\tR\rdisplayUserId\"W\n" + + "\x1cResolveDisplayUserIDResponse\x127\n" + + "\bidentity\x18\x01 \x01(\v2\x1b.hyapp.user.v1.UserIdentityR\bidentity\"\xd6\x01\n" + + "\x1aChangeDisplayUserIDRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12-\n" + + "\x13new_display_user_id\x18\x03 \x01(\tR\x10newDisplayUserId\x12\x16\n" + + "\x06reason\x18\x04 \x01(\tR\x06reason\x12(\n" + + "\x10operator_user_id\x18\x05 \x01(\x03R\x0eoperatorUserId\"V\n" + + "\x1bChangeDisplayUserIDResponse\x127\n" + + "\bidentity\x18\x01 \x01(\v2\x1b.hyapp.user.v1.UserIdentityR\bidentity\"\xf9\x01\n" + + "\x1fApplyPrettyDisplayUserIDRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x123\n" + + "\x16pretty_display_user_id\x18\x03 \x01(\tR\x13prettyDisplayUserId\x12*\n" + + "\x11lease_duration_ms\x18\x04 \x01(\x03R\x0fleaseDurationMs\x12,\n" + + "\x12payment_receipt_id\x18\x05 \x01(\tR\x10paymentReceiptId\"v\n" + + " ApplyPrettyDisplayUserIDResponse\x127\n" + + "\bidentity\x18\x01 \x01(\v2\x1b.hyapp.user.v1.UserIdentityR\bidentity\x12\x19\n" + + "\blease_id\x18\x02 \x01(\tR\aleaseId\"\x86\x01\n" + + " ExpirePrettyDisplayUserIDRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x19\n" + + "\blease_id\x18\x03 \x01(\tR\aleaseId\"\\\n" + + "!ExpirePrettyDisplayUserIDResponse\x127\n" + + "\bidentity\x18\x01 \x01(\v2\x1b.hyapp.user.v1.UserIdentityR\bidentity\"\xdc\x03\n" + + "\x13PrettyDisplayIDPool\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x17\n" + + "\apool_id\x18\x02 \x01(\tR\x06poolId\x12\x12\n" + + "\x04name\x18\x03 \x01(\tR\x04name\x12\x1f\n" + + "\vlevel_track\x18\x04 \x01(\tR\n" + + "levelTrack\x12\x1b\n" + + "\tmin_level\x18\x05 \x01(\x05R\bminLevel\x12\x1b\n" + + "\tmax_level\x18\x06 \x01(\x05R\bmaxLevel\x12\x1b\n" + + "\trule_type\x18\a \x01(\tR\bruleType\x12(\n" + + "\x10rule_config_json\x18\b \x01(\tR\x0eruleConfigJson\x12\x16\n" + + "\x06status\x18\t \x01(\tR\x06status\x12\x1d\n" + + "\n" + + "sort_order\x18\n" + + " \x01(\x05R\tsortOrder\x12-\n" + + "\x13created_by_admin_id\x18\v \x01(\x03R\x10createdByAdminId\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\"\xe0\x04\n" + + "\x0fPrettyDisplayID\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x1b\n" + + "\tpretty_id\x18\x02 \x01(\tR\bprettyId\x12\x17\n" + + "\apool_id\x18\x03 \x01(\tR\x06poolId\x12\x16\n" + + "\x06source\x18\x04 \x01(\tR\x06source\x12&\n" + + "\x0fdisplay_user_id\x18\x05 \x01(\tR\rdisplayUserId\x12\x16\n" + + "\x06status\x18\x06 \x01(\tR\x06status\x12(\n" + + "\x10assigned_user_id\x18\a \x01(\x03R\x0eassignedUserId\x12*\n" + + "\x11assigned_lease_id\x18\b \x01(\tR\x0fassignedLeaseId\x12$\n" + + "\x0eassigned_at_ms\x18\t \x01(\x03R\fassignedAtMs\x12$\n" + + "\x0ereleased_at_ms\x18\n" + + " \x01(\x03R\freleasedAtMs\x12%\n" + + "\x0erelease_reason\x18\v \x01(\tR\rreleaseReason\x12,\n" + + "\x12generated_batch_id\x18\f \x01(\tR\x10generatedBatchId\x12-\n" + + "\x13created_by_admin_id\x18\r \x01(\x03R\x10createdByAdminId\x12\"\n" + + "\rcreated_at_ms\x18\x0e \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x0f \x01(\x03R\vupdatedAtMs\x126\n" + + "\x04pool\x18\x10 \x01(\v2\".hyapp.user.v1.PrettyDisplayIDPoolR\x04pool\"\xe9\x03\n" + + "\x1ePrettyDisplayIDGenerationBatch\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x19\n" + + "\bbatch_id\x18\x02 \x01(\tR\abatchId\x12\x17\n" + + "\apool_id\x18\x03 \x01(\tR\x06poolId\x12\x1b\n" + + "\trule_type\x18\x04 \x01(\tR\bruleType\x12(\n" + + "\x10rule_config_json\x18\x05 \x01(\tR\x0eruleConfigJson\x12'\n" + + "\x0frequested_count\x18\x06 \x01(\x05R\x0erequestedCount\x12'\n" + + "\x0fgenerated_count\x18\a \x01(\x05R\x0egeneratedCount\x124\n" + + "\x16skipped_conflict_count\x18\b \x01(\x05R\x14skippedConflictCount\x12\x16\n" + + "\x06status\x18\t \x01(\tR\x06status\x12*\n" + + "\x11operator_admin_id\x18\n" + + " \x01(\x03R\x0foperatorAdminId\x12\x1d\n" + + "\n" + + "request_id\x18\v \x01(\tR\trequestId\x12\"\n" + + "\rcreated_at_ms\x18\f \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\r \x01(\x03R\vupdatedAtMs\"\xa0\x01\n" + + "$ListAvailablePrettyDisplayIDsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x12\n" + + "\x04page\x18\x03 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\x04 \x01(\x05R\bpageSize\"s\n" + + "%ListAvailablePrettyDisplayIDsResponse\x124\n" + + "\x05items\x18\x01 \x03(\v2\x1e.hyapp.user.v1.PrettyDisplayIDR\x05items\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\x8b\x01\n" + + "#ApplyPrettyDisplayIDFromPoolRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1b\n" + + "\tpretty_id\x18\x03 \x01(\tR\bprettyId\"\x97\x01\n" + + "$ApplyPrettyDisplayIDFromPoolResponse\x127\n" + + "\bidentity\x18\x01 \x01(\v2\x1b.hyapp.user.v1.UserIdentityR\bidentity\x12\x1b\n" + + "\tpretty_id\x18\x02 \x01(\tR\bprettyId\x12\x19\n" + + "\blease_id\x18\x03 \x01(\tR\aleaseId\"\xbb\x01\n" + + "\x1fListPrettyDisplayIDPoolsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x16\n" + + "\x06status\x18\x02 \x01(\tR\x06status\x12\x1f\n" + + "\vlevel_track\x18\x03 \x01(\tR\n" + + "levelTrack\x12\x12\n" + + "\x04page\x18\x04 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\x05 \x01(\x05R\bpageSize\"r\n" + + " ListPrettyDisplayIDPoolsResponse\x128\n" + + "\x05items\x18\x01 \x03(\v2\".hyapp.user.v1.PrettyDisplayIDPoolR\x05items\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\xeb\x02\n" + + " CreatePrettyDisplayIDPoolRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12\x1f\n" + + "\vlevel_track\x18\x03 \x01(\tR\n" + + "levelTrack\x12\x1b\n" + + "\tmin_level\x18\x04 \x01(\x05R\bminLevel\x12\x1b\n" + + "\tmax_level\x18\x05 \x01(\x05R\bmaxLevel\x12\x1b\n" + + "\trule_type\x18\x06 \x01(\tR\bruleType\x12(\n" + + "\x10rule_config_json\x18\a \x01(\tR\x0eruleConfigJson\x12\x16\n" + + "\x06status\x18\b \x01(\tR\x06status\x12\x1d\n" + + "\n" + + "sort_order\x18\t \x01(\x05R\tsortOrder\x12*\n" + + "\x11operator_admin_id\x18\n" + + " \x01(\x03R\x0foperatorAdminId\"\x84\x03\n" + + " UpdatePrettyDisplayIDPoolRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\apool_id\x18\x02 \x01(\tR\x06poolId\x12\x12\n" + + "\x04name\x18\x03 \x01(\tR\x04name\x12\x1f\n" + + "\vlevel_track\x18\x04 \x01(\tR\n" + + "levelTrack\x12\x1b\n" + + "\tmin_level\x18\x05 \x01(\x05R\bminLevel\x12\x1b\n" + + "\tmax_level\x18\x06 \x01(\x05R\bmaxLevel\x12\x1b\n" + + "\trule_type\x18\a \x01(\tR\bruleType\x12(\n" + + "\x10rule_config_json\x18\b \x01(\tR\x0eruleConfigJson\x12\x16\n" + + "\x06status\x18\t \x01(\tR\x06status\x12\x1d\n" + + "\n" + + "sort_order\x18\n" + + " \x01(\x05R\tsortOrder\x12*\n" + + "\x11operator_admin_id\x18\v \x01(\x03R\x0foperatorAdminId\"U\n" + + "\x1bPrettyDisplayIDPoolResponse\x126\n" + + "\x04pool\x18\x01 \x01(\v2\".hyapp.user.v1.PrettyDisplayIDPoolR\x04pool\"\xf3\x01\n" + + "\x1fGeneratePrettyDisplayIDsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\apool_id\x18\x02 \x01(\tR\x06poolId\x12\x1b\n" + + "\trule_type\x18\x03 \x01(\tR\bruleType\x12(\n" + + "\x10rule_config_json\x18\x04 \x01(\tR\x0eruleConfigJson\x12\x14\n" + + "\x05count\x18\x05 \x01(\x05R\x05count\x12*\n" + + "\x11operator_admin_id\x18\x06 \x01(\x03R\x0foperatorAdminId\"g\n" + + " GeneratePrettyDisplayIDsResponse\x12C\n" + + "\x05batch\x18\x01 \x01(\v2-.hyapp.user.v1.PrettyDisplayIDGenerationBatchR\x05batch\"\x8b\x02\n" + + "\x1bListPrettyDisplayIDsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + + "\apool_id\x18\x02 \x01(\tR\x06poolId\x12\x16\n" + + "\x06source\x18\x03 \x01(\tR\x06source\x12\x16\n" + + "\x06status\x18\x04 \x01(\tR\x06status\x12\x18\n" + + "\akeyword\x18\x05 \x01(\tR\akeyword\x12(\n" + + "\x10assigned_user_id\x18\x06 \x01(\x03R\x0eassignedUserId\x12\x12\n" + + "\x04page\x18\a \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\b \x01(\x05R\bpageSize\"j\n" + + "\x1cListPrettyDisplayIDsResponse\x124\n" + + "\x05items\x18\x01 \x03(\v2\x1e.hyapp.user.v1.PrettyDisplayIDR\x05items\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\xca\x01\n" + + "\x1fSetPrettyDisplayIDStatusRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1b\n" + + "\tpretty_id\x18\x02 \x01(\tR\bprettyId\x12\x16\n" + + "\x06status\x18\x03 \x01(\tR\x06status\x12*\n" + + "\x11operator_admin_id\x18\x04 \x01(\x03R\x0foperatorAdminId\x12\x16\n" + + "\x06reason\x18\x05 \x01(\tR\x06reason\"\xb0\x01\n" + + "\x1dRecyclePrettyDisplayIDRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1b\n" + + "\tpretty_id\x18\x02 \x01(\tR\bprettyId\x12\x16\n" + + "\x06reason\x18\x03 \x01(\tR\x06reason\x12*\n" + + "\x11operator_admin_id\x18\x04 \x01(\x03R\x0foperatorAdminId\"M\n" + + "\x17PrettyDisplayIDResponse\x122\n" + + "\x04item\x18\x01 \x01(\v2\x1e.hyapp.user.v1.PrettyDisplayIDR\x04item\"\x85\x02\n" + + " AdminGrantPrettyDisplayIDRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12$\n" + + "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12&\n" + + "\x0fdisplay_user_id\x18\x03 \x01(\tR\rdisplayUserId\x12\x1f\n" + + "\vduration_ms\x18\x04 \x01(\x03R\n" + + "durationMs\x12\x16\n" + + "\x06reason\x18\x05 \x01(\tR\x06reason\x12*\n" + + "\x11operator_admin_id\x18\x06 \x01(\x03R\x0foperatorAdminId\"\x94\x01\n" + + "!AdminGrantPrettyDisplayIDResponse\x127\n" + + "\bidentity\x18\x01 \x01(\v2\x1b.hyapp.user.v1.UserIdentityR\bidentity\x12\x1b\n" + + "\tpretty_id\x18\x02 \x01(\tR\bprettyId\x12\x19\n" + + "\blease_id\x18\x03 \x01(\tR\aleaseId\"\xf8\x01\n" + + "\x17CPFormationGiftFeedItem\x12!\n" + + "\fformation_id\x18\x01 \x01(\tR\vformationId\x12&\n" + + "\x0fgift_coin_value\x18\x02 \x01(\x03R\rgiftCoinValue\x12:\n" + + "\trequester\x18\x03 \x01(\v2\x1c.hyapp.user.v1.CPUserProfileR\trequester\x124\n" + + "\x06target\x18\x04 \x01(\v2\x1c.hyapp.user.v1.CPUserProfileR\x06target\x12 \n" + + "\fformed_at_ms\x18\x05 \x01(\x03R\n" + + "formedAtMs\"f\n" + + "\x1eListCPFormationGiftFeedRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x14\n" + + "\x05limit\x18\x02 \x01(\x05R\x05limit\"_\n" + + "\x1fListCPFormationGiftFeedResponse\x12<\n" + + "\x05items\x18\x01 \x03(\v2&.hyapp.user.v1.CPFormationGiftFeedItemR\x05items\"A\n" + + "\x0fListAppsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\":\n" + + "\x10ListAppsResponse\x12&\n" + + "\x04apps\x18\x01 \x03(\v2\x12.hyapp.user.v1.AppR\x04apps\"|\n" + + "!ResolveAdminUserIdentifierRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12'\n" + + "\x0fuser_identifier\x18\x02 \x01(\tR\x0euserIdentifier\"]\n" + + "\"ResolveAdminUserIdentifierResponse\x127\n" + + "\bidentity\x18\x01 \x01(\v2\x1b.hyapp.user.v1.UserIdentityR\bidentity*s\n" + + "\n" + + "UserStatus\x12\x1b\n" + + "\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\xac\x15\n" + + "\vUserService\x12H\n" + + "\aGetUser\x12\x1d.hyapp.user.v1.GetUserRequest\x1a\x1e.hyapp.user.v1.GetUserResponse\x12o\n" + + "\x14GetInviteAttribution\x12*.hyapp.user.v1.GetInviteAttributionRequest\x1a+.hyapp.user.v1.GetInviteAttributionResponse\x12i\n" + + "\x12BusinessUserLookup\x12(.hyapp.user.v1.BusinessUserLookupRequest\x1a).hyapp.user.v1.BusinessUserLookupResponse\x12f\n" + + "\x11GetMyProfileStats\x12'.hyapp.user.v1.GetMyProfileStatsRequest\x1a(.hyapp.user.v1.GetMyProfileStatsResponse\x12Z\n" + + "\rBatchGetUsers\x12#.hyapp.user.v1.BatchGetUsersRequest\x1a$.hyapp.user.v1.BatchGetUsersResponse\x12~\n" + + "\x19BatchGetUserAdminProfiles\x12/.hyapp.user.v1.BatchGetUserAdminProfilesRequest\x1a0.hyapp.user.v1.BatchGetUserAdminProfilesResponse\x12~\n" + + "\x19AdminIssueUserAccessToken\x12/.hyapp.user.v1.AdminIssueUserAccessTokenRequest\x1a0.hyapp.user.v1.AdminIssueUserAccessTokenResponse\x12u\n" + + "\x16BatchGetRoomBasicUsers\x12,.hyapp.user.v1.BatchGetRoomBasicUsersRequest\x1a-.hyapp.user.v1.BatchGetRoomBasicUsersResponse\x12T\n" + + "\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\x12\x84\x01\n" + + "\x1bUpdateUserProfileBackground\x121.hyapp.user.v1.UpdateUserProfileBackgroundRequest\x1a2.hyapp.user.v1.UpdateUserProfileBackgroundResponse\x12r\n" + + "\x15UpdateUserContactInfo\x12+.hyapp.user.v1.UpdateUserContactInfoRequest\x1a,.hyapp.user.v1.UpdateUserContactInfoResponse\x12~\n" + + "\x19UpdateUserWithdrawAddress\x12/.hyapp.user.v1.UpdateUserWithdrawAddressRequest\x1a0.hyapp.user.v1.UpdateUserWithdrawAddressResponse\x12f\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\x12W\n" + + "\fAdminBanUser\x12\".hyapp.user.v1.AdminBanUserRequest\x1a#.hyapp.user.v1.AdminBanUserResponse\x12]\n" + + "\x0eAdminUnbanUser\x12$.hyapp.user.v1.AdminUnbanUserRequest\x1a%.hyapp.user.v1.AdminUnbanUserResponse\x12u\n" + + "\x16CreateManagerUserBlock\x12,.hyapp.user.v1.CreateManagerUserBlockRequest\x1a-.hyapp.user.v1.CreateManagerUserBlockResponse\x12r\n" + + "\x15ListManagerUserBlocks\x12+.hyapp.user.v1.ListManagerUserBlocksRequest\x1a,.hyapp.user.v1.ListManagerUserBlocksResponse\x12i\n" + + "\x12UnblockManagerUser\x12(.hyapp.user.v1.UnblockManagerUserRequest\x1a).hyapp.user.v1.UnblockManagerUserResponse\x12i\n" + + "\x12CompleteOnboarding\x12(.hyapp.user.v1.CompleteOnboardingRequest\x1a).hyapp.user.v1.CompleteOnboardingResponse\x12o\n" + + "\x14SearchInviteReferrer\x12*.hyapp.user.v1.SearchInviteReferrerRequest\x1a+.hyapp.user.v1.SearchInviteReferrerResponse\x12i\n" + + "\x12BindInviteReferrer\x12(.hyapp.user.v1.BindInviteReferrerRequest\x1a).hyapp.user.v1.BindInviteReferrerResponse2\xc3\b\n" + + "\x11UserSocialService\x12i\n" + + "\x12RecordProfileVisit\x12(.hyapp.user.v1.RecordProfileVisitRequest\x1a).hyapp.user.v1.RecordProfileVisitResponse\x12l\n" + + "\x13ListProfileVisitors\x12).hyapp.user.v1.ListProfileVisitorsRequest\x1a*.hyapp.user.v1.ListProfileVisitorsResponse\x12Q\n" + + "\n" + + "FollowUser\x12 .hyapp.user.v1.FollowUserRequest\x1a!.hyapp.user.v1.FollowUserResponse\x12W\n" + + "\fUnfollowUser\x12\".hyapp.user.v1.UnfollowUserRequest\x1a#.hyapp.user.v1.UnfollowUserResponse\x12Z\n" + + "\rListFollowing\x12#.hyapp.user.v1.ListFollowingRequest\x1a$.hyapp.user.v1.ListFollowingResponse\x12T\n" + + "\vApplyFriend\x12!.hyapp.user.v1.ApplyFriendRequest\x1a\".hyapp.user.v1.ApplyFriendResponse\x12x\n" + + "\x17AcceptFriendApplication\x12-.hyapp.user.v1.AcceptFriendApplicationRequest\x1a..hyapp.user.v1.AcceptFriendApplicationResponse\x12W\n" + + "\fDeleteFriend\x12\".hyapp.user.v1.DeleteFriendRequest\x1a#.hyapp.user.v1.DeleteFriendResponse\x12T\n" + + "\vListFriends\x12!.hyapp.user.v1.ListFriendsRequest\x1a\".hyapp.user.v1.ListFriendsResponse\x12u\n" + + "\x16ListFriendApplications\x12,.hyapp.user.v1.ListFriendApplicationsRequest\x1a-.hyapp.user.v1.ListFriendApplicationsResponse\x12W\n" + + "\fSubmitReport\x12\".hyapp.user.v1.SubmitReportRequest\x1a#.hyapp.user.v1.SubmitReportResponse2\xc6\b\n" + + "\rUserCPService\x12i\n" + + "\x12ListCPApplications\x12(.hyapp.user.v1.ListCPApplicationsRequest\x1a).hyapp.user.v1.ListCPApplicationsResponse\x12l\n" + + "\x13AcceptCPApplication\x12).hyapp.user.v1.AcceptCPApplicationRequest\x1a*.hyapp.user.v1.AcceptCPApplicationResponse\x12l\n" + + "\x13RejectCPApplication\x12).hyapp.user.v1.RejectCPApplicationRequest\x1a*.hyapp.user.v1.RejectCPApplicationResponse\x12l\n" + + "\x13ListCPRelationships\x12).hyapp.user.v1.ListCPRelationshipsRequest\x1a*.hyapp.user.v1.ListCPRelationshipsResponse\x12~\n" + + "\x19ListCPIntimacyLeaderboard\x12/.hyapp.user.v1.ListCPIntimacyLeaderboardRequest\x1a0.hyapp.user.v1.ListCPIntimacyLeaderboardResponse\x12\x81\x01\n" + + "\x1aPrepareBreakCPRelationship\x120.hyapp.user.v1.PrepareBreakCPRelationshipRequest\x1a1.hyapp.user.v1.PrepareBreakCPRelationshipResponse\x12\x81\x01\n" + + "\x1aConfirmBreakCPRelationship\x120.hyapp.user.v1.ConfirmBreakCPRelationshipRequest\x1a1.hyapp.user.v1.ConfirmBreakCPRelationshipResponse\x12~\n" + + "\x19CancelBreakCPRelationship\x12/.hyapp.user.v1.CancelBreakCPRelationshipRequest\x1a0.hyapp.user.v1.CancelBreakCPRelationshipResponse\x12x\n" + + "\x17ListCPFormationGiftFeed\x12-.hyapp.user.v1.ListCPFormationGiftFeedRequest\x1a..hyapp.user.v1.ListCPFormationGiftFeedResponse2\x88\x02\n" + + "\x15UserCPInternalService\x12u\n" + + "\x16ConsumeRoomGiftCPEvent\x12,.hyapp.user.v1.ConsumeRoomGiftCPEventRequest\x1a-.hyapp.user.v1.ConsumeRoomGiftCPEventResponse\x12x\n" + + "\x17ListCPWeeklyRankEntries\x12-.hyapp.user.v1.ListCPWeeklyRankEntriesRequest\x1a..hyapp.user.v1.ListCPWeeklyRankEntriesResponse2\xab\x05\n" + + "\x0fUserCronService\x12\\\n" + + "\x17ProcessLoginIPRiskBatch\x12\x1f.hyapp.user.v1.CronBatchRequest\x1a .hyapp.user.v1.CronBatchResponse\x12^\n" + + "\x19ProcessRegionRebuildBatch\x12\x1f.hyapp.user.v1.CronBatchRequest\x1a .hyapp.user.v1.CronBatchResponse\x12^\n" + + "\x19CompensateMicOpenSessions\x12\x1f.hyapp.user.v1.CronBatchRequest\x1a .hyapp.user.v1.CronBatchResponse\x12_\n" + + "\x1aCompensateRoomOpenSessions\x12\x1f.hyapp.user.v1.CronBatchRequest\x1a .hyapp.user.v1.CronBatchResponse\x12\\\n" + + "\x17ExpireManagerUserBlocks\x12\x1f.hyapp.user.v1.CronBatchRequest\x1a .hyapp.user.v1.CronBatchResponse\x12X\n" + + "\x13ExpireAdminUserBans\x12\x1f.hyapp.user.v1.CronBatchRequest\x1a .hyapp.user.v1.CronBatchResponse\x12a\n" + + "\x1cRefreshCPIntimacyLeaderboard\x12\x1f.hyapp.user.v1.CronBatchRequest\x1a .hyapp.user.v1.CronBatchResponse2\xd1\x01\n" + + "\x11UserDeviceService\x12Z\n" + + "\rBindPushToken\x12#.hyapp.user.v1.BindPushTokenRequest\x1a$.hyapp.user.v1.BindPushTokenResponse\x12`\n" + + "\x0fDeletePushToken\x12%.hyapp.user.v1.DeletePushTokenRequest\x1a&.hyapp.user.v1.DeletePushTokenResponse2\xb4\x01\n" + + "\x12AppRegistryService\x12Q\n" + + "\n" + + "ResolveApp\x12 .hyapp.user.v1.ResolveAppRequest\x1a!.hyapp.user.v1.ResolveAppResponse\x12K\n" + + "\bListApps\x12\x1e.hyapp.user.v1.ListAppsRequest\x1a\x1f.hyapp.user.v1.ListAppsResponse2\xc7\x01\n" + + "\x13CountryAdminService\x12Z\n" + + "\rListCountries\x12#.hyapp.user.v1.ListCountriesRequest\x1a$.hyapp.user.v1.ListCountriesResponse\x12T\n" + + "\rUpdateCountry\x12#.hyapp.user.v1.UpdateCountryRequest\x1a\x1e.hyapp.user.v1.CountryResponse2\xa2\x02\n" + + "\x13CountryQueryService\x12~\n" + + "\x19ListRegistrationCountries\x12/.hyapp.user.v1.ListRegistrationCountriesRequest\x1a0.hyapp.user.v1.ListRegistrationCountriesResponse\x12\x8a\x01\n" + + "\x1dListLoginRiskBlockedCountries\x123.hyapp.user.v1.ListLoginRiskBlockedCountriesRequest\x1a4.hyapp.user.v1.ListLoginRiskBlockedCountriesResponse2\xf1\x02\n" + + "\x12RegionAdminService\x12T\n" + + "\vListRegions\x12!.hyapp.user.v1.ListRegionsRequest\x1a\".hyapp.user.v1.ListRegionsResponse\x12K\n" + + "\tGetRegion\x12\x1f.hyapp.user.v1.GetRegionRequest\x1a\x1d.hyapp.user.v1.RegionResponse\x12Q\n" + + "\fUpdateRegion\x12\".hyapp.user.v1.UpdateRegionRequest\x1a\x1d.hyapp.user.v1.RegionResponse\x12e\n" + + "\x16ReplaceRegionCountries\x12,.hyapp.user.v1.ReplaceRegionCountriesRequest\x1a\x1d.hyapp.user.v1.RegionResponse2\xee\a\n" + + "\x13UserIdentityService\x12`\n" + + "\x0fGetUserIdentity\x12%.hyapp.user.v1.GetUserIdentityRequest\x1a&.hyapp.user.v1.GetUserIdentityResponse\x12o\n" + + "\x14ResolveDisplayUserID\x12*.hyapp.user.v1.ResolveDisplayUserIDRequest\x1a+.hyapp.user.v1.ResolveDisplayUserIDResponse\x12\x81\x01\n" + + "\x1aResolveAdminUserIdentifier\x120.hyapp.user.v1.ResolveAdminUserIdentifierRequest\x1a1.hyapp.user.v1.ResolveAdminUserIdentifierResponse\x12l\n" + + "\x13ChangeDisplayUserID\x12).hyapp.user.v1.ChangeDisplayUserIDRequest\x1a*.hyapp.user.v1.ChangeDisplayUserIDResponse\x12{\n" + + "\x18ApplyPrettyDisplayUserID\x12..hyapp.user.v1.ApplyPrettyDisplayUserIDRequest\x1a/.hyapp.user.v1.ApplyPrettyDisplayUserIDResponse\x12\x8a\x01\n" + + "\x1dListAvailablePrettyDisplayIDs\x123.hyapp.user.v1.ListAvailablePrettyDisplayIDsRequest\x1a4.hyapp.user.v1.ListAvailablePrettyDisplayIDsResponse\x12\x87\x01\n" + + "\x1cApplyPrettyDisplayIDFromPool\x122.hyapp.user.v1.ApplyPrettyDisplayIDFromPoolRequest\x1a3.hyapp.user.v1.ApplyPrettyDisplayIDFromPoolResponse\x12~\n" + + "\x19ExpirePrettyDisplayUserID\x12/.hyapp.user.v1.ExpirePrettyDisplayUserIDRequest\x1a0.hyapp.user.v1.ExpirePrettyDisplayUserIDResponse2\xe4\a\n" + + "\x1fUserPrettyDisplayIDAdminService\x12{\n" + + "\x18ListPrettyDisplayIDPools\x12..hyapp.user.v1.ListPrettyDisplayIDPoolsRequest\x1a/.hyapp.user.v1.ListPrettyDisplayIDPoolsResponse\x12x\n" + + "\x19CreatePrettyDisplayIDPool\x12/.hyapp.user.v1.CreatePrettyDisplayIDPoolRequest\x1a*.hyapp.user.v1.PrettyDisplayIDPoolResponse\x12x\n" + + "\x19UpdatePrettyDisplayIDPool\x12/.hyapp.user.v1.UpdatePrettyDisplayIDPoolRequest\x1a*.hyapp.user.v1.PrettyDisplayIDPoolResponse\x12{\n" + + "\x18GeneratePrettyDisplayIDs\x12..hyapp.user.v1.GeneratePrettyDisplayIDsRequest\x1a/.hyapp.user.v1.GeneratePrettyDisplayIDsResponse\x12o\n" + + "\x14ListPrettyDisplayIDs\x12*.hyapp.user.v1.ListPrettyDisplayIDsRequest\x1a+.hyapp.user.v1.ListPrettyDisplayIDsResponse\x12r\n" + + "\x18SetPrettyDisplayIDStatus\x12..hyapp.user.v1.SetPrettyDisplayIDStatusRequest\x1a&.hyapp.user.v1.PrettyDisplayIDResponse\x12n\n" + + "\x16RecyclePrettyDisplayID\x12,.hyapp.user.v1.RecyclePrettyDisplayIDRequest\x1a&.hyapp.user.v1.PrettyDisplayIDResponse\x12~\n" + + "\x19AdminGrantPrettyDisplayID\x12/.hyapp.user.v1.AdminGrantPrettyDisplayIDRequest\x1a0.hyapp.user.v1.AdminGrantPrettyDisplayIDResponseB&Z$hyapp.local/api/proto/user/v1;userv1b\x06proto3" var ( file_proto_user_v1_user_proto_rawDescOnce sync.Once - file_proto_user_v1_user_proto_rawDescData = file_proto_user_v1_user_proto_rawDesc + file_proto_user_v1_user_proto_rawDescData []byte ) func file_proto_user_v1_user_proto_rawDescGZIP() []byte { file_proto_user_v1_user_proto_rawDescOnce.Do(func() { - file_proto_user_v1_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_user_v1_user_proto_rawDescData) + file_proto_user_v1_user_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_user_v1_user_proto_rawDesc), len(file_proto_user_v1_user_proto_rawDesc))) }) return file_proto_user_v1_user_proto_rawDescData } var file_proto_user_v1_user_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_proto_user_v1_user_proto_msgTypes = make([]protoimpl.MessageInfo, 184) +var file_proto_user_v1_user_proto_msgTypes = make([]protoimpl.MessageInfo, 187) var file_proto_user_v1_user_proto_goTypes = []any{ (UserStatus)(0), // 0: hyapp.user.v1.UserStatus (*RequestMeta)(nil), // 1: hyapp.user.v1.RequestMeta @@ -16490,13 +14878,16 @@ var file_proto_user_v1_user_proto_goTypes = []any{ (*PrettyDisplayIDResponse)(nil), // 175: hyapp.user.v1.PrettyDisplayIDResponse (*AdminGrantPrettyDisplayIDRequest)(nil), // 176: hyapp.user.v1.AdminGrantPrettyDisplayIDRequest (*AdminGrantPrettyDisplayIDResponse)(nil), // 177: hyapp.user.v1.AdminGrantPrettyDisplayIDResponse - (*ListAppsRequest)(nil), // 178: hyapp.user.v1.ListAppsRequest - (*ListAppsResponse)(nil), // 179: hyapp.user.v1.ListAppsResponse - (*ResolveAdminUserIdentifierRequest)(nil), // 180: hyapp.user.v1.ResolveAdminUserIdentifierRequest - (*ResolveAdminUserIdentifierResponse)(nil), // 181: hyapp.user.v1.ResolveAdminUserIdentifierResponse - nil, // 182: hyapp.user.v1.BatchGetUsersResponse.UsersEntry - nil, // 183: hyapp.user.v1.BatchGetUserAdminProfilesResponse.ProfilesEntry - nil, // 184: hyapp.user.v1.BatchGetRoomBasicUsersResponse.UsersEntry + (*CPFormationGiftFeedItem)(nil), // 178: hyapp.user.v1.CPFormationGiftFeedItem + (*ListCPFormationGiftFeedRequest)(nil), // 179: hyapp.user.v1.ListCPFormationGiftFeedRequest + (*ListCPFormationGiftFeedResponse)(nil), // 180: hyapp.user.v1.ListCPFormationGiftFeedResponse + (*ListAppsRequest)(nil), // 181: hyapp.user.v1.ListAppsRequest + (*ListAppsResponse)(nil), // 182: hyapp.user.v1.ListAppsResponse + (*ResolveAdminUserIdentifierRequest)(nil), // 183: hyapp.user.v1.ResolveAdminUserIdentifierRequest + (*ResolveAdminUserIdentifierResponse)(nil), // 184: hyapp.user.v1.ResolveAdminUserIdentifierResponse + nil, // 185: hyapp.user.v1.BatchGetUsersResponse.UsersEntry + nil, // 186: hyapp.user.v1.BatchGetUserAdminProfilesResponse.ProfilesEntry + nil, // 187: hyapp.user.v1.BatchGetRoomBasicUsersResponse.UsersEntry } var file_proto_user_v1_user_proto_depIdxs = []int32{ 1, // 0: hyapp.user.v1.ResolveAppRequest.meta:type_name -> hyapp.user.v1.RequestMeta @@ -16570,15 +14961,15 @@ var file_proto_user_v1_user_proto_depIdxs = []int32{ 1, // 68: hyapp.user.v1.SubmitReportRequest.meta:type_name -> hyapp.user.v1.RequestMeta 78, // 69: hyapp.user.v1.SubmitReportResponse.report:type_name -> hyapp.user.v1.UserReport 1, // 70: hyapp.user.v1.BatchGetUsersRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 182, // 71: hyapp.user.v1.BatchGetUsersResponse.users:type_name -> hyapp.user.v1.BatchGetUsersResponse.UsersEntry + 185, // 71: hyapp.user.v1.BatchGetUsersResponse.users:type_name -> hyapp.user.v1.BatchGetUsersResponse.UsersEntry 0, // 72: hyapp.user.v1.ActiveUserBanSummary.user_status:type_name -> hyapp.user.v1.UserStatus 5, // 73: hyapp.user.v1.UserAdminProfile.user:type_name -> hyapp.user.v1.User 83, // 74: hyapp.user.v1.UserAdminProfile.ban:type_name -> hyapp.user.v1.ActiveUserBanSummary 1, // 75: hyapp.user.v1.BatchGetUserAdminProfilesRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 183, // 76: hyapp.user.v1.BatchGetUserAdminProfilesResponse.profiles:type_name -> hyapp.user.v1.BatchGetUserAdminProfilesResponse.ProfilesEntry + 186, // 76: hyapp.user.v1.BatchGetUserAdminProfilesResponse.profiles:type_name -> hyapp.user.v1.BatchGetUserAdminProfilesResponse.ProfilesEntry 1, // 77: hyapp.user.v1.AdminIssueUserAccessTokenRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 78: hyapp.user.v1.BatchGetRoomBasicUsersRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 184, // 79: hyapp.user.v1.BatchGetRoomBasicUsersResponse.users:type_name -> hyapp.user.v1.BatchGetRoomBasicUsersResponse.UsersEntry + 187, // 79: hyapp.user.v1.BatchGetRoomBasicUsersResponse.users:type_name -> hyapp.user.v1.BatchGetRoomBasicUsersResponse.UsersEntry 1, // 80: hyapp.user.v1.ListUserIDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 81: hyapp.user.v1.UpdateUserProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta 5, // 82: hyapp.user.v1.UpdateUserProfileResponse.user:type_name -> hyapp.user.v1.User @@ -16662,180 +15053,186 @@ var file_proto_user_v1_user_proto_depIdxs = []int32{ 158, // 160: hyapp.user.v1.PrettyDisplayIDResponse.item:type_name -> hyapp.user.v1.PrettyDisplayID 1, // 161: hyapp.user.v1.AdminGrantPrettyDisplayIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta 146, // 162: hyapp.user.v1.AdminGrantPrettyDisplayIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity - 1, // 163: hyapp.user.v1.ListAppsRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 2, // 164: hyapp.user.v1.ListAppsResponse.apps:type_name -> hyapp.user.v1.App - 1, // 165: hyapp.user.v1.ResolveAdminUserIdentifierRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 146, // 166: hyapp.user.v1.ResolveAdminUserIdentifierResponse.identity:type_name -> hyapp.user.v1.UserIdentity - 5, // 167: hyapp.user.v1.BatchGetUsersResponse.UsersEntry.value:type_name -> hyapp.user.v1.User - 84, // 168: hyapp.user.v1.BatchGetUserAdminProfilesResponse.ProfilesEntry.value:type_name -> hyapp.user.v1.UserAdminProfile - 89, // 169: hyapp.user.v1.BatchGetRoomBasicUsersResponse.UsersEntry.value:type_name -> hyapp.user.v1.RoomBasicUser - 17, // 170: hyapp.user.v1.UserService.GetUser:input_type -> hyapp.user.v1.GetUserRequest - 9, // 171: hyapp.user.v1.UserService.GetInviteAttribution:input_type -> hyapp.user.v1.GetInviteAttributionRequest - 19, // 172: hyapp.user.v1.UserService.BusinessUserLookup:input_type -> hyapp.user.v1.BusinessUserLookupRequest - 23, // 173: hyapp.user.v1.UserService.GetMyProfileStats:input_type -> hyapp.user.v1.GetMyProfileStatsRequest - 81, // 174: hyapp.user.v1.UserService.BatchGetUsers:input_type -> hyapp.user.v1.BatchGetUsersRequest - 85, // 175: hyapp.user.v1.UserService.BatchGetUserAdminProfiles:input_type -> hyapp.user.v1.BatchGetUserAdminProfilesRequest - 87, // 176: hyapp.user.v1.UserService.AdminIssueUserAccessToken:input_type -> hyapp.user.v1.AdminIssueUserAccessTokenRequest - 90, // 177: hyapp.user.v1.UserService.BatchGetRoomBasicUsers:input_type -> hyapp.user.v1.BatchGetRoomBasicUsersRequest - 92, // 178: hyapp.user.v1.UserService.ListUserIDs:input_type -> hyapp.user.v1.ListUserIDsRequest - 12, // 179: hyapp.user.v1.UserService.GetUserMicLifetimeStats:input_type -> hyapp.user.v1.GetUserMicLifetimeStatsRequest - 94, // 180: hyapp.user.v1.UserService.UpdateUserProfile:input_type -> hyapp.user.v1.UpdateUserProfileRequest - 96, // 181: hyapp.user.v1.UserService.UpdateUserProfileBackground:input_type -> hyapp.user.v1.UpdateUserProfileBackgroundRequest - 98, // 182: hyapp.user.v1.UserService.UpdateUserContactInfo:input_type -> hyapp.user.v1.UpdateUserContactInfoRequest - 100, // 183: hyapp.user.v1.UserService.UpdateUserWithdrawAddress:input_type -> hyapp.user.v1.UpdateUserWithdrawAddressRequest - 102, // 184: hyapp.user.v1.UserService.ChangeUserCountry:input_type -> hyapp.user.v1.ChangeUserCountryRequest - 103, // 185: hyapp.user.v1.UserService.AdminChangeUserCountry:input_type -> hyapp.user.v1.AdminChangeUserCountryRequest - 105, // 186: hyapp.user.v1.UserService.SetUserStatus:input_type -> hyapp.user.v1.SetUserStatusRequest - 108, // 187: hyapp.user.v1.UserService.AdminBanUser:input_type -> hyapp.user.v1.AdminBanUserRequest - 110, // 188: hyapp.user.v1.UserService.AdminUnbanUser:input_type -> hyapp.user.v1.AdminUnbanUserRequest - 113, // 189: hyapp.user.v1.UserService.CreateManagerUserBlock:input_type -> hyapp.user.v1.CreateManagerUserBlockRequest - 115, // 190: hyapp.user.v1.UserService.ListManagerUserBlocks:input_type -> hyapp.user.v1.ListManagerUserBlocksRequest - 117, // 191: hyapp.user.v1.UserService.UnblockManagerUser:input_type -> hyapp.user.v1.UnblockManagerUserRequest - 119, // 192: hyapp.user.v1.UserService.CompleteOnboarding:input_type -> hyapp.user.v1.CompleteOnboardingRequest - 121, // 193: hyapp.user.v1.UserService.SearchInviteReferrer:input_type -> hyapp.user.v1.SearchInviteReferrerRequest - 123, // 194: hyapp.user.v1.UserService.BindInviteReferrer:input_type -> hyapp.user.v1.BindInviteReferrerRequest - 25, // 195: hyapp.user.v1.UserSocialService.RecordProfileVisit:input_type -> hyapp.user.v1.RecordProfileVisitRequest - 28, // 196: hyapp.user.v1.UserSocialService.ListProfileVisitors:input_type -> hyapp.user.v1.ListProfileVisitorsRequest - 30, // 197: hyapp.user.v1.UserSocialService.FollowUser:input_type -> hyapp.user.v1.FollowUserRequest - 32, // 198: hyapp.user.v1.UserSocialService.UnfollowUser:input_type -> hyapp.user.v1.UnfollowUserRequest - 35, // 199: hyapp.user.v1.UserSocialService.ListFollowing:input_type -> hyapp.user.v1.ListFollowingRequest - 37, // 200: hyapp.user.v1.UserSocialService.ApplyFriend:input_type -> hyapp.user.v1.ApplyFriendRequest - 39, // 201: hyapp.user.v1.UserSocialService.AcceptFriendApplication:input_type -> hyapp.user.v1.AcceptFriendApplicationRequest - 41, // 202: hyapp.user.v1.UserSocialService.DeleteFriend:input_type -> hyapp.user.v1.DeleteFriendRequest - 44, // 203: hyapp.user.v1.UserSocialService.ListFriends:input_type -> hyapp.user.v1.ListFriendsRequest - 47, // 204: hyapp.user.v1.UserSocialService.ListFriendApplications:input_type -> hyapp.user.v1.ListFriendApplicationsRequest - 79, // 205: hyapp.user.v1.UserSocialService.SubmitReport:input_type -> hyapp.user.v1.SubmitReportRequest - 59, // 206: hyapp.user.v1.UserCPService.ListCPApplications:input_type -> hyapp.user.v1.ListCPApplicationsRequest - 61, // 207: hyapp.user.v1.UserCPService.AcceptCPApplication:input_type -> hyapp.user.v1.AcceptCPApplicationRequest - 63, // 208: hyapp.user.v1.UserCPService.RejectCPApplication:input_type -> hyapp.user.v1.RejectCPApplicationRequest - 65, // 209: hyapp.user.v1.UserCPService.ListCPRelationships:input_type -> hyapp.user.v1.ListCPRelationshipsRequest - 67, // 210: hyapp.user.v1.UserCPService.ListCPIntimacyLeaderboard:input_type -> hyapp.user.v1.ListCPIntimacyLeaderboardRequest - 69, // 211: hyapp.user.v1.UserCPService.PrepareBreakCPRelationship:input_type -> hyapp.user.v1.PrepareBreakCPRelationshipRequest - 71, // 212: hyapp.user.v1.UserCPService.ConfirmBreakCPRelationship:input_type -> hyapp.user.v1.ConfirmBreakCPRelationshipRequest - 73, // 213: hyapp.user.v1.UserCPService.CancelBreakCPRelationship:input_type -> hyapp.user.v1.CancelBreakCPRelationshipRequest - 76, // 214: hyapp.user.v1.UserCPInternalService.ConsumeRoomGiftCPEvent:input_type -> hyapp.user.v1.ConsumeRoomGiftCPEventRequest - 57, // 215: hyapp.user.v1.UserCPInternalService.ListCPWeeklyRankEntries:input_type -> hyapp.user.v1.ListCPWeeklyRankEntriesRequest - 14, // 216: hyapp.user.v1.UserCronService.ProcessLoginIPRiskBatch:input_type -> hyapp.user.v1.CronBatchRequest - 14, // 217: hyapp.user.v1.UserCronService.ProcessRegionRebuildBatch:input_type -> hyapp.user.v1.CronBatchRequest - 14, // 218: hyapp.user.v1.UserCronService.CompensateMicOpenSessions:input_type -> hyapp.user.v1.CronBatchRequest - 14, // 219: hyapp.user.v1.UserCronService.CompensateRoomOpenSessions:input_type -> hyapp.user.v1.CronBatchRequest - 14, // 220: hyapp.user.v1.UserCronService.ExpireManagerUserBlocks:input_type -> hyapp.user.v1.CronBatchRequest - 14, // 221: hyapp.user.v1.UserCronService.ExpireAdminUserBans:input_type -> hyapp.user.v1.CronBatchRequest - 14, // 222: hyapp.user.v1.UserCronService.RefreshCPIntimacyLeaderboard:input_type -> hyapp.user.v1.CronBatchRequest - 125, // 223: hyapp.user.v1.UserDeviceService.BindPushToken:input_type -> hyapp.user.v1.BindPushTokenRequest - 127, // 224: hyapp.user.v1.UserDeviceService.DeletePushToken:input_type -> hyapp.user.v1.DeletePushTokenRequest - 3, // 225: hyapp.user.v1.AppRegistryService.ResolveApp:input_type -> hyapp.user.v1.ResolveAppRequest - 178, // 226: hyapp.user.v1.AppRegistryService.ListApps:input_type -> hyapp.user.v1.ListAppsRequest - 131, // 227: hyapp.user.v1.CountryAdminService.ListCountries:input_type -> hyapp.user.v1.ListCountriesRequest - 133, // 228: hyapp.user.v1.CountryAdminService.UpdateCountry:input_type -> hyapp.user.v1.UpdateCountryRequest - 135, // 229: hyapp.user.v1.CountryQueryService.ListRegistrationCountries:input_type -> hyapp.user.v1.ListRegistrationCountriesRequest - 138, // 230: hyapp.user.v1.CountryQueryService.ListLoginRiskBlockedCountries:input_type -> hyapp.user.v1.ListLoginRiskBlockedCountriesRequest - 140, // 231: hyapp.user.v1.RegionAdminService.ListRegions:input_type -> hyapp.user.v1.ListRegionsRequest - 142, // 232: hyapp.user.v1.RegionAdminService.GetRegion:input_type -> hyapp.user.v1.GetRegionRequest - 143, // 233: hyapp.user.v1.RegionAdminService.UpdateRegion:input_type -> hyapp.user.v1.UpdateRegionRequest - 144, // 234: hyapp.user.v1.RegionAdminService.ReplaceRegionCountries:input_type -> hyapp.user.v1.ReplaceRegionCountriesRequest - 147, // 235: hyapp.user.v1.UserIdentityService.GetUserIdentity:input_type -> hyapp.user.v1.GetUserIdentityRequest - 149, // 236: hyapp.user.v1.UserIdentityService.ResolveDisplayUserID:input_type -> hyapp.user.v1.ResolveDisplayUserIDRequest - 180, // 237: hyapp.user.v1.UserIdentityService.ResolveAdminUserIdentifier:input_type -> hyapp.user.v1.ResolveAdminUserIdentifierRequest - 151, // 238: hyapp.user.v1.UserIdentityService.ChangeDisplayUserID:input_type -> hyapp.user.v1.ChangeDisplayUserIDRequest - 153, // 239: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayUserID:input_type -> hyapp.user.v1.ApplyPrettyDisplayUserIDRequest - 160, // 240: hyapp.user.v1.UserIdentityService.ListAvailablePrettyDisplayIDs:input_type -> hyapp.user.v1.ListAvailablePrettyDisplayIDsRequest - 162, // 241: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayIDFromPool:input_type -> hyapp.user.v1.ApplyPrettyDisplayIDFromPoolRequest - 155, // 242: hyapp.user.v1.UserIdentityService.ExpirePrettyDisplayUserID:input_type -> hyapp.user.v1.ExpirePrettyDisplayUserIDRequest - 164, // 243: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDPools:input_type -> hyapp.user.v1.ListPrettyDisplayIDPoolsRequest - 166, // 244: hyapp.user.v1.UserPrettyDisplayIDAdminService.CreatePrettyDisplayIDPool:input_type -> hyapp.user.v1.CreatePrettyDisplayIDPoolRequest - 167, // 245: hyapp.user.v1.UserPrettyDisplayIDAdminService.UpdatePrettyDisplayIDPool:input_type -> hyapp.user.v1.UpdatePrettyDisplayIDPoolRequest - 169, // 246: hyapp.user.v1.UserPrettyDisplayIDAdminService.GeneratePrettyDisplayIDs:input_type -> hyapp.user.v1.GeneratePrettyDisplayIDsRequest - 171, // 247: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDs:input_type -> hyapp.user.v1.ListPrettyDisplayIDsRequest - 173, // 248: hyapp.user.v1.UserPrettyDisplayIDAdminService.SetPrettyDisplayIDStatus:input_type -> hyapp.user.v1.SetPrettyDisplayIDStatusRequest - 174, // 249: hyapp.user.v1.UserPrettyDisplayIDAdminService.RecyclePrettyDisplayID:input_type -> hyapp.user.v1.RecyclePrettyDisplayIDRequest - 176, // 250: hyapp.user.v1.UserPrettyDisplayIDAdminService.AdminGrantPrettyDisplayID:input_type -> hyapp.user.v1.AdminGrantPrettyDisplayIDRequest - 18, // 251: hyapp.user.v1.UserService.GetUser:output_type -> hyapp.user.v1.GetUserResponse - 10, // 252: hyapp.user.v1.UserService.GetInviteAttribution:output_type -> hyapp.user.v1.GetInviteAttributionResponse - 21, // 253: hyapp.user.v1.UserService.BusinessUserLookup:output_type -> hyapp.user.v1.BusinessUserLookupResponse - 24, // 254: hyapp.user.v1.UserService.GetMyProfileStats:output_type -> hyapp.user.v1.GetMyProfileStatsResponse - 82, // 255: hyapp.user.v1.UserService.BatchGetUsers:output_type -> hyapp.user.v1.BatchGetUsersResponse - 86, // 256: hyapp.user.v1.UserService.BatchGetUserAdminProfiles:output_type -> hyapp.user.v1.BatchGetUserAdminProfilesResponse - 88, // 257: hyapp.user.v1.UserService.AdminIssueUserAccessToken:output_type -> hyapp.user.v1.AdminIssueUserAccessTokenResponse - 91, // 258: hyapp.user.v1.UserService.BatchGetRoomBasicUsers:output_type -> hyapp.user.v1.BatchGetRoomBasicUsersResponse - 93, // 259: hyapp.user.v1.UserService.ListUserIDs:output_type -> hyapp.user.v1.ListUserIDsResponse - 13, // 260: hyapp.user.v1.UserService.GetUserMicLifetimeStats:output_type -> hyapp.user.v1.GetUserMicLifetimeStatsResponse - 95, // 261: hyapp.user.v1.UserService.UpdateUserProfile:output_type -> hyapp.user.v1.UpdateUserProfileResponse - 97, // 262: hyapp.user.v1.UserService.UpdateUserProfileBackground:output_type -> hyapp.user.v1.UpdateUserProfileBackgroundResponse - 99, // 263: hyapp.user.v1.UserService.UpdateUserContactInfo:output_type -> hyapp.user.v1.UpdateUserContactInfoResponse - 101, // 264: hyapp.user.v1.UserService.UpdateUserWithdrawAddress:output_type -> hyapp.user.v1.UpdateUserWithdrawAddressResponse - 104, // 265: hyapp.user.v1.UserService.ChangeUserCountry:output_type -> hyapp.user.v1.ChangeUserCountryResponse - 104, // 266: hyapp.user.v1.UserService.AdminChangeUserCountry:output_type -> hyapp.user.v1.ChangeUserCountryResponse - 106, // 267: hyapp.user.v1.UserService.SetUserStatus:output_type -> hyapp.user.v1.SetUserStatusResponse - 109, // 268: hyapp.user.v1.UserService.AdminBanUser:output_type -> hyapp.user.v1.AdminBanUserResponse - 111, // 269: hyapp.user.v1.UserService.AdminUnbanUser:output_type -> hyapp.user.v1.AdminUnbanUserResponse - 114, // 270: hyapp.user.v1.UserService.CreateManagerUserBlock:output_type -> hyapp.user.v1.CreateManagerUserBlockResponse - 116, // 271: hyapp.user.v1.UserService.ListManagerUserBlocks:output_type -> hyapp.user.v1.ListManagerUserBlocksResponse - 118, // 272: hyapp.user.v1.UserService.UnblockManagerUser:output_type -> hyapp.user.v1.UnblockManagerUserResponse - 120, // 273: hyapp.user.v1.UserService.CompleteOnboarding:output_type -> hyapp.user.v1.CompleteOnboardingResponse - 122, // 274: hyapp.user.v1.UserService.SearchInviteReferrer:output_type -> hyapp.user.v1.SearchInviteReferrerResponse - 124, // 275: hyapp.user.v1.UserService.BindInviteReferrer:output_type -> hyapp.user.v1.BindInviteReferrerResponse - 26, // 276: hyapp.user.v1.UserSocialService.RecordProfileVisit:output_type -> hyapp.user.v1.RecordProfileVisitResponse - 29, // 277: hyapp.user.v1.UserSocialService.ListProfileVisitors:output_type -> hyapp.user.v1.ListProfileVisitorsResponse - 31, // 278: hyapp.user.v1.UserSocialService.FollowUser:output_type -> hyapp.user.v1.FollowUserResponse - 33, // 279: hyapp.user.v1.UserSocialService.UnfollowUser:output_type -> hyapp.user.v1.UnfollowUserResponse - 36, // 280: hyapp.user.v1.UserSocialService.ListFollowing:output_type -> hyapp.user.v1.ListFollowingResponse - 38, // 281: hyapp.user.v1.UserSocialService.ApplyFriend:output_type -> hyapp.user.v1.ApplyFriendResponse - 40, // 282: hyapp.user.v1.UserSocialService.AcceptFriendApplication:output_type -> hyapp.user.v1.AcceptFriendApplicationResponse - 42, // 283: hyapp.user.v1.UserSocialService.DeleteFriend:output_type -> hyapp.user.v1.DeleteFriendResponse - 45, // 284: hyapp.user.v1.UserSocialService.ListFriends:output_type -> hyapp.user.v1.ListFriendsResponse - 48, // 285: hyapp.user.v1.UserSocialService.ListFriendApplications:output_type -> hyapp.user.v1.ListFriendApplicationsResponse - 80, // 286: hyapp.user.v1.UserSocialService.SubmitReport:output_type -> hyapp.user.v1.SubmitReportResponse - 60, // 287: hyapp.user.v1.UserCPService.ListCPApplications:output_type -> hyapp.user.v1.ListCPApplicationsResponse - 62, // 288: hyapp.user.v1.UserCPService.AcceptCPApplication:output_type -> hyapp.user.v1.AcceptCPApplicationResponse - 64, // 289: hyapp.user.v1.UserCPService.RejectCPApplication:output_type -> hyapp.user.v1.RejectCPApplicationResponse - 66, // 290: hyapp.user.v1.UserCPService.ListCPRelationships:output_type -> hyapp.user.v1.ListCPRelationshipsResponse - 68, // 291: hyapp.user.v1.UserCPService.ListCPIntimacyLeaderboard:output_type -> hyapp.user.v1.ListCPIntimacyLeaderboardResponse - 70, // 292: hyapp.user.v1.UserCPService.PrepareBreakCPRelationship:output_type -> hyapp.user.v1.PrepareBreakCPRelationshipResponse - 72, // 293: hyapp.user.v1.UserCPService.ConfirmBreakCPRelationship:output_type -> hyapp.user.v1.ConfirmBreakCPRelationshipResponse - 74, // 294: hyapp.user.v1.UserCPService.CancelBreakCPRelationship:output_type -> hyapp.user.v1.CancelBreakCPRelationshipResponse - 77, // 295: hyapp.user.v1.UserCPInternalService.ConsumeRoomGiftCPEvent:output_type -> hyapp.user.v1.ConsumeRoomGiftCPEventResponse - 58, // 296: hyapp.user.v1.UserCPInternalService.ListCPWeeklyRankEntries:output_type -> hyapp.user.v1.ListCPWeeklyRankEntriesResponse - 15, // 297: hyapp.user.v1.UserCronService.ProcessLoginIPRiskBatch:output_type -> hyapp.user.v1.CronBatchResponse - 15, // 298: hyapp.user.v1.UserCronService.ProcessRegionRebuildBatch:output_type -> hyapp.user.v1.CronBatchResponse - 15, // 299: hyapp.user.v1.UserCronService.CompensateMicOpenSessions:output_type -> hyapp.user.v1.CronBatchResponse - 15, // 300: hyapp.user.v1.UserCronService.CompensateRoomOpenSessions:output_type -> hyapp.user.v1.CronBatchResponse - 15, // 301: hyapp.user.v1.UserCronService.ExpireManagerUserBlocks:output_type -> hyapp.user.v1.CronBatchResponse - 15, // 302: hyapp.user.v1.UserCronService.ExpireAdminUserBans:output_type -> hyapp.user.v1.CronBatchResponse - 15, // 303: hyapp.user.v1.UserCronService.RefreshCPIntimacyLeaderboard:output_type -> hyapp.user.v1.CronBatchResponse - 126, // 304: hyapp.user.v1.UserDeviceService.BindPushToken:output_type -> hyapp.user.v1.BindPushTokenResponse - 128, // 305: hyapp.user.v1.UserDeviceService.DeletePushToken:output_type -> hyapp.user.v1.DeletePushTokenResponse - 4, // 306: hyapp.user.v1.AppRegistryService.ResolveApp:output_type -> hyapp.user.v1.ResolveAppResponse - 179, // 307: hyapp.user.v1.AppRegistryService.ListApps:output_type -> hyapp.user.v1.ListAppsResponse - 132, // 308: hyapp.user.v1.CountryAdminService.ListCountries:output_type -> hyapp.user.v1.ListCountriesResponse - 134, // 309: hyapp.user.v1.CountryAdminService.UpdateCountry:output_type -> hyapp.user.v1.CountryResponse - 136, // 310: hyapp.user.v1.CountryQueryService.ListRegistrationCountries:output_type -> hyapp.user.v1.ListRegistrationCountriesResponse - 139, // 311: hyapp.user.v1.CountryQueryService.ListLoginRiskBlockedCountries:output_type -> hyapp.user.v1.ListLoginRiskBlockedCountriesResponse - 141, // 312: hyapp.user.v1.RegionAdminService.ListRegions:output_type -> hyapp.user.v1.ListRegionsResponse - 145, // 313: hyapp.user.v1.RegionAdminService.GetRegion:output_type -> hyapp.user.v1.RegionResponse - 145, // 314: hyapp.user.v1.RegionAdminService.UpdateRegion:output_type -> hyapp.user.v1.RegionResponse - 145, // 315: hyapp.user.v1.RegionAdminService.ReplaceRegionCountries:output_type -> hyapp.user.v1.RegionResponse - 148, // 316: hyapp.user.v1.UserIdentityService.GetUserIdentity:output_type -> hyapp.user.v1.GetUserIdentityResponse - 150, // 317: hyapp.user.v1.UserIdentityService.ResolveDisplayUserID:output_type -> hyapp.user.v1.ResolveDisplayUserIDResponse - 181, // 318: hyapp.user.v1.UserIdentityService.ResolveAdminUserIdentifier:output_type -> hyapp.user.v1.ResolveAdminUserIdentifierResponse - 152, // 319: hyapp.user.v1.UserIdentityService.ChangeDisplayUserID:output_type -> hyapp.user.v1.ChangeDisplayUserIDResponse - 154, // 320: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayUserID:output_type -> hyapp.user.v1.ApplyPrettyDisplayUserIDResponse - 161, // 321: hyapp.user.v1.UserIdentityService.ListAvailablePrettyDisplayIDs:output_type -> hyapp.user.v1.ListAvailablePrettyDisplayIDsResponse - 163, // 322: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayIDFromPool:output_type -> hyapp.user.v1.ApplyPrettyDisplayIDFromPoolResponse - 156, // 323: hyapp.user.v1.UserIdentityService.ExpirePrettyDisplayUserID:output_type -> hyapp.user.v1.ExpirePrettyDisplayUserIDResponse - 165, // 324: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDPools:output_type -> hyapp.user.v1.ListPrettyDisplayIDPoolsResponse - 168, // 325: hyapp.user.v1.UserPrettyDisplayIDAdminService.CreatePrettyDisplayIDPool:output_type -> hyapp.user.v1.PrettyDisplayIDPoolResponse - 168, // 326: hyapp.user.v1.UserPrettyDisplayIDAdminService.UpdatePrettyDisplayIDPool:output_type -> hyapp.user.v1.PrettyDisplayIDPoolResponse - 170, // 327: hyapp.user.v1.UserPrettyDisplayIDAdminService.GeneratePrettyDisplayIDs:output_type -> hyapp.user.v1.GeneratePrettyDisplayIDsResponse - 172, // 328: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDs:output_type -> hyapp.user.v1.ListPrettyDisplayIDsResponse - 175, // 329: hyapp.user.v1.UserPrettyDisplayIDAdminService.SetPrettyDisplayIDStatus:output_type -> hyapp.user.v1.PrettyDisplayIDResponse - 175, // 330: hyapp.user.v1.UserPrettyDisplayIDAdminService.RecyclePrettyDisplayID:output_type -> hyapp.user.v1.PrettyDisplayIDResponse - 177, // 331: hyapp.user.v1.UserPrettyDisplayIDAdminService.AdminGrantPrettyDisplayID:output_type -> hyapp.user.v1.AdminGrantPrettyDisplayIDResponse - 251, // [251:332] is the sub-list for method output_type - 170, // [170:251] is the sub-list for method input_type - 170, // [170:170] is the sub-list for extension type_name - 170, // [170:170] is the sub-list for extension extendee - 0, // [0:170] is the sub-list for field type_name + 49, // 163: hyapp.user.v1.CPFormationGiftFeedItem.requester:type_name -> hyapp.user.v1.CPUserProfile + 49, // 164: hyapp.user.v1.CPFormationGiftFeedItem.target:type_name -> hyapp.user.v1.CPUserProfile + 1, // 165: hyapp.user.v1.ListCPFormationGiftFeedRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 178, // 166: hyapp.user.v1.ListCPFormationGiftFeedResponse.items:type_name -> hyapp.user.v1.CPFormationGiftFeedItem + 1, // 167: hyapp.user.v1.ListAppsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 2, // 168: hyapp.user.v1.ListAppsResponse.apps:type_name -> hyapp.user.v1.App + 1, // 169: hyapp.user.v1.ResolveAdminUserIdentifierRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 146, // 170: hyapp.user.v1.ResolveAdminUserIdentifierResponse.identity:type_name -> hyapp.user.v1.UserIdentity + 5, // 171: hyapp.user.v1.BatchGetUsersResponse.UsersEntry.value:type_name -> hyapp.user.v1.User + 84, // 172: hyapp.user.v1.BatchGetUserAdminProfilesResponse.ProfilesEntry.value:type_name -> hyapp.user.v1.UserAdminProfile + 89, // 173: hyapp.user.v1.BatchGetRoomBasicUsersResponse.UsersEntry.value:type_name -> hyapp.user.v1.RoomBasicUser + 17, // 174: hyapp.user.v1.UserService.GetUser:input_type -> hyapp.user.v1.GetUserRequest + 9, // 175: hyapp.user.v1.UserService.GetInviteAttribution:input_type -> hyapp.user.v1.GetInviteAttributionRequest + 19, // 176: hyapp.user.v1.UserService.BusinessUserLookup:input_type -> hyapp.user.v1.BusinessUserLookupRequest + 23, // 177: hyapp.user.v1.UserService.GetMyProfileStats:input_type -> hyapp.user.v1.GetMyProfileStatsRequest + 81, // 178: hyapp.user.v1.UserService.BatchGetUsers:input_type -> hyapp.user.v1.BatchGetUsersRequest + 85, // 179: hyapp.user.v1.UserService.BatchGetUserAdminProfiles:input_type -> hyapp.user.v1.BatchGetUserAdminProfilesRequest + 87, // 180: hyapp.user.v1.UserService.AdminIssueUserAccessToken:input_type -> hyapp.user.v1.AdminIssueUserAccessTokenRequest + 90, // 181: hyapp.user.v1.UserService.BatchGetRoomBasicUsers:input_type -> hyapp.user.v1.BatchGetRoomBasicUsersRequest + 92, // 182: hyapp.user.v1.UserService.ListUserIDs:input_type -> hyapp.user.v1.ListUserIDsRequest + 12, // 183: hyapp.user.v1.UserService.GetUserMicLifetimeStats:input_type -> hyapp.user.v1.GetUserMicLifetimeStatsRequest + 94, // 184: hyapp.user.v1.UserService.UpdateUserProfile:input_type -> hyapp.user.v1.UpdateUserProfileRequest + 96, // 185: hyapp.user.v1.UserService.UpdateUserProfileBackground:input_type -> hyapp.user.v1.UpdateUserProfileBackgroundRequest + 98, // 186: hyapp.user.v1.UserService.UpdateUserContactInfo:input_type -> hyapp.user.v1.UpdateUserContactInfoRequest + 100, // 187: hyapp.user.v1.UserService.UpdateUserWithdrawAddress:input_type -> hyapp.user.v1.UpdateUserWithdrawAddressRequest + 102, // 188: hyapp.user.v1.UserService.ChangeUserCountry:input_type -> hyapp.user.v1.ChangeUserCountryRequest + 103, // 189: hyapp.user.v1.UserService.AdminChangeUserCountry:input_type -> hyapp.user.v1.AdminChangeUserCountryRequest + 105, // 190: hyapp.user.v1.UserService.SetUserStatus:input_type -> hyapp.user.v1.SetUserStatusRequest + 108, // 191: hyapp.user.v1.UserService.AdminBanUser:input_type -> hyapp.user.v1.AdminBanUserRequest + 110, // 192: hyapp.user.v1.UserService.AdminUnbanUser:input_type -> hyapp.user.v1.AdminUnbanUserRequest + 113, // 193: hyapp.user.v1.UserService.CreateManagerUserBlock:input_type -> hyapp.user.v1.CreateManagerUserBlockRequest + 115, // 194: hyapp.user.v1.UserService.ListManagerUserBlocks:input_type -> hyapp.user.v1.ListManagerUserBlocksRequest + 117, // 195: hyapp.user.v1.UserService.UnblockManagerUser:input_type -> hyapp.user.v1.UnblockManagerUserRequest + 119, // 196: hyapp.user.v1.UserService.CompleteOnboarding:input_type -> hyapp.user.v1.CompleteOnboardingRequest + 121, // 197: hyapp.user.v1.UserService.SearchInviteReferrer:input_type -> hyapp.user.v1.SearchInviteReferrerRequest + 123, // 198: hyapp.user.v1.UserService.BindInviteReferrer:input_type -> hyapp.user.v1.BindInviteReferrerRequest + 25, // 199: hyapp.user.v1.UserSocialService.RecordProfileVisit:input_type -> hyapp.user.v1.RecordProfileVisitRequest + 28, // 200: hyapp.user.v1.UserSocialService.ListProfileVisitors:input_type -> hyapp.user.v1.ListProfileVisitorsRequest + 30, // 201: hyapp.user.v1.UserSocialService.FollowUser:input_type -> hyapp.user.v1.FollowUserRequest + 32, // 202: hyapp.user.v1.UserSocialService.UnfollowUser:input_type -> hyapp.user.v1.UnfollowUserRequest + 35, // 203: hyapp.user.v1.UserSocialService.ListFollowing:input_type -> hyapp.user.v1.ListFollowingRequest + 37, // 204: hyapp.user.v1.UserSocialService.ApplyFriend:input_type -> hyapp.user.v1.ApplyFriendRequest + 39, // 205: hyapp.user.v1.UserSocialService.AcceptFriendApplication:input_type -> hyapp.user.v1.AcceptFriendApplicationRequest + 41, // 206: hyapp.user.v1.UserSocialService.DeleteFriend:input_type -> hyapp.user.v1.DeleteFriendRequest + 44, // 207: hyapp.user.v1.UserSocialService.ListFriends:input_type -> hyapp.user.v1.ListFriendsRequest + 47, // 208: hyapp.user.v1.UserSocialService.ListFriendApplications:input_type -> hyapp.user.v1.ListFriendApplicationsRequest + 79, // 209: hyapp.user.v1.UserSocialService.SubmitReport:input_type -> hyapp.user.v1.SubmitReportRequest + 59, // 210: hyapp.user.v1.UserCPService.ListCPApplications:input_type -> hyapp.user.v1.ListCPApplicationsRequest + 61, // 211: hyapp.user.v1.UserCPService.AcceptCPApplication:input_type -> hyapp.user.v1.AcceptCPApplicationRequest + 63, // 212: hyapp.user.v1.UserCPService.RejectCPApplication:input_type -> hyapp.user.v1.RejectCPApplicationRequest + 65, // 213: hyapp.user.v1.UserCPService.ListCPRelationships:input_type -> hyapp.user.v1.ListCPRelationshipsRequest + 67, // 214: hyapp.user.v1.UserCPService.ListCPIntimacyLeaderboard:input_type -> hyapp.user.v1.ListCPIntimacyLeaderboardRequest + 69, // 215: hyapp.user.v1.UserCPService.PrepareBreakCPRelationship:input_type -> hyapp.user.v1.PrepareBreakCPRelationshipRequest + 71, // 216: hyapp.user.v1.UserCPService.ConfirmBreakCPRelationship:input_type -> hyapp.user.v1.ConfirmBreakCPRelationshipRequest + 73, // 217: hyapp.user.v1.UserCPService.CancelBreakCPRelationship:input_type -> hyapp.user.v1.CancelBreakCPRelationshipRequest + 179, // 218: hyapp.user.v1.UserCPService.ListCPFormationGiftFeed:input_type -> hyapp.user.v1.ListCPFormationGiftFeedRequest + 76, // 219: hyapp.user.v1.UserCPInternalService.ConsumeRoomGiftCPEvent:input_type -> hyapp.user.v1.ConsumeRoomGiftCPEventRequest + 57, // 220: hyapp.user.v1.UserCPInternalService.ListCPWeeklyRankEntries:input_type -> hyapp.user.v1.ListCPWeeklyRankEntriesRequest + 14, // 221: hyapp.user.v1.UserCronService.ProcessLoginIPRiskBatch:input_type -> hyapp.user.v1.CronBatchRequest + 14, // 222: hyapp.user.v1.UserCronService.ProcessRegionRebuildBatch:input_type -> hyapp.user.v1.CronBatchRequest + 14, // 223: hyapp.user.v1.UserCronService.CompensateMicOpenSessions:input_type -> hyapp.user.v1.CronBatchRequest + 14, // 224: hyapp.user.v1.UserCronService.CompensateRoomOpenSessions:input_type -> hyapp.user.v1.CronBatchRequest + 14, // 225: hyapp.user.v1.UserCronService.ExpireManagerUserBlocks:input_type -> hyapp.user.v1.CronBatchRequest + 14, // 226: hyapp.user.v1.UserCronService.ExpireAdminUserBans:input_type -> hyapp.user.v1.CronBatchRequest + 14, // 227: hyapp.user.v1.UserCronService.RefreshCPIntimacyLeaderboard:input_type -> hyapp.user.v1.CronBatchRequest + 125, // 228: hyapp.user.v1.UserDeviceService.BindPushToken:input_type -> hyapp.user.v1.BindPushTokenRequest + 127, // 229: hyapp.user.v1.UserDeviceService.DeletePushToken:input_type -> hyapp.user.v1.DeletePushTokenRequest + 3, // 230: hyapp.user.v1.AppRegistryService.ResolveApp:input_type -> hyapp.user.v1.ResolveAppRequest + 181, // 231: hyapp.user.v1.AppRegistryService.ListApps:input_type -> hyapp.user.v1.ListAppsRequest + 131, // 232: hyapp.user.v1.CountryAdminService.ListCountries:input_type -> hyapp.user.v1.ListCountriesRequest + 133, // 233: hyapp.user.v1.CountryAdminService.UpdateCountry:input_type -> hyapp.user.v1.UpdateCountryRequest + 135, // 234: hyapp.user.v1.CountryQueryService.ListRegistrationCountries:input_type -> hyapp.user.v1.ListRegistrationCountriesRequest + 138, // 235: hyapp.user.v1.CountryQueryService.ListLoginRiskBlockedCountries:input_type -> hyapp.user.v1.ListLoginRiskBlockedCountriesRequest + 140, // 236: hyapp.user.v1.RegionAdminService.ListRegions:input_type -> hyapp.user.v1.ListRegionsRequest + 142, // 237: hyapp.user.v1.RegionAdminService.GetRegion:input_type -> hyapp.user.v1.GetRegionRequest + 143, // 238: hyapp.user.v1.RegionAdminService.UpdateRegion:input_type -> hyapp.user.v1.UpdateRegionRequest + 144, // 239: hyapp.user.v1.RegionAdminService.ReplaceRegionCountries:input_type -> hyapp.user.v1.ReplaceRegionCountriesRequest + 147, // 240: hyapp.user.v1.UserIdentityService.GetUserIdentity:input_type -> hyapp.user.v1.GetUserIdentityRequest + 149, // 241: hyapp.user.v1.UserIdentityService.ResolveDisplayUserID:input_type -> hyapp.user.v1.ResolveDisplayUserIDRequest + 183, // 242: hyapp.user.v1.UserIdentityService.ResolveAdminUserIdentifier:input_type -> hyapp.user.v1.ResolveAdminUserIdentifierRequest + 151, // 243: hyapp.user.v1.UserIdentityService.ChangeDisplayUserID:input_type -> hyapp.user.v1.ChangeDisplayUserIDRequest + 153, // 244: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayUserID:input_type -> hyapp.user.v1.ApplyPrettyDisplayUserIDRequest + 160, // 245: hyapp.user.v1.UserIdentityService.ListAvailablePrettyDisplayIDs:input_type -> hyapp.user.v1.ListAvailablePrettyDisplayIDsRequest + 162, // 246: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayIDFromPool:input_type -> hyapp.user.v1.ApplyPrettyDisplayIDFromPoolRequest + 155, // 247: hyapp.user.v1.UserIdentityService.ExpirePrettyDisplayUserID:input_type -> hyapp.user.v1.ExpirePrettyDisplayUserIDRequest + 164, // 248: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDPools:input_type -> hyapp.user.v1.ListPrettyDisplayIDPoolsRequest + 166, // 249: hyapp.user.v1.UserPrettyDisplayIDAdminService.CreatePrettyDisplayIDPool:input_type -> hyapp.user.v1.CreatePrettyDisplayIDPoolRequest + 167, // 250: hyapp.user.v1.UserPrettyDisplayIDAdminService.UpdatePrettyDisplayIDPool:input_type -> hyapp.user.v1.UpdatePrettyDisplayIDPoolRequest + 169, // 251: hyapp.user.v1.UserPrettyDisplayIDAdminService.GeneratePrettyDisplayIDs:input_type -> hyapp.user.v1.GeneratePrettyDisplayIDsRequest + 171, // 252: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDs:input_type -> hyapp.user.v1.ListPrettyDisplayIDsRequest + 173, // 253: hyapp.user.v1.UserPrettyDisplayIDAdminService.SetPrettyDisplayIDStatus:input_type -> hyapp.user.v1.SetPrettyDisplayIDStatusRequest + 174, // 254: hyapp.user.v1.UserPrettyDisplayIDAdminService.RecyclePrettyDisplayID:input_type -> hyapp.user.v1.RecyclePrettyDisplayIDRequest + 176, // 255: hyapp.user.v1.UserPrettyDisplayIDAdminService.AdminGrantPrettyDisplayID:input_type -> hyapp.user.v1.AdminGrantPrettyDisplayIDRequest + 18, // 256: hyapp.user.v1.UserService.GetUser:output_type -> hyapp.user.v1.GetUserResponse + 10, // 257: hyapp.user.v1.UserService.GetInviteAttribution:output_type -> hyapp.user.v1.GetInviteAttributionResponse + 21, // 258: hyapp.user.v1.UserService.BusinessUserLookup:output_type -> hyapp.user.v1.BusinessUserLookupResponse + 24, // 259: hyapp.user.v1.UserService.GetMyProfileStats:output_type -> hyapp.user.v1.GetMyProfileStatsResponse + 82, // 260: hyapp.user.v1.UserService.BatchGetUsers:output_type -> hyapp.user.v1.BatchGetUsersResponse + 86, // 261: hyapp.user.v1.UserService.BatchGetUserAdminProfiles:output_type -> hyapp.user.v1.BatchGetUserAdminProfilesResponse + 88, // 262: hyapp.user.v1.UserService.AdminIssueUserAccessToken:output_type -> hyapp.user.v1.AdminIssueUserAccessTokenResponse + 91, // 263: hyapp.user.v1.UserService.BatchGetRoomBasicUsers:output_type -> hyapp.user.v1.BatchGetRoomBasicUsersResponse + 93, // 264: hyapp.user.v1.UserService.ListUserIDs:output_type -> hyapp.user.v1.ListUserIDsResponse + 13, // 265: hyapp.user.v1.UserService.GetUserMicLifetimeStats:output_type -> hyapp.user.v1.GetUserMicLifetimeStatsResponse + 95, // 266: hyapp.user.v1.UserService.UpdateUserProfile:output_type -> hyapp.user.v1.UpdateUserProfileResponse + 97, // 267: hyapp.user.v1.UserService.UpdateUserProfileBackground:output_type -> hyapp.user.v1.UpdateUserProfileBackgroundResponse + 99, // 268: hyapp.user.v1.UserService.UpdateUserContactInfo:output_type -> hyapp.user.v1.UpdateUserContactInfoResponse + 101, // 269: hyapp.user.v1.UserService.UpdateUserWithdrawAddress:output_type -> hyapp.user.v1.UpdateUserWithdrawAddressResponse + 104, // 270: hyapp.user.v1.UserService.ChangeUserCountry:output_type -> hyapp.user.v1.ChangeUserCountryResponse + 104, // 271: hyapp.user.v1.UserService.AdminChangeUserCountry:output_type -> hyapp.user.v1.ChangeUserCountryResponse + 106, // 272: hyapp.user.v1.UserService.SetUserStatus:output_type -> hyapp.user.v1.SetUserStatusResponse + 109, // 273: hyapp.user.v1.UserService.AdminBanUser:output_type -> hyapp.user.v1.AdminBanUserResponse + 111, // 274: hyapp.user.v1.UserService.AdminUnbanUser:output_type -> hyapp.user.v1.AdminUnbanUserResponse + 114, // 275: hyapp.user.v1.UserService.CreateManagerUserBlock:output_type -> hyapp.user.v1.CreateManagerUserBlockResponse + 116, // 276: hyapp.user.v1.UserService.ListManagerUserBlocks:output_type -> hyapp.user.v1.ListManagerUserBlocksResponse + 118, // 277: hyapp.user.v1.UserService.UnblockManagerUser:output_type -> hyapp.user.v1.UnblockManagerUserResponse + 120, // 278: hyapp.user.v1.UserService.CompleteOnboarding:output_type -> hyapp.user.v1.CompleteOnboardingResponse + 122, // 279: hyapp.user.v1.UserService.SearchInviteReferrer:output_type -> hyapp.user.v1.SearchInviteReferrerResponse + 124, // 280: hyapp.user.v1.UserService.BindInviteReferrer:output_type -> hyapp.user.v1.BindInviteReferrerResponse + 26, // 281: hyapp.user.v1.UserSocialService.RecordProfileVisit:output_type -> hyapp.user.v1.RecordProfileVisitResponse + 29, // 282: hyapp.user.v1.UserSocialService.ListProfileVisitors:output_type -> hyapp.user.v1.ListProfileVisitorsResponse + 31, // 283: hyapp.user.v1.UserSocialService.FollowUser:output_type -> hyapp.user.v1.FollowUserResponse + 33, // 284: hyapp.user.v1.UserSocialService.UnfollowUser:output_type -> hyapp.user.v1.UnfollowUserResponse + 36, // 285: hyapp.user.v1.UserSocialService.ListFollowing:output_type -> hyapp.user.v1.ListFollowingResponse + 38, // 286: hyapp.user.v1.UserSocialService.ApplyFriend:output_type -> hyapp.user.v1.ApplyFriendResponse + 40, // 287: hyapp.user.v1.UserSocialService.AcceptFriendApplication:output_type -> hyapp.user.v1.AcceptFriendApplicationResponse + 42, // 288: hyapp.user.v1.UserSocialService.DeleteFriend:output_type -> hyapp.user.v1.DeleteFriendResponse + 45, // 289: hyapp.user.v1.UserSocialService.ListFriends:output_type -> hyapp.user.v1.ListFriendsResponse + 48, // 290: hyapp.user.v1.UserSocialService.ListFriendApplications:output_type -> hyapp.user.v1.ListFriendApplicationsResponse + 80, // 291: hyapp.user.v1.UserSocialService.SubmitReport:output_type -> hyapp.user.v1.SubmitReportResponse + 60, // 292: hyapp.user.v1.UserCPService.ListCPApplications:output_type -> hyapp.user.v1.ListCPApplicationsResponse + 62, // 293: hyapp.user.v1.UserCPService.AcceptCPApplication:output_type -> hyapp.user.v1.AcceptCPApplicationResponse + 64, // 294: hyapp.user.v1.UserCPService.RejectCPApplication:output_type -> hyapp.user.v1.RejectCPApplicationResponse + 66, // 295: hyapp.user.v1.UserCPService.ListCPRelationships:output_type -> hyapp.user.v1.ListCPRelationshipsResponse + 68, // 296: hyapp.user.v1.UserCPService.ListCPIntimacyLeaderboard:output_type -> hyapp.user.v1.ListCPIntimacyLeaderboardResponse + 70, // 297: hyapp.user.v1.UserCPService.PrepareBreakCPRelationship:output_type -> hyapp.user.v1.PrepareBreakCPRelationshipResponse + 72, // 298: hyapp.user.v1.UserCPService.ConfirmBreakCPRelationship:output_type -> hyapp.user.v1.ConfirmBreakCPRelationshipResponse + 74, // 299: hyapp.user.v1.UserCPService.CancelBreakCPRelationship:output_type -> hyapp.user.v1.CancelBreakCPRelationshipResponse + 180, // 300: hyapp.user.v1.UserCPService.ListCPFormationGiftFeed:output_type -> hyapp.user.v1.ListCPFormationGiftFeedResponse + 77, // 301: hyapp.user.v1.UserCPInternalService.ConsumeRoomGiftCPEvent:output_type -> hyapp.user.v1.ConsumeRoomGiftCPEventResponse + 58, // 302: hyapp.user.v1.UserCPInternalService.ListCPWeeklyRankEntries:output_type -> hyapp.user.v1.ListCPWeeklyRankEntriesResponse + 15, // 303: hyapp.user.v1.UserCronService.ProcessLoginIPRiskBatch:output_type -> hyapp.user.v1.CronBatchResponse + 15, // 304: hyapp.user.v1.UserCronService.ProcessRegionRebuildBatch:output_type -> hyapp.user.v1.CronBatchResponse + 15, // 305: hyapp.user.v1.UserCronService.CompensateMicOpenSessions:output_type -> hyapp.user.v1.CronBatchResponse + 15, // 306: hyapp.user.v1.UserCronService.CompensateRoomOpenSessions:output_type -> hyapp.user.v1.CronBatchResponse + 15, // 307: hyapp.user.v1.UserCronService.ExpireManagerUserBlocks:output_type -> hyapp.user.v1.CronBatchResponse + 15, // 308: hyapp.user.v1.UserCronService.ExpireAdminUserBans:output_type -> hyapp.user.v1.CronBatchResponse + 15, // 309: hyapp.user.v1.UserCronService.RefreshCPIntimacyLeaderboard:output_type -> hyapp.user.v1.CronBatchResponse + 126, // 310: hyapp.user.v1.UserDeviceService.BindPushToken:output_type -> hyapp.user.v1.BindPushTokenResponse + 128, // 311: hyapp.user.v1.UserDeviceService.DeletePushToken:output_type -> hyapp.user.v1.DeletePushTokenResponse + 4, // 312: hyapp.user.v1.AppRegistryService.ResolveApp:output_type -> hyapp.user.v1.ResolveAppResponse + 182, // 313: hyapp.user.v1.AppRegistryService.ListApps:output_type -> hyapp.user.v1.ListAppsResponse + 132, // 314: hyapp.user.v1.CountryAdminService.ListCountries:output_type -> hyapp.user.v1.ListCountriesResponse + 134, // 315: hyapp.user.v1.CountryAdminService.UpdateCountry:output_type -> hyapp.user.v1.CountryResponse + 136, // 316: hyapp.user.v1.CountryQueryService.ListRegistrationCountries:output_type -> hyapp.user.v1.ListRegistrationCountriesResponse + 139, // 317: hyapp.user.v1.CountryQueryService.ListLoginRiskBlockedCountries:output_type -> hyapp.user.v1.ListLoginRiskBlockedCountriesResponse + 141, // 318: hyapp.user.v1.RegionAdminService.ListRegions:output_type -> hyapp.user.v1.ListRegionsResponse + 145, // 319: hyapp.user.v1.RegionAdminService.GetRegion:output_type -> hyapp.user.v1.RegionResponse + 145, // 320: hyapp.user.v1.RegionAdminService.UpdateRegion:output_type -> hyapp.user.v1.RegionResponse + 145, // 321: hyapp.user.v1.RegionAdminService.ReplaceRegionCountries:output_type -> hyapp.user.v1.RegionResponse + 148, // 322: hyapp.user.v1.UserIdentityService.GetUserIdentity:output_type -> hyapp.user.v1.GetUserIdentityResponse + 150, // 323: hyapp.user.v1.UserIdentityService.ResolveDisplayUserID:output_type -> hyapp.user.v1.ResolveDisplayUserIDResponse + 184, // 324: hyapp.user.v1.UserIdentityService.ResolveAdminUserIdentifier:output_type -> hyapp.user.v1.ResolveAdminUserIdentifierResponse + 152, // 325: hyapp.user.v1.UserIdentityService.ChangeDisplayUserID:output_type -> hyapp.user.v1.ChangeDisplayUserIDResponse + 154, // 326: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayUserID:output_type -> hyapp.user.v1.ApplyPrettyDisplayUserIDResponse + 161, // 327: hyapp.user.v1.UserIdentityService.ListAvailablePrettyDisplayIDs:output_type -> hyapp.user.v1.ListAvailablePrettyDisplayIDsResponse + 163, // 328: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayIDFromPool:output_type -> hyapp.user.v1.ApplyPrettyDisplayIDFromPoolResponse + 156, // 329: hyapp.user.v1.UserIdentityService.ExpirePrettyDisplayUserID:output_type -> hyapp.user.v1.ExpirePrettyDisplayUserIDResponse + 165, // 330: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDPools:output_type -> hyapp.user.v1.ListPrettyDisplayIDPoolsResponse + 168, // 331: hyapp.user.v1.UserPrettyDisplayIDAdminService.CreatePrettyDisplayIDPool:output_type -> hyapp.user.v1.PrettyDisplayIDPoolResponse + 168, // 332: hyapp.user.v1.UserPrettyDisplayIDAdminService.UpdatePrettyDisplayIDPool:output_type -> hyapp.user.v1.PrettyDisplayIDPoolResponse + 170, // 333: hyapp.user.v1.UserPrettyDisplayIDAdminService.GeneratePrettyDisplayIDs:output_type -> hyapp.user.v1.GeneratePrettyDisplayIDsResponse + 172, // 334: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDs:output_type -> hyapp.user.v1.ListPrettyDisplayIDsResponse + 175, // 335: hyapp.user.v1.UserPrettyDisplayIDAdminService.SetPrettyDisplayIDStatus:output_type -> hyapp.user.v1.PrettyDisplayIDResponse + 175, // 336: hyapp.user.v1.UserPrettyDisplayIDAdminService.RecyclePrettyDisplayID:output_type -> hyapp.user.v1.PrettyDisplayIDResponse + 177, // 337: hyapp.user.v1.UserPrettyDisplayIDAdminService.AdminGrantPrettyDisplayID:output_type -> hyapp.user.v1.AdminGrantPrettyDisplayIDResponse + 256, // [256:338] is the sub-list for method output_type + 174, // [174:256] is the sub-list for method input_type + 174, // [174:174] is the sub-list for extension type_name + 174, // [174:174] is the sub-list for extension extendee + 0, // [0:174] is the sub-list for field type_name } func init() { file_proto_user_v1_user_proto_init() } @@ -16849,9 +15246,9 @@ func file_proto_user_v1_user_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_user_v1_user_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_user_v1_user_proto_rawDesc), len(file_proto_user_v1_user_proto_rawDesc)), NumEnums: 1, - NumMessages: 184, + NumMessages: 187, NumExtensions: 0, NumServices: 12, }, @@ -16861,7 +15258,6 @@ func file_proto_user_v1_user_proto_init() { MessageInfos: file_proto_user_v1_user_proto_msgTypes, }.Build() File_proto_user_v1_user_proto = out.File - file_proto_user_v1_user_proto_rawDesc = nil file_proto_user_v1_user_proto_goTypes = nil file_proto_user_v1_user_proto_depIdxs = nil } diff --git a/api/proto/user/v1/user.proto b/api/proto/user/v1/user.proto index 0457df95..759f781c 100644 --- a/api/proto/user/v1/user.proto +++ b/api/proto/user/v1/user.proto @@ -416,6 +416,8 @@ message CPGiftSnapshot { int32 gift_count = 5; int64 gift_value = 6; string billing_receipt_id = 7; + // coin_spent 是 wallet 结算出的礼物金币价值(背包礼物也保留价值),不能用 gift_value(热度/亲密值)替代。 + int64 coin_spent = 8; } // CPApplication 是 A 给 B 发送 CP/兄弟/姐妹礼物后生成的待处理申请。 @@ -649,6 +651,8 @@ message RoomGiftCPEvent { string gift_name = 16; string gift_icon_url = 17; string gift_animation_url = 18; + // coin_spent 来自 RoomGiftSent 的 wallet 结算价值,和 gift_value 的热度口径彼此独立。 + int64 coin_spent = 19; } message ConsumeRoomGiftCPEventRequest { @@ -1457,6 +1461,24 @@ message AdminGrantPrettyDisplayIDResponse { string lease_id = 3; } +// CPFormationGiftFeedItem 是组 CP 成立时所用礼物超过固定门槛的页面展示快照。 +message CPFormationGiftFeedItem { + string formation_id = 1; + int64 gift_coin_value = 2; + CPUserProfile requester = 3; + CPUserProfile target = 4; + int64 formed_at_ms = 5; +} + +message ListCPFormationGiftFeedRequest { + RequestMeta meta = 1; + int32 limit = 2; +} + +message ListCPFormationGiftFeedResponse { + repeated CPFormationGiftFeedItem items = 1; +} + // UserService 提供用户主状态、基础资料和注册资料读写接口。 service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); @@ -1511,6 +1533,7 @@ service UserCPService { rpc PrepareBreakCPRelationship(PrepareBreakCPRelationshipRequest) returns (PrepareBreakCPRelationshipResponse); rpc ConfirmBreakCPRelationship(ConfirmBreakCPRelationshipRequest) returns (ConfirmBreakCPRelationshipResponse); rpc CancelBreakCPRelationship(CancelBreakCPRelationshipRequest) returns (CancelBreakCPRelationshipResponse); + rpc ListCPFormationGiftFeed(ListCPFormationGiftFeedRequest) returns (ListCPFormationGiftFeedResponse); } // UserCPInternalService 给 owner outbox 消费 worker 调用,不暴露给 App 或后台。 diff --git a/api/proto/user/v1/user_grpc.pb.go b/api/proto/user/v1/user_grpc.pb.go index 1acc7df6..3049a8dc 100644 --- a/api/proto/user/v1/user_grpc.pb.go +++ b/api/proto/user/v1/user_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.6.2 -// - protoc v5.29.2 +// - protoc v7.35.0 // source: proto/user/v1/user.proto package userv1 @@ -1531,6 +1531,7 @@ const ( UserCPService_PrepareBreakCPRelationship_FullMethodName = "/hyapp.user.v1.UserCPService/PrepareBreakCPRelationship" UserCPService_ConfirmBreakCPRelationship_FullMethodName = "/hyapp.user.v1.UserCPService/ConfirmBreakCPRelationship" UserCPService_CancelBreakCPRelationship_FullMethodName = "/hyapp.user.v1.UserCPService/CancelBreakCPRelationship" + UserCPService_ListCPFormationGiftFeed_FullMethodName = "/hyapp.user.v1.UserCPService/ListCPFormationGiftFeed" ) // UserCPServiceClient is the client API for UserCPService service. @@ -1547,6 +1548,7 @@ type UserCPServiceClient interface { PrepareBreakCPRelationship(ctx context.Context, in *PrepareBreakCPRelationshipRequest, opts ...grpc.CallOption) (*PrepareBreakCPRelationshipResponse, error) ConfirmBreakCPRelationship(ctx context.Context, in *ConfirmBreakCPRelationshipRequest, opts ...grpc.CallOption) (*ConfirmBreakCPRelationshipResponse, error) CancelBreakCPRelationship(ctx context.Context, in *CancelBreakCPRelationshipRequest, opts ...grpc.CallOption) (*CancelBreakCPRelationshipResponse, error) + ListCPFormationGiftFeed(ctx context.Context, in *ListCPFormationGiftFeedRequest, opts ...grpc.CallOption) (*ListCPFormationGiftFeedResponse, error) } type userCPServiceClient struct { @@ -1637,6 +1639,16 @@ func (c *userCPServiceClient) CancelBreakCPRelationship(ctx context.Context, in return out, nil } +func (c *userCPServiceClient) ListCPFormationGiftFeed(ctx context.Context, in *ListCPFormationGiftFeedRequest, opts ...grpc.CallOption) (*ListCPFormationGiftFeedResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListCPFormationGiftFeedResponse) + err := c.cc.Invoke(ctx, UserCPService_ListCPFormationGiftFeed_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // UserCPServiceServer is the server API for UserCPService service. // All implementations must embed UnimplementedUserCPServiceServer // for forward compatibility. @@ -1651,6 +1663,7 @@ type UserCPServiceServer interface { PrepareBreakCPRelationship(context.Context, *PrepareBreakCPRelationshipRequest) (*PrepareBreakCPRelationshipResponse, error) ConfirmBreakCPRelationship(context.Context, *ConfirmBreakCPRelationshipRequest) (*ConfirmBreakCPRelationshipResponse, error) CancelBreakCPRelationship(context.Context, *CancelBreakCPRelationshipRequest) (*CancelBreakCPRelationshipResponse, error) + ListCPFormationGiftFeed(context.Context, *ListCPFormationGiftFeedRequest) (*ListCPFormationGiftFeedResponse, error) mustEmbedUnimplementedUserCPServiceServer() } @@ -1685,6 +1698,9 @@ func (UnimplementedUserCPServiceServer) ConfirmBreakCPRelationship(context.Conte func (UnimplementedUserCPServiceServer) CancelBreakCPRelationship(context.Context, *CancelBreakCPRelationshipRequest) (*CancelBreakCPRelationshipResponse, error) { return nil, status.Error(codes.Unimplemented, "method CancelBreakCPRelationship not implemented") } +func (UnimplementedUserCPServiceServer) ListCPFormationGiftFeed(context.Context, *ListCPFormationGiftFeedRequest) (*ListCPFormationGiftFeedResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListCPFormationGiftFeed not implemented") +} func (UnimplementedUserCPServiceServer) mustEmbedUnimplementedUserCPServiceServer() {} func (UnimplementedUserCPServiceServer) testEmbeddedByValue() {} @@ -1850,6 +1866,24 @@ func _UserCPService_CancelBreakCPRelationship_Handler(srv interface{}, ctx conte return interceptor(ctx, in, info, handler) } +func _UserCPService_ListCPFormationGiftFeed_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListCPFormationGiftFeedRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserCPServiceServer).ListCPFormationGiftFeed(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UserCPService_ListCPFormationGiftFeed_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserCPServiceServer).ListCPFormationGiftFeed(ctx, req.(*ListCPFormationGiftFeedRequest)) + } + return interceptor(ctx, in, info, handler) +} + // UserCPService_ServiceDesc is the grpc.ServiceDesc for UserCPService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -1889,6 +1923,10 @@ var UserCPService_ServiceDesc = grpc.ServiceDesc{ MethodName: "CancelBreakCPRelationship", Handler: _UserCPService_CancelBreakCPRelationship_Handler, }, + { + MethodName: "ListCPFormationGiftFeed", + Handler: _UserCPService_ListCPFormationGiftFeed_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "proto/user/v1/user.proto", @@ -2581,7 +2619,7 @@ func (UnimplementedAppRegistryServiceServer) ResolveApp(context.Context, *Resolv return nil, status.Error(codes.Unimplemented, "method ResolveApp not implemented") } func (UnimplementedAppRegistryServiceServer) ListApps(context.Context, *ListAppsRequest) (*ListAppsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListApps not implemented") + return nil, status.Error(codes.Unimplemented, "method ListApps not implemented") } func (UnimplementedAppRegistryServiceServer) mustEmbedUnimplementedAppRegistryServiceServer() {} func (UnimplementedAppRegistryServiceServer) testEmbeddedByValue() {} diff --git a/api/proto/wallet/v1/wallet.pb.go b/api/proto/wallet/v1/wallet.pb.go index c4d2849c..6d14f257 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.35.1 +// protoc-gen-go v1.36.11 // protoc v7.35.0 // source: proto/wallet/v1/wallet.proto @@ -11,6 +11,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -22,16 +23,13 @@ const ( // DebitGiftRequest 是 room-service 送礼同步扣费的最小账务输入。 type DebitGiftRequest struct { - 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"` + 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"` // 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"` @@ -48,7 +46,9 @@ type DebitGiftRequest struct { // entitlement_id 非空表示本次送礼从用户背包 gift 权益扣库存,不扣 COIN。 EntitlementId string `protobuf:"bytes,14,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` // charge_source 区分 coin/bag;为空按 coin 兼容旧客户端。 - ChargeSource string `protobuf:"bytes,15,opt,name=charge_source,json=chargeSource,proto3" json:"charge_source,omitempty"` + ChargeSource string `protobuf:"bytes,15,opt,name=charge_source,json=chargeSource,proto3" json:"charge_source,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *DebitGiftRequest) Reset() { @@ -188,17 +188,14 @@ func (x *DebitGiftRequest) GetChargeSource() string { // DebitDirectGiftRequest 是私聊送礼的账务命令;gateway 负责用 user-service 补齐区域和主播身份。 type DebitDirectGiftRequest struct { - 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"` - SenderUserId int64 `protobuf:"varint,2,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_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 `protogen:"open.v1"` + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + SenderUserId int64 `protobuf:"varint,2,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_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 使用 sender 当前 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"` @@ -207,6 +204,8 @@ type DebitDirectGiftRequest struct { TargetAgencyOwnerUserId int64 `protobuf:"varint,12,opt,name=target_agency_owner_user_id,json=targetAgencyOwnerUserId,proto3" json:"target_agency_owner_user_id,omitempty"` EntitlementId string `protobuf:"bytes,13,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` ChargeSource string `protobuf:"bytes,14,opt,name=charge_source,json=chargeSource,proto3" json:"charge_source,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *DebitDirectGiftRequest) Reset() { @@ -339,13 +338,10 @@ func (x *DebitDirectGiftRequest) GetChargeSource() string { // DebitGiftResponse 返回扣费流水、服务端结算值和 sender COIN 账后余额。 type DebitGiftResponse struct { - 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"` + 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"` // 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"` @@ -391,7 +387,9 @@ type DebitGiftResponse struct { LastRechargedAtMs int64 `protobuf:"varint,31,opt,name=last_recharged_at_ms,json=lastRechargedAtMs,proto3" json:"last_recharged_at_ms,omitempty"` // paid_at_ms 是 wallet_transactions.created_at_ms 的稳定快照;首次扣费与同 command_id 重放必须完全一致。 // room/lucky 只能用该 wallet owner 事实做 UTC 日、小时和充值后短窗归属,不能用 saga 或恢复 worker 时钟替代。 - PaidAtMs int64 `protobuf:"varint,32,opt,name=paid_at_ms,json=paidAtMs,proto3" json:"paid_at_ms,omitempty"` + PaidAtMs int64 `protobuf:"varint,32,opt,name=paid_at_ms,json=paidAtMs,proto3" json:"paid_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *DebitGiftResponse) Reset() { @@ -650,16 +648,15 @@ func (x *DebitGiftResponse) GetPaidAtMs() int64 { // DebitGiftTarget 是一笔批量送礼中的单个接收方账务快照。 type DebitGiftTarget struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // 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() { @@ -729,23 +726,22 @@ func (x *DebitGiftTarget) GetTargetAgencyOwnerUserId() int64 { // BatchDebitGiftRequest 在一个钱包事务内完成同一 sender 对多个 target 的送礼扣费。 type BatchDebitGiftRequest struct { - 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"` + 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"` EntitlementId string `protobuf:"bytes,11,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` ChargeSource string `protobuf:"bytes,12,opt,name=charge_source,json=chargeSource,proto3" json:"charge_source,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *BatchDebitGiftRequest) Reset() { @@ -864,13 +860,12 @@ func (x *BatchDebitGiftRequest) GetChargeSource() string { // BatchDebitGiftReceipt 保留每个目标独立交易的回执,房间事件按它逐目标落事实。 type BatchDebitGiftReceipt struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *BatchDebitGiftReceipt) Reset() { @@ -926,12 +921,11 @@ func (x *BatchDebitGiftReceipt) GetBilling() *DebitGiftResponse { // BatchDebitGiftResponse 返回批量聚合值和逐目标账务回执。 type BatchDebitGiftResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Aggregate *DebitGiftResponse `protobuf:"bytes,1,opt,name=aggregate,proto3" json:"aggregate,omitempty"` - Receipts []*BatchDebitGiftReceipt `protobuf:"bytes,2,rep,name=receipts,proto3" json:"receipts,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BatchDebitGiftResponse) Reset() { @@ -981,20 +975,19 @@ func (x *BatchDebitGiftResponse) GetReceipts() []*BatchDebitGiftReceipt { // DebitRobotGiftRequest 是机器人房间内部送礼扣费命令。 // 它只扣 ROBOT_COIN,不产生主播钻石、真实充值消费流水或普通礼物墙投影。 type DebitRobotGiftRequest struct { - 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"` - 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"` - RegionId int64 `protobuf:"varint,9,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - SenderRegionId int64 `protobuf:"varint,10,opt,name=sender_region_id,json=senderRegionId,proto3" json:"sender_region_id,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"` + 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"` + 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"` + RegionId int64 `protobuf:"varint,9,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + SenderRegionId int64 `protobuf:"varint,10,opt,name=sender_region_id,json=senderRegionId,proto3" json:"sender_region_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *DebitRobotGiftRequest) Reset() { @@ -1099,15 +1092,14 @@ func (x *DebitRobotGiftRequest) GetSenderRegionId() int64 { // AssetBalance 是用户某类资产的余额投影。 type AssetBalance struct { - 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"` + 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 } func (x *AssetBalance) Reset() { @@ -1177,14 +1169,13 @@ func (x *AssetBalance) GetAppCode() string { // GetBalancesRequest 查询用户多资产余额;内部调用方负责鉴权和用户范围控制。 type GetBalancesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetBalancesRequest) Reset() { @@ -1246,11 +1237,10 @@ func (x *GetBalancesRequest) GetAppCode() string { } type GetBalancesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Balances []*AssetBalance `protobuf:"bytes,1,rep,name=balances,proto3" json:"balances,omitempty"` unknownFields protoimpl.UnknownFields - - Balances []*AssetBalance `protobuf:"bytes,1,rep,name=balances,proto3" json:"balances,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetBalancesResponse) Reset() { @@ -1291,17 +1281,16 @@ func (x *GetBalancesResponse) GetBalances() []*AssetBalance { } type HostSalaryPolicyLevel struct { - 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"` + 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() { @@ -1384,10 +1373,7 @@ func (x *HostSalaryPolicyLevel) GetSortOrder() int32 { } type HostSalaryPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + 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"` @@ -1399,6 +1385,8 @@ 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() { @@ -1509,16 +1497,15 @@ func (x *HostSalaryPolicy) GetLevels() []*HostSalaryPolicyLevel { } type GetActiveHostSalaryPolicyRequest struct { - 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"` + 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() { @@ -1594,12 +1581,11 @@ func (x *GetActiveHostSalaryPolicyRequest) GetNowMs() int64 { } type GetActiveHostSalaryPolicyResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Found bool `protobuf:"varint,1,opt,name=found,proto3" json:"found,omitempty"` - Policy *HostSalaryPolicy `protobuf:"bytes,2,opt,name=policy,proto3" json:"policy,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetActiveHostSalaryPolicyResponse) Reset() { @@ -1647,17 +1633,16 @@ func (x *GetActiveHostSalaryPolicyResponse) GetPolicy() *HostSalaryPolicy { } type HostSalaryProgress struct { - 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"` + 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() { @@ -1740,15 +1725,14 @@ func (x *HostSalaryProgress) GetUpdatedAtMs() int64 { } type GetHostSalaryProgressRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetHostSalaryProgressRequest) Reset() { @@ -1817,11 +1801,10 @@ func (x *GetHostSalaryProgressRequest) GetNowMs() int64 { } type GetHostSalaryProgressResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Progress *HostSalaryProgress `protobuf:"bytes,1,opt,name=progress,proto3" json:"progress,omitempty"` unknownFields protoimpl.UnknownFields - - Progress *HostSalaryProgress `protobuf:"bytes,1,opt,name=progress,proto3" json:"progress,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetHostSalaryProgressResponse) Reset() { @@ -1865,16 +1848,15 @@ func (x *GetHostSalaryProgressResponse) GetProgress() *HostSalaryProgress { // estimated 口径是“预收入”:按当前累计钻石命中的政策档位工资 + 未达下一档剩余钻石按月底费率折美元, // 与已结算累计取大,保证已关闭周期回读时等于真实发放值。 type TeamHostSalaryCycleStat struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - CycleKey string `protobuf:"bytes,1,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` - EstimatedHostSalaryUsdMinor int64 `protobuf:"varint,2,opt,name=estimated_host_salary_usd_minor,json=estimatedHostSalaryUsdMinor,proto3" json:"estimated_host_salary_usd_minor,omitempty"` - SettledHostSalaryUsdMinor int64 `protobuf:"varint,3,opt,name=settled_host_salary_usd_minor,json=settledHostSalaryUsdMinor,proto3" json:"settled_host_salary_usd_minor,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + CycleKey string `protobuf:"bytes,1,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` + EstimatedHostSalaryUsdMinor int64 `protobuf:"varint,2,opt,name=estimated_host_salary_usd_minor,json=estimatedHostSalaryUsdMinor,proto3" json:"estimated_host_salary_usd_minor,omitempty"` + SettledHostSalaryUsdMinor int64 `protobuf:"varint,3,opt,name=settled_host_salary_usd_minor,json=settledHostSalaryUsdMinor,proto3" json:"settled_host_salary_usd_minor,omitempty"` // active_host_count 统计该周期内累计钻石大于 0 的主播数。 ActiveHostCount int32 `protobuf:"varint,4,opt,name=active_host_count,json=activeHostCount,proto3" json:"active_host_count,omitempty"` TotalDiamonds int64 `protobuf:"varint,5,opt,name=total_diamonds,json=totalDiamonds,proto3" json:"total_diamonds,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *TeamHostSalaryCycleStat) Reset() { @@ -1943,17 +1925,16 @@ func (x *TeamHostSalaryCycleStat) GetTotalDiamonds() int64 { } type GetTeamHostSalaryStatsRequest struct { - 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"` + 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"` // agency_owner_user_ids 由调用方(gateway)从 user-service 组织树解析后传入;wallet 只按周期账户上的收款人快照聚合。 AgencyOwnerUserIds []int64 `protobuf:"varint,3,rep,packed,name=agency_owner_user_ids,json=agencyOwnerUserIds,proto3" json:"agency_owner_user_ids,omitempty"` CycleKeys []string `protobuf:"bytes,4,rep,name=cycle_keys,json=cycleKeys,proto3" json:"cycle_keys,omitempty"` // now_ms 用于解析各区域当前生效的工资政策做档位估算。 - NowMs int64 `protobuf:"varint,5,opt,name=now_ms,json=nowMs,proto3" json:"now_ms,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 *GetTeamHostSalaryStatsRequest) Reset() { @@ -2022,12 +2003,11 @@ func (x *GetTeamHostSalaryStatsRequest) GetNowMs() int64 { } type GetTeamHostSalaryStatsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Stats []*TeamHostSalaryCycleStat `protobuf:"bytes,1,rep,name=stats,proto3" json:"stats,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` unknownFields protoimpl.UnknownFields - - Stats []*TeamHostSalaryCycleStat `protobuf:"bytes,1,rep,name=stats,proto3" json:"stats,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetTeamHostSalaryStatsResponse) Reset() { @@ -2076,19 +2056,18 @@ func (x *GetTeamHostSalaryStatsResponse) GetServerTimeMs() int64 { // AdminCreditAssetRequest 是后台手动入账/调账的最小审计命令。 type AdminCreditAssetRequest struct { - 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"` - Remark string `protobuf:"bytes,9,opt,name=remark,proto3" json:"remark,omitempty"` + 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"` + Remark string `protobuf:"bytes,9,opt,name=remark,proto3" json:"remark,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminCreditAssetRequest) Reset() { @@ -2185,12 +2164,11 @@ func (x *AdminCreditAssetRequest) GetRemark() string { } type AdminCreditAssetResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *AdminCreditAssetResponse) Reset() { @@ -2239,23 +2217,22 @@ func (x *AdminCreditAssetResponse) GetBalance() *AssetBalance { // AdminCreditCoinSellerStockRequest 是后台调整币商专用库存的账务命令。 type AdminCreditCoinSellerStockRequest struct { - 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"` + 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"` + 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"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminCreditCoinSellerStockRequest) Reset() { @@ -2380,19 +2357,18 @@ func (x *AdminCreditCoinSellerStockRequest) GetSellerRegionId() int64 { } type AdminCreditCoinSellerStockResponse struct { - 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"` + 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 } func (x *AdminCreditCoinSellerStockResponse) Reset() { @@ -2490,20 +2466,19 @@ func (x *AdminCreditCoinSellerStockResponse) GetCreatedAtMs() int64 { // TransferCoinFromSellerRequest 是币商给玩家转普通金币的内部账务命令。 type TransferCoinFromSellerRequest struct { - 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"` + 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 和 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"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *TransferCoinFromSellerRequest) Reset() { @@ -2601,20 +2576,19 @@ func (x *TransferCoinFromSellerRequest) GetTargetCountryId() int64 { // TransferCoinFromSellerResponse 同时返回金币到账结果和本次转账对应的充值金额口径。 type TransferCoinFromSellerResponse struct { - 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"` + 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 } func (x *TransferCoinFromSellerResponse) Reset() { @@ -2719,17 +2693,16 @@ func (x *TransferCoinFromSellerResponse) GetRechargePolicyUsdMinorAmount() int64 // TransferCoinSellerStockToChildRequest 是父币商向直属子币商转移专用金币库存的内部账务命令。 type TransferCoinSellerStockToChildRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + ParentUserId int64 `protobuf:"varint,2,opt,name=parent_user_id,json=parentUserId,proto3" json:"parent_user_id,omitempty"` + ChildUserId int64 `protobuf:"varint,3,opt,name=child_user_id,json=childUserId,proto3" json:"child_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"` + RegionId int64 `protobuf:"varint,7,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` unknownFields protoimpl.UnknownFields - - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - ParentUserId int64 `protobuf:"varint,2,opt,name=parent_user_id,json=parentUserId,proto3" json:"parent_user_id,omitempty"` - ChildUserId int64 `protobuf:"varint,3,opt,name=child_user_id,json=childUserId,proto3" json:"child_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"` - RegionId int64 `protobuf:"varint,7,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *TransferCoinSellerStockToChildRequest) Reset() { @@ -2812,15 +2785,14 @@ func (x *TransferCoinSellerStockToChildRequest) GetRegionId() int64 { } type TransferCoinSellerStockToChildResponse struct { - 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"` - ParentBalanceAfter int64 `protobuf:"varint,2,opt,name=parent_balance_after,json=parentBalanceAfter,proto3" json:"parent_balance_after,omitempty"` - ChildBalanceAfter int64 `protobuf:"varint,3,opt,name=child_balance_after,json=childBalanceAfter,proto3" json:"child_balance_after,omitempty"` - Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` - CreatedAtMs int64 `protobuf:"varint,5,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + ParentBalanceAfter int64 `protobuf:"varint,2,opt,name=parent_balance_after,json=parentBalanceAfter,proto3" json:"parent_balance_after,omitempty"` + ChildBalanceAfter int64 `protobuf:"varint,3,opt,name=child_balance_after,json=childBalanceAfter,proto3" json:"child_balance_after,omitempty"` + Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` + CreatedAtMs int64 `protobuf:"varint,5,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *TransferCoinSellerStockToChildResponse) Reset() { @@ -2890,17 +2862,16 @@ func (x *TransferCoinSellerStockToChildResponse) GetCreatedAtMs() int64 { // CoinSellerSalaryExchangeRateTier 是用户工资转给币商时,按区域和美元金额命中的金币兑换区间。 type CoinSellerSalaryExchangeRateTier struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *CoinSellerSalaryExchangeRateTier) Reset() { @@ -2983,14 +2954,13 @@ func (x *CoinSellerSalaryExchangeRateTier) GetUpdatedAtMs() int64 { } type ListCoinSellerSalaryExchangeRateTiersRequest struct { - 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"` + 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() { @@ -3052,11 +3022,10 @@ func (x *ListCoinSellerSalaryExchangeRateTiersRequest) GetIncludeDisabled() bool } type ListCoinSellerSalaryExchangeRateTiersResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Tiers []*CoinSellerSalaryExchangeRateTier `protobuf:"bytes,1,rep,name=tiers,proto3" json:"tiers,omitempty"` unknownFields protoimpl.UnknownFields - - Tiers []*CoinSellerSalaryExchangeRateTier `protobuf:"bytes,1,rep,name=tiers,proto3" json:"tiers,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListCoinSellerSalaryExchangeRateTiersResponse) Reset() { @@ -3098,16 +3067,15 @@ func (x *ListCoinSellerSalaryExchangeRateTiersResponse) GetTiers() []*CoinSeller // ExchangeSalaryToCoinRequest 扣当前用户某个身份工资美元钱包,并按固定比例给同一用户加普通 COIN。 type ExchangeSalaryToCoinRequest struct { - 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"` + 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() { @@ -3183,16 +3151,15 @@ func (x *ExchangeSalaryToCoinRequest) GetAppCode() string { } type ExchangeSalaryToCoinResponse struct { - 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"` + 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() { @@ -3269,18 +3236,17 @@ func (x *ExchangeSalaryToCoinResponse) GetCoinPerUsd() int64 { // TransferSalaryToCoinSellerRequest 扣当前用户某个身份工资美元钱包,并按区域区间比例给同区域币商加专用金币库存。 type TransferSalaryToCoinSellerRequest struct { - 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"` + 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() { @@ -3370,18 +3336,17 @@ func (x *TransferSalaryToCoinSellerRequest) GetAppCode() string { } type TransferSalaryToCoinSellerResponse struct { - 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"` + 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() { @@ -3472,17 +3437,16 @@ func (x *TransferSalaryToCoinSellerResponse) GetRateMaxUsdMinor() int64 { // FreezeSalaryWithdrawalRequest 将用户工资美元从可用余额转入冻结余额,等待财务审核。 type FreezeSalaryWithdrawalRequest struct { - 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"` - WithdrawalRef string `protobuf:"bytes,7,opt,name=withdrawal_ref,json=withdrawalRef,proto3" json:"withdrawal_ref,omitempty"` + 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"` + WithdrawalRef string `protobuf:"bytes,7,opt,name=withdrawal_ref,json=withdrawalRef,proto3" json:"withdrawal_ref,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *FreezeSalaryWithdrawalRequest) Reset() { @@ -3565,13 +3529,12 @@ func (x *FreezeSalaryWithdrawalRequest) GetWithdrawalRef() string { } type FreezeSalaryWithdrawalResponse struct { - 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"` - SalaryUsdMinor int64 `protobuf:"varint,3,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` + 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"` + SalaryUsdMinor int64 `protobuf:"varint,3,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *FreezeSalaryWithdrawalResponse) Reset() { @@ -3627,18 +3590,17 @@ func (x *FreezeSalaryWithdrawalResponse) GetSalaryUsdMinor() int64 { // SettleSalaryWithdrawalRequest 在审核通过时扣掉已冻结工资;不会再扣可用余额。 type SettleSalaryWithdrawalRequest struct { - 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"` - 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"` - AppCode string `protobuf:"bytes,7,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - WithdrawalApplicationId string `protobuf:"bytes,8,opt,name=withdrawal_application_id,json=withdrawalApplicationId,proto3" json:"withdrawal_application_id,omitempty"` + 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"` + 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"` + AppCode string `protobuf:"bytes,7,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + WithdrawalApplicationId string `protobuf:"bytes,8,opt,name=withdrawal_application_id,json=withdrawalApplicationId,proto3" json:"withdrawal_application_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SettleSalaryWithdrawalRequest) Reset() { @@ -3728,13 +3690,12 @@ func (x *SettleSalaryWithdrawalRequest) GetWithdrawalApplicationId() string { } type SettleSalaryWithdrawalResponse struct { - 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"` - SalaryUsdMinor int64 `protobuf:"varint,3,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` + 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"` + SalaryUsdMinor int64 `protobuf:"varint,3,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SettleSalaryWithdrawalResponse) Reset() { @@ -3790,18 +3751,17 @@ func (x *SettleSalaryWithdrawalResponse) GetSalaryUsdMinor() int64 { // ReleaseSalaryWithdrawalRequest 在审核拒绝或申请创建失败回滚时把冻结工资返还到可用余额。 type ReleaseSalaryWithdrawalRequest struct { - 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"` - 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"` - AppCode string `protobuf:"bytes,7,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - WithdrawalApplicationId string `protobuf:"bytes,8,opt,name=withdrawal_application_id,json=withdrawalApplicationId,proto3" json:"withdrawal_application_id,omitempty"` + 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"` + 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"` + AppCode string `protobuf:"bytes,7,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + WithdrawalApplicationId string `protobuf:"bytes,8,opt,name=withdrawal_application_id,json=withdrawalApplicationId,proto3" json:"withdrawal_application_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ReleaseSalaryWithdrawalRequest) Reset() { @@ -3891,13 +3851,12 @@ func (x *ReleaseSalaryWithdrawalRequest) GetWithdrawalApplicationId() string { } type ReleaseSalaryWithdrawalResponse struct { - 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"` - SalaryUsdMinor int64 `protobuf:"varint,3,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` + 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"` + SalaryUsdMinor int64 `protobuf:"varint,3,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ReleaseSalaryWithdrawalResponse) Reset() { @@ -3953,12 +3912,9 @@ func (x *ReleaseSalaryWithdrawalResponse) GetSalaryUsdMinor() int64 { // FreezePointWithdrawalRequest 将 Huwaa 策略积分从可用余额冻结到提现审核池。 type FreezePointWithdrawalRequest struct { - 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"` + 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"` // asset_type 只能是 POINT 或 COIN_SELLER_POINT;旧工资美元资产继续使用 SalaryWithdrawal 接口。 AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` // gross_point_amount 是本次冻结的积分总额,Huwaa 普通 POINT 最低 1,000,000。 @@ -3973,6 +3929,8 @@ type FreezePointWithdrawalRequest struct { Reason string `protobuf:"bytes,9,opt,name=reason,proto3" json:"reason,omitempty"` AppCode string `protobuf:"bytes,10,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` WithdrawalRef string `protobuf:"bytes,11,opt,name=withdrawal_ref,json=withdrawalRef,proto3" json:"withdrawal_ref,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *FreezePointWithdrawalRequest) Reset() { @@ -4083,17 +4041,16 @@ func (x *FreezePointWithdrawalRequest) GetWithdrawalRef() string { } type FreezePointWithdrawalResponse struct { - 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"` - GrossPointAmount int64 `protobuf:"varint,3,opt,name=gross_point_amount,json=grossPointAmount,proto3" json:"gross_point_amount,omitempty"` - FeePointAmount int64 `protobuf:"varint,4,opt,name=fee_point_amount,json=feePointAmount,proto3" json:"fee_point_amount,omitempty"` - NetPointAmount int64 `protobuf:"varint,5,opt,name=net_point_amount,json=netPointAmount,proto3" json:"net_point_amount,omitempty"` - PointsPerUsd int64 `protobuf:"varint,6,opt,name=points_per_usd,json=pointsPerUsd,proto3" json:"points_per_usd,omitempty"` - FeeBps int32 `protobuf:"varint,7,opt,name=fee_bps,json=feeBps,proto3" json:"fee_bps,omitempty"` + 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"` + GrossPointAmount int64 `protobuf:"varint,3,opt,name=gross_point_amount,json=grossPointAmount,proto3" json:"gross_point_amount,omitempty"` + FeePointAmount int64 `protobuf:"varint,4,opt,name=fee_point_amount,json=feePointAmount,proto3" json:"fee_point_amount,omitempty"` + NetPointAmount int64 `protobuf:"varint,5,opt,name=net_point_amount,json=netPointAmount,proto3" json:"net_point_amount,omitempty"` + PointsPerUsd int64 `protobuf:"varint,6,opt,name=points_per_usd,json=pointsPerUsd,proto3" json:"points_per_usd,omitempty"` + FeeBps int32 `protobuf:"varint,7,opt,name=fee_bps,json=feeBps,proto3" json:"fee_bps,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *FreezePointWithdrawalResponse) Reset() { @@ -4177,22 +4134,21 @@ func (x *FreezePointWithdrawalResponse) GetFeeBps() int32 { // SettlePointWithdrawalRequest 在审核通过时扣掉已冻结积分;不会再次扣 available。 type SettlePointWithdrawalRequest struct { - 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"` - AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` - GrossPointAmount int64 `protobuf:"varint,4,opt,name=gross_point_amount,json=grossPointAmount,proto3" json:"gross_point_amount,omitempty"` - FeePointAmount int64 `protobuf:"varint,5,opt,name=fee_point_amount,json=feePointAmount,proto3" json:"fee_point_amount,omitempty"` - NetPointAmount int64 `protobuf:"varint,6,opt,name=net_point_amount,json=netPointAmount,proto3" json:"net_point_amount,omitempty"` - PointsPerUsd int64 `protobuf:"varint,7,opt,name=points_per_usd,json=pointsPerUsd,proto3" json:"points_per_usd,omitempty"` - FeeBps int32 `protobuf:"varint,8,opt,name=fee_bps,json=feeBps,proto3" json:"fee_bps,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"` - WithdrawalApplicationId string `protobuf:"bytes,12,opt,name=withdrawal_application_id,json=withdrawalApplicationId,proto3" json:"withdrawal_application_id,omitempty"` + 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"` + AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` + GrossPointAmount int64 `protobuf:"varint,4,opt,name=gross_point_amount,json=grossPointAmount,proto3" json:"gross_point_amount,omitempty"` + FeePointAmount int64 `protobuf:"varint,5,opt,name=fee_point_amount,json=feePointAmount,proto3" json:"fee_point_amount,omitempty"` + NetPointAmount int64 `protobuf:"varint,6,opt,name=net_point_amount,json=netPointAmount,proto3" json:"net_point_amount,omitempty"` + PointsPerUsd int64 `protobuf:"varint,7,opt,name=points_per_usd,json=pointsPerUsd,proto3" json:"points_per_usd,omitempty"` + FeeBps int32 `protobuf:"varint,8,opt,name=fee_bps,json=feeBps,proto3" json:"fee_bps,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"` + WithdrawalApplicationId string `protobuf:"bytes,12,opt,name=withdrawal_application_id,json=withdrawalApplicationId,proto3" json:"withdrawal_application_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SettlePointWithdrawalRequest) Reset() { @@ -4310,17 +4266,16 @@ func (x *SettlePointWithdrawalRequest) GetWithdrawalApplicationId() string { } type SettlePointWithdrawalResponse struct { - 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"` - GrossPointAmount int64 `protobuf:"varint,3,opt,name=gross_point_amount,json=grossPointAmount,proto3" json:"gross_point_amount,omitempty"` - FeePointAmount int64 `protobuf:"varint,4,opt,name=fee_point_amount,json=feePointAmount,proto3" json:"fee_point_amount,omitempty"` - NetPointAmount int64 `protobuf:"varint,5,opt,name=net_point_amount,json=netPointAmount,proto3" json:"net_point_amount,omitempty"` - PointsPerUsd int64 `protobuf:"varint,6,opt,name=points_per_usd,json=pointsPerUsd,proto3" json:"points_per_usd,omitempty"` - FeeBps int32 `protobuf:"varint,7,opt,name=fee_bps,json=feeBps,proto3" json:"fee_bps,omitempty"` + 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"` + GrossPointAmount int64 `protobuf:"varint,3,opt,name=gross_point_amount,json=grossPointAmount,proto3" json:"gross_point_amount,omitempty"` + FeePointAmount int64 `protobuf:"varint,4,opt,name=fee_point_amount,json=feePointAmount,proto3" json:"fee_point_amount,omitempty"` + NetPointAmount int64 `protobuf:"varint,5,opt,name=net_point_amount,json=netPointAmount,proto3" json:"net_point_amount,omitempty"` + PointsPerUsd int64 `protobuf:"varint,6,opt,name=points_per_usd,json=pointsPerUsd,proto3" json:"points_per_usd,omitempty"` + FeeBps int32 `protobuf:"varint,7,opt,name=fee_bps,json=feeBps,proto3" json:"fee_bps,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SettlePointWithdrawalResponse) Reset() { @@ -4404,22 +4359,21 @@ func (x *SettlePointWithdrawalResponse) GetFeeBps() int32 { // ReleasePointWithdrawalRequest 在审核拒绝或申请创建失败时释放冻结积分。 type ReleasePointWithdrawalRequest struct { - 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"` - AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` - GrossPointAmount int64 `protobuf:"varint,4,opt,name=gross_point_amount,json=grossPointAmount,proto3" json:"gross_point_amount,omitempty"` - FeePointAmount int64 `protobuf:"varint,5,opt,name=fee_point_amount,json=feePointAmount,proto3" json:"fee_point_amount,omitempty"` - NetPointAmount int64 `protobuf:"varint,6,opt,name=net_point_amount,json=netPointAmount,proto3" json:"net_point_amount,omitempty"` - PointsPerUsd int64 `protobuf:"varint,7,opt,name=points_per_usd,json=pointsPerUsd,proto3" json:"points_per_usd,omitempty"` - FeeBps int32 `protobuf:"varint,8,opt,name=fee_bps,json=feeBps,proto3" json:"fee_bps,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"` - WithdrawalApplicationId string `protobuf:"bytes,12,opt,name=withdrawal_application_id,json=withdrawalApplicationId,proto3" json:"withdrawal_application_id,omitempty"` + 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"` + AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` + GrossPointAmount int64 `protobuf:"varint,4,opt,name=gross_point_amount,json=grossPointAmount,proto3" json:"gross_point_amount,omitempty"` + FeePointAmount int64 `protobuf:"varint,5,opt,name=fee_point_amount,json=feePointAmount,proto3" json:"fee_point_amount,omitempty"` + NetPointAmount int64 `protobuf:"varint,6,opt,name=net_point_amount,json=netPointAmount,proto3" json:"net_point_amount,omitempty"` + PointsPerUsd int64 `protobuf:"varint,7,opt,name=points_per_usd,json=pointsPerUsd,proto3" json:"points_per_usd,omitempty"` + FeeBps int32 `protobuf:"varint,8,opt,name=fee_bps,json=feeBps,proto3" json:"fee_bps,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"` + WithdrawalApplicationId string `protobuf:"bytes,12,opt,name=withdrawal_application_id,json=withdrawalApplicationId,proto3" json:"withdrawal_application_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ReleasePointWithdrawalRequest) Reset() { @@ -4537,17 +4491,16 @@ func (x *ReleasePointWithdrawalRequest) GetWithdrawalApplicationId() string { } type ReleasePointWithdrawalResponse struct { - 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"` - GrossPointAmount int64 `protobuf:"varint,3,opt,name=gross_point_amount,json=grossPointAmount,proto3" json:"gross_point_amount,omitempty"` - FeePointAmount int64 `protobuf:"varint,4,opt,name=fee_point_amount,json=feePointAmount,proto3" json:"fee_point_amount,omitempty"` - NetPointAmount int64 `protobuf:"varint,5,opt,name=net_point_amount,json=netPointAmount,proto3" json:"net_point_amount,omitempty"` - PointsPerUsd int64 `protobuf:"varint,6,opt,name=points_per_usd,json=pointsPerUsd,proto3" json:"points_per_usd,omitempty"` - FeeBps int32 `protobuf:"varint,7,opt,name=fee_bps,json=feeBps,proto3" json:"fee_bps,omitempty"` + 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"` + GrossPointAmount int64 `protobuf:"varint,3,opt,name=gross_point_amount,json=grossPointAmount,proto3" json:"gross_point_amount,omitempty"` + FeePointAmount int64 `protobuf:"varint,4,opt,name=fee_point_amount,json=feePointAmount,proto3" json:"fee_point_amount,omitempty"` + NetPointAmount int64 `protobuf:"varint,5,opt,name=net_point_amount,json=netPointAmount,proto3" json:"net_point_amount,omitempty"` + PointsPerUsd int64 `protobuf:"varint,6,opt,name=points_per_usd,json=pointsPerUsd,proto3" json:"points_per_usd,omitempty"` + FeeBps int32 `protobuf:"varint,7,opt,name=fee_bps,json=feeBps,proto3" json:"fee_bps,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ReleasePointWithdrawalResponse) Reset() { @@ -4631,35 +4584,34 @@ func (x *ReleasePointWithdrawalResponse) GetFeeBps() int32 { // Resource 是资源库里可配置、可赠送、可被礼物引用的最小资源。 type Resource struct { - 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"` + 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"` // 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() { @@ -4861,22 +4813,21 @@ func (x *Resource) GetGiftPointAmount() int64 { } type ResourceGroupItem struct { - 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"` + 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 } func (x *ResourceGroupItem) Reset() { @@ -4994,22 +4945,21 @@ func (x *ResourceGroupItem) GetWalletAssetAmount() int64 { } type ResourceGroup struct { - 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"` + 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 } func (x *ResourceGroup) Reset() { @@ -5129,22 +5079,21 @@ func (x *ResourceGroup) GetUpdatedAtMs() int64 { // ResourceGroupSnapshot 是 owner 在业务发布时钉住的不可变奖励承诺。后续资源组编辑、停用 // 或资源展示信息变化都不会改变 snapshot_id 对应的实际发放内容和 App 展示内容。 type ResourceGroupSnapshot struct { - 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"` - SnapshotId string `protobuf:"bytes,2,opt,name=snapshot_id,json=snapshotId,proto3" json:"snapshot_id,omitempty"` - PinKey string `protobuf:"bytes,3,opt,name=pin_key,json=pinKey,proto3" json:"pin_key,omitempty"` - SourceGroupId int64 `protobuf:"varint,4,opt,name=source_group_id,json=sourceGroupId,proto3" json:"source_group_id,omitempty"` - VersionNo int64 `protobuf:"varint,5,opt,name=version_no,json=versionNo,proto3" json:"version_no,omitempty"` - SnapshotHash string `protobuf:"bytes,6,opt,name=snapshot_hash,json=snapshotHash,proto3" json:"snapshot_hash,omitempty"` - Group *ResourceGroup `protobuf:"bytes,7,opt,name=group,proto3" json:"group,omitempty"` - CreatedByUserId int64 `protobuf:"varint,8,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,9,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - SourceGroupUpdatedAtMs int64 `protobuf:"varint,10,opt,name=source_group_updated_at_ms,json=sourceGroupUpdatedAtMs,proto3" json:"source_group_updated_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + SnapshotId string `protobuf:"bytes,2,opt,name=snapshot_id,json=snapshotId,proto3" json:"snapshot_id,omitempty"` + PinKey string `protobuf:"bytes,3,opt,name=pin_key,json=pinKey,proto3" json:"pin_key,omitempty"` + SourceGroupId int64 `protobuf:"varint,4,opt,name=source_group_id,json=sourceGroupId,proto3" json:"source_group_id,omitempty"` + VersionNo int64 `protobuf:"varint,5,opt,name=version_no,json=versionNo,proto3" json:"version_no,omitempty"` + SnapshotHash string `protobuf:"bytes,6,opt,name=snapshot_hash,json=snapshotHash,proto3" json:"snapshot_hash,omitempty"` + Group *ResourceGroup `protobuf:"bytes,7,opt,name=group,proto3" json:"group,omitempty"` + CreatedByUserId int64 `protobuf:"varint,8,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,9,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + SourceGroupUpdatedAtMs int64 `protobuf:"varint,10,opt,name=source_group_updated_at_ms,json=sourceGroupUpdatedAtMs,proto3" json:"source_group_updated_at_ms,omitempty"` // source_content_hash 覆盖资源组、组项和嵌套资源的完整规范化内容;成员资源独立编辑也会改变该值。 SourceContentHash string `protobuf:"bytes,11,opt,name=source_content_hash,json=sourceContentHash,proto3" json:"source_content_hash,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ResourceGroupSnapshot) Reset() { @@ -5255,13 +5204,10 @@ func (x *ResourceGroupSnapshot) GetSourceContentHash() string { } type PinResourceGroupSnapshotRequest struct { - 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"` + 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"` // pin_key 由发布方按业务版本生成;重试同一 key 必须返回同一快照。 PinKey string `protobuf:"bytes,4,opt,name=pin_key,json=pinKey,proto3" json:"pin_key,omitempty"` OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` @@ -5274,6 +5220,8 @@ type PinResourceGroupSnapshotRequest struct { RequiredRegionIds []int64 `protobuf:"varint,8,rep,packed,name=required_region_ids,json=requiredRegionIds,proto3" json:"required_region_ids,omitempty"` // required_all_regions=true 时必须存在 region_id=0 的 pin-time gift config,确保发布后新增区域也可用。 RequiredAllRegions bool `protobuf:"varint,9,opt,name=required_all_regions,json=requiredAllRegions,proto3" json:"required_all_regions,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *PinResourceGroupSnapshotRequest) Reset() { @@ -5370,11 +5318,10 @@ func (x *PinResourceGroupSnapshotRequest) GetRequiredAllRegions() bool { } type PinResourceGroupSnapshotResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Snapshot *ResourceGroupSnapshot `protobuf:"bytes,1,opt,name=snapshot,proto3" json:"snapshot,omitempty"` unknownFields protoimpl.UnknownFields - - Snapshot *ResourceGroupSnapshot `protobuf:"bytes,1,opt,name=snapshot,proto3" json:"snapshot,omitempty"` + sizeCache protoimpl.SizeCache } func (x *PinResourceGroupSnapshotResponse) Reset() { @@ -5415,20 +5362,17 @@ func (x *PinResourceGroupSnapshotResponse) GetSnapshot() *ResourceGroupSnapshot } type GiftConfig struct { - 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"` + 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"` // 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"` @@ -5443,6 +5387,8 @@ type GiftConfig struct { 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"` CpRelationType string `protobuf:"bytes,23,opt,name=cp_relation_type,json=cpRelationType,proto3" json:"cp_relation_type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GiftConfig) Reset() { @@ -5637,20 +5583,19 @@ func (x *GiftConfig) GetCpRelationType() string { } type GiftTypeConfig struct { - 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"` + 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 } func (x *GiftTypeConfig) Reset() { @@ -5754,25 +5699,24 @@ func (x *GiftTypeConfig) GetUpdatedAtMs() int64 { } type ResourceShopItem struct { - 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"` + 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 } func (x *ResourceShopItem) Reset() { @@ -5911,29 +5855,28 @@ func (x *ResourceShopItem) GetUpdatedAtMs() int64 { } type UserResourceEntitlement struct { - 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"` - SourceSnapshotId string `protobuf:"bytes,15,opt,name=source_snapshot_id,json=sourceSnapshotId,proto3" json:"source_snapshot_id,omitempty"` - ResourceSnapshotHash string `protobuf:"bytes,16,opt,name=resource_snapshot_hash,json=resourceSnapshotHash,proto3" json:"resource_snapshot_hash,omitempty"` + 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"` + SourceSnapshotId string `protobuf:"bytes,15,opt,name=source_snapshot_id,json=sourceSnapshotId,proto3" json:"source_snapshot_id,omitempty"` + ResourceSnapshotHash string `protobuf:"bytes,16,opt,name=resource_snapshot_hash,json=resourceSnapshotHash,proto3" json:"resource_snapshot_hash,omitempty"` // pinned_gift_configs 仅在 source_snapshot_id 非空且资源类型为 gift 时返回。内容已由 wallet // 校验 hash/resource/app 绑定,App 背包必须优先使用它,legacy entitlement 才回退当前目录。 PinnedGiftConfigs []*GiftConfig `protobuf:"bytes,17,rep,name=pinned_gift_configs,json=pinnedGiftConfigs,proto3" json:"pinned_gift_configs,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *UserResourceEntitlement) Reset() { @@ -6086,20 +6029,19 @@ func (x *UserResourceEntitlement) GetPinnedGiftConfigs() []*GiftConfig { } type ResourceGrantItem struct { - 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"` + 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 } func (x *ResourceGrantItem) Reset() { @@ -6203,26 +6145,25 @@ func (x *ResourceGrantItem) GetCreatedAtMs() int64 { } type ResourceGrant struct { - 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"` - RevokedAtMs int64 `protobuf:"varint,14,opt,name=revoked_at_ms,json=revokedAtMs,proto3" json:"revoked_at_ms,omitempty"` - RevokedByUserId int64 `protobuf:"varint,15,opt,name=revoked_by_user_id,json=revokedByUserId,proto3" json:"revoked_by_user_id,omitempty"` - RevokeReason string `protobuf:"bytes,16,opt,name=revoke_reason,json=revokeReason,proto3" json:"revoke_reason,omitempty"` + 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"` + RevokedAtMs int64 `protobuf:"varint,14,opt,name=revoked_at_ms,json=revokedAtMs,proto3" json:"revoked_at_ms,omitempty"` + RevokedByUserId int64 `protobuf:"varint,15,opt,name=revoked_by_user_id,json=revokedByUserId,proto3" json:"revoked_by_user_id,omitempty"` + RevokeReason string `protobuf:"bytes,16,opt,name=revoke_reason,json=revokeReason,proto3" json:"revoke_reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ResourceGrant) Reset() { @@ -6368,17 +6309,16 @@ func (x *ResourceGrant) GetRevokeReason() string { } type ResourceGroupItemInput struct { - 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"` + 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 } func (x *ResourceGroupItemInput) Reset() { @@ -6461,19 +6401,18 @@ func (x *ResourceGroupItemInput) GetWalletAssetAmount() int64 { } type ListResourcesRequest struct { - 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"` + 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 } func (x *ListResourcesRequest) Reset() { @@ -6570,12 +6509,11 @@ func (x *ListResourcesRequest) GetManagerGrantOnly() bool { } type ListResourcesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Resources []*Resource `protobuf:"bytes,1,rep,name=resources,proto3" json:"resources,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListResourcesResponse) Reset() { @@ -6623,13 +6561,12 @@ func (x *ListResourcesResponse) GetTotal() int64 { } type GetResourceRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetResourceRequest) Reset() { @@ -6684,11 +6621,10 @@ func (x *GetResourceRequest) GetResourceId() int64 { } type GetResourceResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Resource *Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` unknownFields protoimpl.UnknownFields - - Resource *Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetResourceResponse) Reset() { @@ -6729,32 +6665,31 @@ func (x *GetResourceResponse) GetResource() *Resource { } type CreateResourceRequest struct { - 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"` + 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"` // 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() { @@ -6935,33 +6870,32 @@ func (x *CreateResourceRequest) GetGiftPointAmount() int64 { } type UpdateResourceRequest struct { - 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"` + 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"` // 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() { @@ -7149,15 +7083,14 @@ func (x *UpdateResourceRequest) GetGiftPointAmount() int64 { } type SetResourceStatusRequest struct { - 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"` + 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 } func (x *SetResourceStatusRequest) Reset() { @@ -7226,14 +7159,13 @@ func (x *SetResourceStatusRequest) GetOperatorUserId() int64 { } type DeleteResourceRequest struct { - 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"` - OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + 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"` + 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 *DeleteResourceRequest) Reset() { @@ -7295,14 +7227,13 @@ func (x *DeleteResourceRequest) GetOperatorUserId() int64 { } type BatchDeleteResourcesRequest struct { - 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"` - ResourceIds []int64 `protobuf:"varint,3,rep,packed,name=resource_ids,json=resourceIds,proto3" json:"resource_ids,omitempty"` - OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + 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"` + ResourceIds []int64 `protobuf:"varint,3,rep,packed,name=resource_ids,json=resourceIds,proto3" json:"resource_ids,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 *BatchDeleteResourcesRequest) Reset() { @@ -7364,11 +7295,10 @@ func (x *BatchDeleteResourcesRequest) GetOperatorUserId() int64 { } type BatchDeleteResourcesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Resources []*Resource `protobuf:"bytes,1,rep,name=resources,proto3" json:"resources,omitempty"` unknownFields protoimpl.UnknownFields - - Resources []*Resource `protobuf:"bytes,1,rep,name=resources,proto3" json:"resources,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BatchDeleteResourcesResponse) Reset() { @@ -7409,11 +7339,10 @@ func (x *BatchDeleteResourcesResponse) GetResources() []*Resource { } type ResourceResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Resource *Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` unknownFields protoimpl.UnknownFields - - Resource *Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ResourceResponse) Reset() { @@ -7454,17 +7383,16 @@ func (x *ResourceResponse) GetResource() *Resource { } type ListResourceGroupsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListResourceGroupsRequest) Reset() { @@ -7547,12 +7475,11 @@ func (x *ListResourceGroupsRequest) GetActiveOnly() bool { } type ListResourceGroupsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Groups []*ResourceGroup `protobuf:"bytes,1,rep,name=groups,proto3" json:"groups,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListResourceGroupsResponse) Reset() { @@ -7600,13 +7527,12 @@ func (x *ListResourceGroupsResponse) GetTotal() int64 { } type GetResourceGroupRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetResourceGroupRequest) Reset() { @@ -7661,13 +7587,12 @@ func (x *GetResourceGroupRequest) GetGroupId() int64 { } type GetResourceGroupResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Group *ResourceGroup `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Group *ResourceGroup `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"` // 对 group、ordered items 和嵌套 resource 的规范化 SHA-256。 SourceContentHash string `protobuf:"bytes,2,opt,name=source_content_hash,json=sourceContentHash,proto3" json:"source_content_hash,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GetResourceGroupResponse) Reset() { @@ -7715,10 +7640,7 @@ func (x *GetResourceGroupResponse) GetSourceContentHash() string { } type CreateResourceGroupRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + 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"` GroupCode string `protobuf:"bytes,3,opt,name=group_code,json=groupCode,proto3" json:"group_code,omitempty"` @@ -7728,6 +7650,8 @@ 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() { @@ -7824,10 +7748,7 @@ func (x *CreateResourceGroupRequest) GetOperatorUserId() int64 { } type UpdateResourceGroupRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + 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"` @@ -7838,6 +7759,8 @@ 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() { @@ -7941,15 +7864,14 @@ func (x *UpdateResourceGroupRequest) GetOperatorUserId() int64 { } type SetResourceGroupStatusRequest struct { - 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"` + 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 } func (x *SetResourceGroupStatusRequest) Reset() { @@ -8018,11 +7940,10 @@ func (x *SetResourceGroupStatusRequest) GetOperatorUserId() int64 { } type ResourceGroupResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Group *ResourceGroup `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"` unknownFields protoimpl.UnknownFields - - Group *ResourceGroup `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ResourceGroupResponse) Reset() { @@ -8063,20 +7984,19 @@ func (x *ResourceGroupResponse) GetGroup() *ResourceGroup { } type ListGiftConfigsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListGiftConfigsRequest) Reset() { @@ -8180,12 +8100,11 @@ func (x *ListGiftConfigsRequest) GetGiftTypeCode() string { } type ListGiftConfigsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Gifts []*GiftConfig `protobuf:"bytes,1,rep,name=gifts,proto3" json:"gifts,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListGiftConfigsResponse) Reset() { @@ -8233,14 +8152,13 @@ func (x *ListGiftConfigsResponse) GetTotal() int64 { } type ListGiftTypeConfigsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListGiftTypeConfigsRequest) Reset() { @@ -8302,11 +8220,10 @@ func (x *ListGiftTypeConfigsRequest) GetActiveOnly() bool { } type ListGiftTypeConfigsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - GiftTypes []*GiftTypeConfig `protobuf:"bytes,1,rep,name=gift_types,json=giftTypes,proto3" json:"gift_types,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListGiftTypeConfigsResponse) Reset() { @@ -8347,18 +8264,17 @@ func (x *ListGiftTypeConfigsResponse) GetGiftTypes() []*GiftTypeConfig { } type UpsertGiftTypeConfigRequest struct { - 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"` + 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 } func (x *UpsertGiftTypeConfigRequest) Reset() { @@ -8448,11 +8364,10 @@ func (x *UpsertGiftTypeConfigRequest) GetOperatorUserId() int64 { } type GiftTypeConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - GiftType *GiftTypeConfig `protobuf:"bytes,1,opt,name=gift_type,json=giftType,proto3" json:"gift_type,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GiftTypeConfigResponse) Reset() { @@ -8493,20 +8408,17 @@ func (x *GiftTypeConfigResponse) GetGiftType() *GiftTypeConfig { } type CreateGiftConfigRequest struct { - 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"` + 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"` // 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"` @@ -8519,6 +8431,8 @@ type CreateGiftConfigRequest struct { 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"` CpRelationType string `protobuf:"bytes,21,opt,name=cp_relation_type,json=cpRelationType,proto3" json:"cp_relation_type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CreateGiftConfigRequest) Reset() { @@ -8699,14 +8613,13 @@ func (x *CreateGiftConfigRequest) GetCpRelationType() string { } type BatchCreateGiftConfigsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + 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"` Items []*CreateGiftConfigRequest `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 *BatchCreateGiftConfigsRequest) Reset() { @@ -8768,11 +8681,10 @@ func (x *BatchCreateGiftConfigsRequest) GetOperatorUserId() int64 { } type BatchCreateGiftConfigsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Gifts []*GiftConfig `protobuf:"bytes,1,rep,name=gifts,proto3" json:"gifts,omitempty"` unknownFields protoimpl.UnknownFields - - Gifts []*GiftConfig `protobuf:"bytes,1,rep,name=gifts,proto3" json:"gifts,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BatchCreateGiftConfigsResponse) Reset() { @@ -8813,20 +8725,17 @@ func (x *BatchCreateGiftConfigsResponse) GetGifts() []*GiftConfig { } type UpdateGiftConfigRequest struct { - 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"` + 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"` // 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"` @@ -8839,6 +8748,8 @@ type UpdateGiftConfigRequest struct { 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"` CpRelationType string `protobuf:"bytes,21,opt,name=cp_relation_type,json=cpRelationType,proto3" json:"cp_relation_type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *UpdateGiftConfigRequest) Reset() { @@ -9019,15 +8930,14 @@ func (x *UpdateGiftConfigRequest) GetCpRelationType() string { } type SetGiftConfigStatusRequest struct { - 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"` + 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 } func (x *SetGiftConfigStatusRequest) Reset() { @@ -9096,14 +9006,13 @@ func (x *SetGiftConfigStatusRequest) GetOperatorUserId() int64 { } type DeleteGiftConfigRequest struct { - 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"` - OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + 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"` + 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 *DeleteGiftConfigRequest) Reset() { @@ -9165,11 +9074,10 @@ func (x *DeleteGiftConfigRequest) GetOperatorUserId() int64 { } type GiftConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Gift *GiftConfig `protobuf:"bytes,1,opt,name=gift,proto3" json:"gift,omitempty"` unknownFields protoimpl.UnknownFields - - Gift *GiftConfig `protobuf:"bytes,1,opt,name=gift,proto3" json:"gift,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GiftConfigResponse) Reset() { @@ -9210,19 +9118,18 @@ func (x *GiftConfigResponse) GetGift() *GiftConfig { } type GrantResourceRequest struct { - 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"` + 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 } func (x *GrantResourceRequest) Reset() { @@ -9319,17 +9226,16 @@ func (x *GrantResourceRequest) GetGrantSource() string { } type GrantResourceGroupRequest struct { - 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"` + 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 } func (x *GrantResourceGroupRequest) Reset() { @@ -9412,19 +9318,18 @@ func (x *GrantResourceGroupRequest) GetGrantSource() string { } type GrantPinnedResourceGroupRequest struct { - 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"` - SnapshotId string `protobuf:"bytes,4,opt,name=snapshot_id,json=snapshotId,proto3" json:"snapshot_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"` + 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"` + SnapshotId string `protobuf:"bytes,4,opt,name=snapshot_id,json=snapshotId,proto3" json:"snapshot_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"` // 发布版本持有的快照哈希;wallet 必须与 snapshot_id 对应的 owner 快照精确匹配。 ExpectedSnapshotHash string `protobuf:"bytes,8,opt,name=expected_snapshot_hash,json=expectedSnapshotHash,proto3" json:"expected_snapshot_hash,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GrantPinnedResourceGroupRequest) Reset() { @@ -9514,15 +9419,14 @@ func (x *GrantPinnedResourceGroupRequest) GetExpectedSnapshotHash() string { } type RevokeResourceGrantRequest struct { - 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"` - GrantId string `protobuf:"bytes,3,opt,name=grant_id,json=grantId,proto3" json:"grant_id,omitempty"` - Reason string `protobuf:"bytes,4,opt,name=reason,proto3" json:"reason,omitempty"` - OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + 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"` + GrantId string `protobuf:"bytes,3,opt,name=grant_id,json=grantId,proto3" json:"grant_id,omitempty"` + Reason string `protobuf:"bytes,4,opt,name=reason,proto3" json:"reason,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 } func (x *RevokeResourceGrantRequest) Reset() { @@ -9591,11 +9495,10 @@ func (x *RevokeResourceGrantRequest) GetOperatorUserId() int64 { } type ResourceGrantResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Grant *ResourceGrant `protobuf:"bytes,1,opt,name=grant,proto3" json:"grant,omitempty"` unknownFields protoimpl.UnknownFields - - Grant *ResourceGrant `protobuf:"bytes,1,opt,name=grant,proto3" json:"grant,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ResourceGrantResponse) Reset() { @@ -9636,15 +9539,14 @@ func (x *ResourceGrantResponse) GetGrant() *ResourceGrant { } type ListUserResourcesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListUserResourcesRequest) Reset() { @@ -9713,11 +9615,10 @@ func (x *ListUserResourcesRequest) GetActiveOnly() bool { } type ListUserResourcesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Resources []*UserResourceEntitlement `protobuf:"bytes,1,rep,name=resources,proto3" json:"resources,omitempty"` unknownFields protoimpl.UnknownFields - - Resources []*UserResourceEntitlement `protobuf:"bytes,1,rep,name=resources,proto3" json:"resources,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListUserResourcesResponse) Reset() { @@ -9758,15 +9659,14 @@ func (x *ListUserResourcesResponse) GetResources() []*UserResourceEntitlement { } type EquipUserResourceRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *EquipUserResourceRequest) Reset() { @@ -9835,11 +9735,10 @@ func (x *EquipUserResourceRequest) GetEntitlementId() string { } type EquipUserResourceResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Resource *UserResourceEntitlement `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` unknownFields protoimpl.UnknownFields - - Resource *UserResourceEntitlement `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` + sizeCache protoimpl.SizeCache } func (x *EquipUserResourceResponse) Reset() { @@ -9880,14 +9779,13 @@ func (x *EquipUserResourceResponse) GetResource() *UserResourceEntitlement { } type UnequipUserResourceRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *UnequipUserResourceRequest) Reset() { @@ -9949,13 +9847,12 @@ func (x *UnequipUserResourceRequest) GetResourceType() string { } type UnequipUserResourceResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *UnequipUserResourceResponse) Reset() { @@ -10010,14 +9907,13 @@ func (x *UnequipUserResourceResponse) GetUpdatedAtMs() int64 { } type BatchGetUserEquippedResourcesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *BatchGetUserEquippedResourcesRequest) Reset() { @@ -10079,12 +9975,11 @@ func (x *BatchGetUserEquippedResourcesRequest) GetResourceTypes() []string { } type UserEquippedResources struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *UserEquippedResources) Reset() { @@ -10132,11 +10027,10 @@ func (x *UserEquippedResources) GetResources() []*UserResourceEntitlement { } type BatchGetUserEquippedResourcesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Users []*UserEquippedResources `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` unknownFields protoimpl.UnknownFields - - Users []*UserEquippedResources `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BatchGetUserEquippedResourcesResponse) Reset() { @@ -10177,16 +10071,15 @@ func (x *BatchGetUserEquippedResourcesResponse) GetUsers() []*UserEquippedResour } type ListResourceGrantsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListResourceGrantsRequest) Reset() { @@ -10262,12 +10155,11 @@ func (x *ListResourceGrantsRequest) GetPageSize() int32 { } type ListResourceGrantsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Grants []*ResourceGrant `protobuf:"bytes,1,rep,name=grants,proto3" json:"grants,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListResourceGrantsResponse) Reset() { @@ -10315,17 +10207,18 @@ func (x *ListResourceGrantsResponse) GetTotal() int64 { } type ResourceShopItemInput struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + // coin_price 是当前售卖规格自己的金币价;新建传 0 使用资源列表价,更新已有规格传 0 保留当前售价。 + CoinPrice int64 `protobuf:"varint,8,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` 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"` + sizeCache protoimpl.SizeCache } func (x *ResourceShopItemInput) Reset() { @@ -10407,19 +10300,25 @@ func (x *ResourceShopItemInput) GetSortOrder() int32 { return 0 } -type ListResourceShopItemsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields +func (x *ResourceShopItemInput) GetCoinPrice() int64 { + if x != nil { + return x.CoinPrice + } + return 0 +} - 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"` +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 + sizeCache protoimpl.SizeCache } func (x *ListResourceShopItemsRequest) Reset() { @@ -10509,12 +10408,11 @@ func (x *ListResourceShopItemsRequest) GetActiveOnly() bool { } type ListResourceShopItemsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Items []*ResourceShopItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListResourceShopItemsResponse) Reset() { @@ -10562,14 +10460,13 @@ func (x *ListResourceShopItemsResponse) GetTotal() int64 { } type UpsertResourceShopItemsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + 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"` 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() { @@ -10631,11 +10528,10 @@ func (x *UpsertResourceShopItemsRequest) GetOperatorUserId() int64 { } type UpsertResourceShopItemsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Items []*ResourceShopItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` unknownFields protoimpl.UnknownFields - - Items []*ResourceShopItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UpsertResourceShopItemsResponse) Reset() { @@ -10676,15 +10572,14 @@ func (x *UpsertResourceShopItemsResponse) GetItems() []*ResourceShopItem { } type SetResourceShopItemStatusRequest struct { - 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"` + 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 } func (x *SetResourceShopItemStatusRequest) Reset() { @@ -10753,11 +10648,10 @@ func (x *SetResourceShopItemStatusRequest) GetOperatorUserId() int64 { } type ResourceShopItemResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Item *ResourceShopItem `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` unknownFields protoimpl.UnknownFields - - Item *ResourceShopItem `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ResourceShopItemResponse) Reset() { @@ -10798,14 +10692,13 @@ func (x *ResourceShopItemResponse) GetItem() *ResourceShopItem { } type PurchaseResourceShopItemRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *PurchaseResourceShopItemRequest) Reset() { @@ -10867,10 +10760,7 @@ func (x *PurchaseResourceShopItemRequest) GetShopItemId() int64 { } type PurchaseResourceShopItemResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + 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"` ResourceGrantId string `protobuf:"bytes,3,opt,name=resource_grant_id,json=resourceGrantId,proto3" json:"resource_grant_id,omitempty"` @@ -10878,6 +10768,8 @@ 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() { @@ -10960,29 +10852,26 @@ func (x *PurchaseResourceShopItemResponse) GetCoinSpent() int64 { } type RechargeBill struct { - 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"` - ProviderAmountMinor int64 `protobuf:"varint,19,opt,name=provider_amount_minor,json=providerAmountMinor,proto3" json:"provider_amount_minor,omitempty"` + 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"` + ProviderAmountMinor int64 `protobuf:"varint,19,opt,name=provider_amount_minor,json=providerAmountMinor,proto3" json:"provider_amount_minor,omitempty"` // provider_code 标识账单实际支付渠道:google_play/mifapay/v5pay/usdt_trc20。 ProviderCode string `protobuf:"bytes,20,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` // user_paid_* 是用户实付事实:外部订单来自三方下单快照,Google 订单来自 Play Orders API。 @@ -10994,6 +10883,8 @@ type RechargeBill struct { ProviderNetMicro int64 `protobuf:"varint,25,opt,name=provider_net_micro,json=providerNetMicro,proto3" json:"provider_net_micro,omitempty"` // paid_synced_at_ms 仅对 Google 账单有意义:Orders API 实付明细的同步时间,0 表示未同步。 PaidSyncedAtMs int64 `protobuf:"varint,26,opt,name=paid_synced_at_ms,json=paidSyncedAtMs,proto3" json:"paid_synced_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RechargeBill) Reset() { @@ -11209,24 +11100,23 @@ func (x *RechargeBill) GetPaidSyncedAtMs() int64 { } type ListRechargeBillsRequest struct { - 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"` + 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"` // paid_state=unsynced 只看实付明细未同步的谷歌账单(财务补数视图)。 - PaidState string `protobuf:"bytes,13,opt,name=paid_state,json=paidState,proto3" json:"paid_state,omitempty"` + PaidState string `protobuf:"bytes,13,opt,name=paid_state,json=paidState,proto3" json:"paid_state,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListRechargeBillsRequest) Reset() { @@ -11351,12 +11241,11 @@ func (x *ListRechargeBillsRequest) GetPaidState() string { } type ListRechargeBillsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Bills []*RechargeBill `protobuf:"bytes,1,rep,name=bills,proto3" json:"bills,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListRechargeBillsResponse) Reset() { @@ -11404,20 +11293,19 @@ func (x *ListRechargeBillsResponse) GetTotal() int64 { } type GetRechargeBillSummaryRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` 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"` + sizeCache protoimpl.SizeCache } func (x *GetRechargeBillSummaryRequest) Reset() { @@ -11521,13 +11409,12 @@ func (x *GetRechargeBillSummaryRequest) GetEndAtMs() int64 { } type RechargeBillSummaryBucket struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BillCount int64 `protobuf:"varint,1,opt,name=bill_count,json=billCount,proto3" json:"bill_count,omitempty"` - CoinAmount int64 `protobuf:"varint,2,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - UsdMinorAmount int64 `protobuf:"varint,3,opt,name=usd_minor_amount,json=usdMinorAmount,proto3" json:"usd_minor_amount,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + BillCount int64 `protobuf:"varint,1,opt,name=bill_count,json=billCount,proto3" json:"bill_count,omitempty"` + CoinAmount int64 `protobuf:"varint,2,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + UsdMinorAmount int64 `protobuf:"varint,3,opt,name=usd_minor_amount,json=usdMinorAmount,proto3" json:"usd_minor_amount,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RechargeBillSummaryBucket) Reset() { @@ -11582,15 +11469,14 @@ func (x *RechargeBillSummaryBucket) GetUsdMinorAmount() int64 { } type GetRechargeBillSummaryResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` Total *RechargeBillSummaryBucket `protobuf:"bytes,1,opt,name=total,proto3" json:"total,omitempty"` GooglePlay *RechargeBillSummaryBucket `protobuf:"bytes,2,opt,name=google_play,json=googlePlay,proto3" json:"google_play,omitempty"` ThirdParty *RechargeBillSummaryBucket `protobuf:"bytes,3,opt,name=third_party,json=thirdParty,proto3" json:"third_party,omitempty"` // coin_seller 是币商进货口径:coin_seller_stock_records 里 counts_as_seller_recharge 的进货与冲回净额。 - CoinSeller *RechargeBillSummaryBucket `protobuf:"bytes,4,opt,name=coin_seller,json=coinSeller,proto3" json:"coin_seller,omitempty"` + CoinSeller *RechargeBillSummaryBucket `protobuf:"bytes,4,opt,name=coin_seller,json=coinSeller,proto3" json:"coin_seller,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GetRechargeBillSummaryResponse) Reset() { @@ -11653,16 +11539,15 @@ func (x *GetRechargeBillSummaryResponse) GetCoinSeller() *RechargeBillSummaryBuc // UserRechargeStats 是 wallet-service 已维护的用户累计充值聚合,不允许后台回扫充值流水临时计算。 type UserRechargeStats struct { - 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"` - RechargeCount int64 `protobuf:"varint,2,opt,name=recharge_count,json=rechargeCount,proto3" json:"recharge_count,omitempty"` - TotalCoinAmount int64 `protobuf:"varint,3,opt,name=total_coin_amount,json=totalCoinAmount,proto3" json:"total_coin_amount,omitempty"` - TotalUsdMinorAmount int64 `protobuf:"varint,4,opt,name=total_usd_minor_amount,json=totalUsdMinorAmount,proto3" json:"total_usd_minor_amount,omitempty"` - FirstRechargedAtMs int64 `protobuf:"varint,5,opt,name=first_recharged_at_ms,json=firstRechargedAtMs,proto3" json:"first_recharged_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,6,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + RechargeCount int64 `protobuf:"varint,2,opt,name=recharge_count,json=rechargeCount,proto3" json:"recharge_count,omitempty"` + TotalCoinAmount int64 `protobuf:"varint,3,opt,name=total_coin_amount,json=totalCoinAmount,proto3" json:"total_coin_amount,omitempty"` + TotalUsdMinorAmount int64 `protobuf:"varint,4,opt,name=total_usd_minor_amount,json=totalUsdMinorAmount,proto3" json:"total_usd_minor_amount,omitempty"` + FirstRechargedAtMs int64 `protobuf:"varint,5,opt,name=first_recharged_at_ms,json=firstRechargedAtMs,proto3" json:"first_recharged_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 *UserRechargeStats) Reset() { @@ -11738,13 +11623,12 @@ func (x *UserRechargeStats) GetUpdatedAtMs() int64 { } type BatchGetUserRechargeStatsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` 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"` + sizeCache protoimpl.SizeCache } func (x *BatchGetUserRechargeStatsRequest) Reset() { @@ -11799,11 +11683,10 @@ func (x *BatchGetUserRechargeStatsRequest) GetUserIds() []int64 { } type BatchGetUserRechargeStatsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Items []*UserRechargeStats `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` unknownFields protoimpl.UnknownFields - - Items []*UserRechargeStats `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BatchGetUserRechargeStatsResponse) Reset() { @@ -11844,19 +11727,18 @@ func (x *BatchGetUserRechargeStatsResponse) GetItems() []*UserRechargeStats { } type GetRechargeBillOverviewRequest struct { - 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"` - 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"` - StartAtMs int64 `protobuf:"varint,6,opt,name=start_at_ms,json=startAtMs,proto3" json:"start_at_ms,omitempty"` - EndAtMs int64 `protobuf:"varint,7,opt,name=end_at_ms,json=endAtMs,proto3" json:"end_at_ms,omitempty"` + 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"` + 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"` + StartAtMs int64 `protobuf:"varint,6,opt,name=start_at_ms,json=startAtMs,proto3" json:"start_at_ms,omitempty"` + EndAtMs int64 `protobuf:"varint,7,opt,name=end_at_ms,json=endAtMs,proto3" json:"end_at_ms,omitempty"` // tz_offset_minutes 决定“日”边界(中国时区 480);日趋势与前端展示同一时区口径。 TzOffsetMinutes int32 `protobuf:"varint,8,opt,name=tz_offset_minutes,json=tzOffsetMinutes,proto3" json:"tz_offset_minutes,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GetRechargeBillOverviewRequest) Reset() { @@ -11946,10 +11828,7 @@ func (x *GetRechargeBillOverviewRequest) GetTzOffsetMinutes() int32 { } type RechargeBillDailyBucket struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // date 为 tz_offset_minutes 时区下的 YYYY-MM-DD。 Date string `protobuf:"bytes,1,opt,name=date,proto3" json:"date,omitempty"` GoogleUsdMinor int64 `protobuf:"varint,2,opt,name=google_usd_minor,json=googleUsdMinor,proto3" json:"google_usd_minor,omitempty"` @@ -11958,6 +11837,8 @@ type RechargeBillDailyBucket struct { GoogleCoinAmount int64 `protobuf:"varint,5,opt,name=google_coin_amount,json=googleCoinAmount,proto3" json:"google_coin_amount,omitempty"` ThirdPartyCoinAmount int64 `protobuf:"varint,6,opt,name=third_party_coin_amount,json=thirdPartyCoinAmount,proto3" json:"third_party_coin_amount,omitempty"` CoinSellerCoinAmount int64 `protobuf:"varint,7,opt,name=coin_seller_coin_amount,json=coinSellerCoinAmount,proto3" json:"coin_seller_coin_amount,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RechargeBillDailyBucket) Reset() { @@ -12040,13 +11921,12 @@ func (x *RechargeBillDailyBucket) GetCoinSellerCoinAmount() int64 { } type RechargeBillRegionBucket struct { - 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"` - BillCount int64 `protobuf:"varint,2,opt,name=bill_count,json=billCount,proto3" json:"bill_count,omitempty"` - UsdMinorAmount int64 `protobuf:"varint,3,opt,name=usd_minor_amount,json=usdMinorAmount,proto3" json:"usd_minor_amount,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + RegionId int64 `protobuf:"varint,1,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + BillCount int64 `protobuf:"varint,2,opt,name=bill_count,json=billCount,proto3" json:"bill_count,omitempty"` + UsdMinorAmount int64 `protobuf:"varint,3,opt,name=usd_minor_amount,json=usdMinorAmount,proto3" json:"usd_minor_amount,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RechargeBillRegionBucket) Reset() { @@ -12103,17 +11983,16 @@ func (x *RechargeBillRegionBucket) GetUsdMinorAmount() int64 { // RechargeBillGooglePaidStats 是谷歌实付同步覆盖度与扣费估算: // est_* 只统计已同步且净收入有效的账单,按“美金流水 × 实付占比”折算成 USD 最小单位。 type RechargeBillGooglePaidStats struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - GoogleBillCount int64 `protobuf:"varint,1,opt,name=google_bill_count,json=googleBillCount,proto3" json:"google_bill_count,omitempty"` - SyncedCount int64 `protobuf:"varint,2,opt,name=synced_count,json=syncedCount,proto3" json:"synced_count,omitempty"` - UnsyncedCount int64 `protobuf:"varint,3,opt,name=unsynced_count,json=unsyncedCount,proto3" json:"unsynced_count,omitempty"` - CoveredUsdMinor int64 `protobuf:"varint,4,opt,name=covered_usd_minor,json=coveredUsdMinor,proto3" json:"covered_usd_minor,omitempty"` - EstFeeUsdMinor int64 `protobuf:"varint,5,opt,name=est_fee_usd_minor,json=estFeeUsdMinor,proto3" json:"est_fee_usd_minor,omitempty"` - EstTaxUsdMinor int64 `protobuf:"varint,6,opt,name=est_tax_usd_minor,json=estTaxUsdMinor,proto3" json:"est_tax_usd_minor,omitempty"` - EstNetUsdMinor int64 `protobuf:"varint,7,opt,name=est_net_usd_minor,json=estNetUsdMinor,proto3" json:"est_net_usd_minor,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + GoogleBillCount int64 `protobuf:"varint,1,opt,name=google_bill_count,json=googleBillCount,proto3" json:"google_bill_count,omitempty"` + SyncedCount int64 `protobuf:"varint,2,opt,name=synced_count,json=syncedCount,proto3" json:"synced_count,omitempty"` + UnsyncedCount int64 `protobuf:"varint,3,opt,name=unsynced_count,json=unsyncedCount,proto3" json:"unsynced_count,omitempty"` + CoveredUsdMinor int64 `protobuf:"varint,4,opt,name=covered_usd_minor,json=coveredUsdMinor,proto3" json:"covered_usd_minor,omitempty"` + EstFeeUsdMinor int64 `protobuf:"varint,5,opt,name=est_fee_usd_minor,json=estFeeUsdMinor,proto3" json:"est_fee_usd_minor,omitempty"` + EstTaxUsdMinor int64 `protobuf:"varint,6,opt,name=est_tax_usd_minor,json=estTaxUsdMinor,proto3" json:"est_tax_usd_minor,omitempty"` + EstNetUsdMinor int64 `protobuf:"varint,7,opt,name=est_net_usd_minor,json=estNetUsdMinor,proto3" json:"est_net_usd_minor,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RechargeBillGooglePaidStats) Reset() { @@ -12198,12 +12077,11 @@ func (x *RechargeBillGooglePaidStats) GetEstNetUsdMinor() int64 { // RechargeBillSalaryTransferStats 是“用户提现”口径中来自钱包账本的部分: // 用户把工资 USDT 转给币商(salary_transfer_to_coin_seller)。 type RechargeBillSalaryTransferStats struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TransferCount int64 `protobuf:"varint,1,opt,name=transfer_count,json=transferCount,proto3" json:"transfer_count,omitempty"` - TransferUsdMinor int64 `protobuf:"varint,2,opt,name=transfer_usd_minor,json=transferUsdMinor,proto3" json:"transfer_usd_minor,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + TransferCount int64 `protobuf:"varint,1,opt,name=transfer_count,json=transferCount,proto3" json:"transfer_count,omitempty"` + TransferUsdMinor int64 `protobuf:"varint,2,opt,name=transfer_usd_minor,json=transferUsdMinor,proto3" json:"transfer_usd_minor,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RechargeBillSalaryTransferStats) Reset() { @@ -12251,14 +12129,13 @@ func (x *RechargeBillSalaryTransferStats) GetTransferUsdMinor() int64 { } type GetRechargeBillOverviewResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` Daily []*RechargeBillDailyBucket `protobuf:"bytes,1,rep,name=daily,proto3" json:"daily,omitempty"` Regions []*RechargeBillRegionBucket `protobuf:"bytes,2,rep,name=regions,proto3" json:"regions,omitempty"` GooglePaid *RechargeBillGooglePaidStats `protobuf:"bytes,3,opt,name=google_paid,json=googlePaid,proto3" json:"google_paid,omitempty"` SalaryTransfer *RechargeBillSalaryTransferStats `protobuf:"bytes,4,opt,name=salary_transfer,json=salaryTransfer,proto3" json:"salary_transfer,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GetRechargeBillOverviewResponse) Reset() { @@ -12320,13 +12197,12 @@ func (x *GetRechargeBillOverviewResponse) GetSalaryTransfer() *RechargeBillSalar } type RefreshGooglePaymentPricesRequest struct { - 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"` - TransactionIds []string `protobuf:"bytes,3,rep,name=transaction_ids,json=transactionIds,proto3" json:"transaction_ids,omitempty"` + 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"` + TransactionIds []string `protobuf:"bytes,3,rep,name=transaction_ids,json=transactionIds,proto3" json:"transaction_ids,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RefreshGooglePaymentPricesRequest) Reset() { @@ -12381,17 +12257,16 @@ func (x *RefreshGooglePaymentPricesRequest) GetTransactionIds() []string { } type GooglePaymentPrice struct { - 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"` - CurrencyCode string `protobuf:"bytes,2,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` - PaidAmountMicro int64 `protobuf:"varint,3,opt,name=paid_amount_micro,json=paidAmountMicro,proto3" json:"paid_amount_micro,omitempty"` - TaxMicro int64 `protobuf:"varint,4,opt,name=tax_micro,json=taxMicro,proto3" json:"tax_micro,omitempty"` - NetMicro int64 `protobuf:"varint,5,opt,name=net_micro,json=netMicro,proto3" json:"net_micro,omitempty"` - SyncedAtMs int64 `protobuf:"varint,6,opt,name=synced_at_ms,json=syncedAtMs,proto3" json:"synced_at_ms,omitempty"` - Error string `protobuf:"bytes,7,opt,name=error,proto3" json:"error,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + CurrencyCode string `protobuf:"bytes,2,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` + PaidAmountMicro int64 `protobuf:"varint,3,opt,name=paid_amount_micro,json=paidAmountMicro,proto3" json:"paid_amount_micro,omitempty"` + TaxMicro int64 `protobuf:"varint,4,opt,name=tax_micro,json=taxMicro,proto3" json:"tax_micro,omitempty"` + NetMicro int64 `protobuf:"varint,5,opt,name=net_micro,json=netMicro,proto3" json:"net_micro,omitempty"` + SyncedAtMs int64 `protobuf:"varint,6,opt,name=synced_at_ms,json=syncedAtMs,proto3" json:"synced_at_ms,omitempty"` + Error string `protobuf:"bytes,7,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GooglePaymentPrice) Reset() { @@ -12474,11 +12349,10 @@ func (x *GooglePaymentPrice) GetError() string { } type RefreshGooglePaymentPricesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Prices []*GooglePaymentPrice `protobuf:"bytes,1,rep,name=prices,proto3" json:"prices,omitempty"` unknownFields protoimpl.UnknownFields - - Prices []*GooglePaymentPrice `protobuf:"bytes,1,rep,name=prices,proto3" json:"prices,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RefreshGooglePaymentPricesResponse) Reset() { @@ -12520,12 +12394,11 @@ func (x *RefreshGooglePaymentPricesResponse) GetPrices() []*GooglePaymentPrice { // WalletFeatureFlags 是我的页和钱包首页使用的操作开关,来源属于 wallet-service。 type WalletFeatureFlags struct { - 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"` + 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 } func (x *WalletFeatureFlags) Reset() { @@ -12573,13 +12446,12 @@ func (x *WalletFeatureFlags) GetDiamondExchangeEnabled() bool { } type GetWalletOverviewRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetWalletOverviewRequest) Reset() { @@ -12634,12 +12506,11 @@ func (x *GetWalletOverviewRequest) GetUserId() int64 { } type GetWalletOverviewResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetWalletOverviewResponse) Reset() { @@ -12688,12 +12559,11 @@ func (x *GetWalletOverviewResponse) GetFeatureFlags() *WalletFeatureFlags { // WalletValueSummary 是我的页钱包价值展示的轻量投影,只返回首屏展示需要的金币余额。 type WalletValueSummary struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *WalletValueSummary) Reset() { @@ -12741,13 +12611,12 @@ func (x *WalletValueSummary) GetUpdatedAtMs() int64 { } type GetWalletValueSummaryRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetWalletValueSummaryRequest) Reset() { @@ -12802,11 +12671,10 @@ func (x *GetWalletValueSummaryRequest) GetUserId() int64 { } type GetWalletValueSummaryResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Summary *WalletValueSummary `protobuf:"bytes,1,opt,name=summary,proto3" json:"summary,omitempty"` unknownFields protoimpl.UnknownFields - - Summary *WalletValueSummary `protobuf:"bytes,1,opt,name=summary,proto3" json:"summary,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetWalletValueSummaryResponse) Reset() { @@ -12848,21 +12716,18 @@ func (x *GetWalletValueSummaryResponse) GetSummary() *WalletValueSummary { // GiftWallItem 是用户礼物墙按礼物类型聚合后的当前投影。 type GiftWallItem struct { - 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"` + 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"` // 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"` @@ -12871,6 +12736,8 @@ 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() { @@ -13030,13 +12897,12 @@ func (x *GiftWallItem) GetSortOrder() int32 { } type GetUserGiftWallRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetUserGiftWallRequest) Reset() { @@ -13091,19 +12957,18 @@ func (x *GetUserGiftWallRequest) GetUserId() int64 { } type GetUserGiftWallResponse struct { - 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"` + 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"` // 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() { @@ -13194,35 +13059,34 @@ func (x *GetUserGiftWallResponse) GetTotalHeatValue() int64 { // RechargeProduct 是 App 充值页可展示的区域化充值档位。 type RechargeProduct struct { - 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"` + 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"` // audience_type 区分 H5 普通用户档位和币商档位;旧 App 内购默认 normal。 AudienceType string `protobuf:"bytes,22,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` // app_visible 只控制 App 充值列表展示;active 但不可见的 Google SKU 仍可用于服务端验单和历史订单补偿。 - AppVisible bool `protobuf:"varint,23,opt,name=app_visible,json=appVisible,proto3" json:"app_visible,omitempty"` + AppVisible bool `protobuf:"varint,23,opt,name=app_visible,json=appVisible,proto3" json:"app_visible,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RechargeProduct) Reset() { @@ -13417,18 +13281,17 @@ func (x *RechargeProduct) GetAppVisible() bool { } type ListRechargeProductsRequest struct { - 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"` + 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"` // audience_type 只用于 H5 站外充值;App 旧入口为空时按 normal 兼容。 - AudienceType string `protobuf:"bytes,6,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` + AudienceType string `protobuf:"bytes,6,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListRechargeProductsRequest) Reset() { @@ -13504,12 +13367,11 @@ func (x *ListRechargeProductsRequest) GetAudienceType() string { } type ListRechargeProductsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Products []*RechargeProduct `protobuf:"bytes,1,rep,name=products,proto3" json:"products,omitempty"` - Channels []string `protobuf:"bytes,2,rep,name=channels,proto3" json:"channels,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListRechargeProductsResponse) Reset() { @@ -13557,23 +13419,22 @@ func (x *ListRechargeProductsResponse) GetChannels() []string { } type ConfirmGooglePaymentRequest struct { - 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"` + 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"` // country_id 由 gateway 从 user-service 当前用户资料注入,用于充值事实按真实国家进入 BI。 - CountryId int64 `protobuf:"varint,12,opt,name=country_id,json=countryId,proto3" json:"country_id,omitempty"` + CountryId int64 `protobuf:"varint,12,opt,name=country_id,json=countryId,proto3" json:"country_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ConfirmGooglePaymentRequest) Reset() { @@ -13691,19 +13552,18 @@ func (x *ConfirmGooglePaymentRequest) GetCountryId() int64 { } type ConfirmGooglePaymentResponse struct { - 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"` + 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 } func (x *ConfirmGooglePaymentResponse) Reset() { @@ -13801,19 +13661,18 @@ func (x *ConfirmGooglePaymentResponse) GetConsumeState() string { // ListAdminRechargeProductsRequest 是后台内购配置列表查询,不参与用户充值主链路。 type ListAdminRechargeProductsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + AudienceType string `protobuf:"bytes,9,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` 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"` - AudienceType string `protobuf:"bytes,9,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListAdminRechargeProductsRequest) Reset() { @@ -13910,12 +13769,11 @@ func (x *ListAdminRechargeProductsRequest) GetAudienceType() string { } type ListAdminRechargeProductsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Products []*RechargeProduct `protobuf:"bytes,1,rep,name=products,proto3" json:"products,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListAdminRechargeProductsResponse) Reset() { @@ -13964,23 +13822,22 @@ func (x *ListAdminRechargeProductsResponse) GetTotal() int64 { // CreateRechargeProductRequest 配置一个 App 内购商品;首版资源资产固定为 COIN。 type CreateRechargeProductRequest struct { - 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"` - AudienceType string `protobuf:"bytes,11,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` + 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"` + AudienceType string `protobuf:"bytes,11,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` // 不传时创建为可见,兼容旧后台;传 false 可保留 Google 验单能力但从 App 普通充值列表隐藏。 - AppVisible *bool `protobuf:"varint,12,opt,name=app_visible,json=appVisible,proto3,oneof" json:"app_visible,omitempty"` + AppVisible *bool `protobuf:"varint,12,opt,name=app_visible,json=appVisible,proto3,oneof" json:"app_visible,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CreateRechargeProductRequest) Reset() { @@ -14098,24 +13955,23 @@ func (x *CreateRechargeProductRequest) GetAppVisible() bool { } type UpdateRechargeProductRequest struct { - 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"` - AudienceType string `protobuf:"bytes,12,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` + 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"` + AudienceType string `protobuf:"bytes,12,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` // 不传时保留原可见性,避免旧后台编辑隐藏 SKU 时意外改变展示面。 - AppVisible *bool `protobuf:"varint,13,opt,name=app_visible,json=appVisible,proto3,oneof" json:"app_visible,omitempty"` + AppVisible *bool `protobuf:"varint,13,opt,name=app_visible,json=appVisible,proto3,oneof" json:"app_visible,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *UpdateRechargeProductRequest) Reset() { @@ -14240,14 +14096,13 @@ func (x *UpdateRechargeProductRequest) GetAppVisible() bool { } type DeleteRechargeProductRequest struct { - 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"` + 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 } func (x *DeleteRechargeProductRequest) Reset() { @@ -14309,11 +14164,10 @@ func (x *DeleteRechargeProductRequest) GetOperatorUserId() int64 { } type RechargeProductResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Product *RechargeProduct `protobuf:"bytes,1,opt,name=product,proto3" json:"product,omitempty"` unknownFields protoimpl.UnknownFields - - Product *RechargeProduct `protobuf:"bytes,1,opt,name=product,proto3" json:"product,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RechargeProductResponse) Reset() { @@ -14354,11 +14208,10 @@ func (x *RechargeProductResponse) GetProduct() *RechargeProduct { } type DeleteRechargeProductResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"` unknownFields protoimpl.UnknownFields - - Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"` + sizeCache protoimpl.SizeCache } func (x *DeleteRechargeProductResponse) Reset() { @@ -14400,26 +14253,25 @@ func (x *DeleteRechargeProductResponse) GetDeleted() bool { // ThirdPartyPaymentMethod 是后台和 H5 共用的三方支付方式配置快照。 type ThirdPartyPaymentMethod struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - MethodId int64 `protobuf:"varint,1,opt,name=method_id,json=methodId,proto3" json:"method_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ProviderCode string `protobuf:"bytes,3,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` - ProviderName string `protobuf:"bytes,4,opt,name=provider_name,json=providerName,proto3" json:"provider_name,omitempty"` - CountryCode string `protobuf:"bytes,5,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` - CountryName string `protobuf:"bytes,6,opt,name=country_name,json=countryName,proto3" json:"country_name,omitempty"` - CurrencyCode string `protobuf:"bytes,7,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` - PayWay string `protobuf:"bytes,8,opt,name=pay_way,json=payWay,proto3" json:"pay_way,omitempty"` - PayType string `protobuf:"bytes,9,opt,name=pay_type,json=payType,proto3" json:"pay_type,omitempty"` - MethodName string `protobuf:"bytes,10,opt,name=method_name,json=methodName,proto3" json:"method_name,omitempty"` - LogoUrl string `protobuf:"bytes,11,opt,name=logo_url,json=logoUrl,proto3" json:"logo_url,omitempty"` - Status string `protobuf:"bytes,12,opt,name=status,proto3" json:"status,omitempty"` - UsdToCurrencyRate string `protobuf:"bytes,13,opt,name=usd_to_currency_rate,json=usdToCurrencyRate,proto3" json:"usd_to_currency_rate,omitempty"` - SortOrder int32 `protobuf:"varint,14,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,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"` + state protoimpl.MessageState `protogen:"open.v1"` + MethodId int64 `protobuf:"varint,1,opt,name=method_id,json=methodId,proto3" json:"method_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ProviderCode string `protobuf:"bytes,3,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` + ProviderName string `protobuf:"bytes,4,opt,name=provider_name,json=providerName,proto3" json:"provider_name,omitempty"` + CountryCode string `protobuf:"bytes,5,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` + CountryName string `protobuf:"bytes,6,opt,name=country_name,json=countryName,proto3" json:"country_name,omitempty"` + CurrencyCode string `protobuf:"bytes,7,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` + PayWay string `protobuf:"bytes,8,opt,name=pay_way,json=payWay,proto3" json:"pay_way,omitempty"` + PayType string `protobuf:"bytes,9,opt,name=pay_type,json=payType,proto3" json:"pay_type,omitempty"` + MethodName string `protobuf:"bytes,10,opt,name=method_name,json=methodName,proto3" json:"method_name,omitempty"` + LogoUrl string `protobuf:"bytes,11,opt,name=logo_url,json=logoUrl,proto3" json:"logo_url,omitempty"` + Status string `protobuf:"bytes,12,opt,name=status,proto3" json:"status,omitempty"` + UsdToCurrencyRate string `protobuf:"bytes,13,opt,name=usd_to_currency_rate,json=usdToCurrencyRate,proto3" json:"usd_to_currency_rate,omitempty"` + SortOrder int32 `protobuf:"varint,14,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,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"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ThirdPartyPaymentMethod) Reset() { @@ -14565,16 +14417,15 @@ func (x *ThirdPartyPaymentMethod) GetUpdatedAtMs() int64 { } type ThirdPartyPaymentChannel struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ProviderCode string `protobuf:"bytes,2,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` + ProviderName string `protobuf:"bytes,3,opt,name=provider_name,json=providerName,proto3" json:"provider_name,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + SortOrder int32 `protobuf:"varint,5,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + Methods []*ThirdPartyPaymentMethod `protobuf:"bytes,6,rep,name=methods,proto3" json:"methods,omitempty"` unknownFields protoimpl.UnknownFields - - AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ProviderCode string `protobuf:"bytes,2,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` - ProviderName string `protobuf:"bytes,3,opt,name=provider_name,json=providerName,proto3" json:"provider_name,omitempty"` - Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` - SortOrder int32 `protobuf:"varint,5,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - Methods []*ThirdPartyPaymentMethod `protobuf:"bytes,6,rep,name=methods,proto3" json:"methods,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ThirdPartyPaymentChannel) Reset() { @@ -14650,15 +14501,14 @@ func (x *ThirdPartyPaymentChannel) GetMethods() []*ThirdPartyPaymentMethod { } type ListThirdPartyPaymentChannelsRequest struct { - 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"` - ProviderCode string `protobuf:"bytes,3,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` - Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` - IncludeDisabledMethods bool `protobuf:"varint,5,opt,name=include_disabled_methods,json=includeDisabledMethods,proto3" json:"include_disabled_methods,omitempty"` + 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"` + ProviderCode string `protobuf:"bytes,3,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + IncludeDisabledMethods bool `protobuf:"varint,5,opt,name=include_disabled_methods,json=includeDisabledMethods,proto3" json:"include_disabled_methods,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListThirdPartyPaymentChannelsRequest) Reset() { @@ -14727,11 +14577,10 @@ func (x *ListThirdPartyPaymentChannelsRequest) GetIncludeDisabledMethods() bool } type ListThirdPartyPaymentChannelsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Channels []*ThirdPartyPaymentChannel `protobuf:"bytes,1,rep,name=channels,proto3" json:"channels,omitempty"` unknownFields protoimpl.UnknownFields - - Channels []*ThirdPartyPaymentChannel `protobuf:"bytes,1,rep,name=channels,proto3" json:"channels,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListThirdPartyPaymentChannelsResponse) Reset() { @@ -14772,15 +14621,14 @@ func (x *ListThirdPartyPaymentChannelsResponse) GetChannels() []*ThirdPartyPayme } type SetThirdPartyPaymentMethodStatusRequest struct { - 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"` - MethodId int64 `protobuf:"varint,3,opt,name=method_id,json=methodId,proto3" json:"method_id,omitempty"` - Enabled bool `protobuf:"varint,4,opt,name=enabled,proto3" json:"enabled,omitempty"` - OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + 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"` + MethodId int64 `protobuf:"varint,3,opt,name=method_id,json=methodId,proto3" json:"method_id,omitempty"` + Enabled bool `protobuf:"varint,4,opt,name=enabled,proto3" json:"enabled,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 } func (x *SetThirdPartyPaymentMethodStatusRequest) Reset() { @@ -14849,11 +14697,10 @@ func (x *SetThirdPartyPaymentMethodStatusRequest) GetOperatorUserId() int64 { } type ThirdPartyPaymentMethodResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Method *ThirdPartyPaymentMethod `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"` unknownFields protoimpl.UnknownFields - - Method *ThirdPartyPaymentMethod `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ThirdPartyPaymentMethodResponse) Reset() { @@ -14894,15 +14741,14 @@ func (x *ThirdPartyPaymentMethodResponse) GetMethod() *ThirdPartyPaymentMethod { } type UpdateThirdPartyPaymentRateRequest struct { - 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"` - MethodId int64 `protobuf:"varint,3,opt,name=method_id,json=methodId,proto3" json:"method_id,omitempty"` - UsdToCurrencyRate string `protobuf:"bytes,4,opt,name=usd_to_currency_rate,json=usdToCurrencyRate,proto3" json:"usd_to_currency_rate,omitempty"` - OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + 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"` + MethodId int64 `protobuf:"varint,3,opt,name=method_id,json=methodId,proto3" json:"method_id,omitempty"` + UsdToCurrencyRate string `protobuf:"bytes,4,opt,name=usd_to_currency_rate,json=usdToCurrencyRate,proto3" json:"usd_to_currency_rate,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 } func (x *UpdateThirdPartyPaymentRateRequest) Reset() { @@ -14971,14 +14817,13 @@ func (x *UpdateThirdPartyPaymentRateRequest) GetOperatorUserId() int64 { } type ThirdPartyPaymentMethodSyncIssue struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` + CurrencyCode string `protobuf:"bytes,2,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` + Code string `protobuf:"bytes,3,opt,name=code,proto3" json:"code,omitempty"` + Message string `protobuf:"bytes,4,opt,name=message,proto3" json:"message,omitempty"` unknownFields protoimpl.UnknownFields - - CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` - CurrencyCode string `protobuf:"bytes,2,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` - Code string `protobuf:"bytes,3,opt,name=code,proto3" json:"code,omitempty"` - Message string `protobuf:"bytes,4,opt,name=message,proto3" json:"message,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ThirdPartyPaymentMethodSyncIssue) Reset() { @@ -15040,14 +14885,13 @@ func (x *ThirdPartyPaymentMethodSyncIssue) GetMessage() string { } type SyncThirdPartyPaymentMethodsRequest struct { - 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"` - ProviderCode string `protobuf:"bytes,3,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` - OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + 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"` + ProviderCode string `protobuf:"bytes,3,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,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 *SyncThirdPartyPaymentMethodsRequest) Reset() { @@ -15109,10 +14953,7 @@ func (x *SyncThirdPartyPaymentMethodsRequest) GetOperatorUserId() int64 { } type SyncThirdPartyPaymentMethodsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` ProviderCode string `protobuf:"bytes,1,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` ScannedCountryCount int32 `protobuf:"varint,2,opt,name=scanned_country_count,json=scannedCountryCount,proto3" json:"scanned_country_count,omitempty"` FetchedCountryCount int32 `protobuf:"varint,3,opt,name=fetched_country_count,json=fetchedCountryCount,proto3" json:"fetched_country_count,omitempty"` @@ -15120,6 +14961,8 @@ type SyncThirdPartyPaymentMethodsResponse struct { UpdatedCount int32 `protobuf:"varint,5,opt,name=updated_count,json=updatedCount,proto3" json:"updated_count,omitempty"` SkippedCount int32 `protobuf:"varint,6,opt,name=skipped_count,json=skippedCount,proto3" json:"skipped_count,omitempty"` Issues []*ThirdPartyPaymentMethodSyncIssue `protobuf:"bytes,7,rep,name=issues,proto3" json:"issues,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SyncThirdPartyPaymentMethodsResponse) Reset() { @@ -15202,16 +15045,15 @@ func (x *SyncThirdPartyPaymentMethodsResponse) GetIssues() []*ThirdPartyPaymentM } type H5RechargeOptionsRequest struct { - 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"` - TargetRegionId int64 `protobuf:"varint,4,opt,name=target_region_id,json=targetRegionId,proto3" json:"target_region_id,omitempty"` - TargetCountryCode string `protobuf:"bytes,5,opt,name=target_country_code,json=targetCountryCode,proto3" json:"target_country_code,omitempty"` - AudienceType string `protobuf:"bytes,6,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` + 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"` + TargetRegionId int64 `protobuf:"varint,4,opt,name=target_region_id,json=targetRegionId,proto3" json:"target_region_id,omitempty"` + TargetCountryCode string `protobuf:"bytes,5,opt,name=target_country_code,json=targetCountryCode,proto3" json:"target_country_code,omitempty"` + AudienceType string `protobuf:"bytes,6,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *H5RechargeOptionsRequest) Reset() { @@ -15287,14 +15129,13 @@ func (x *H5RechargeOptionsRequest) GetAudienceType() string { } type H5RechargeOptionsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` Products []*RechargeProduct `protobuf:"bytes,1,rep,name=products,proto3" json:"products,omitempty"` PaymentMethods []*ThirdPartyPaymentMethod `protobuf:"bytes,2,rep,name=payment_methods,json=paymentMethods,proto3" json:"payment_methods,omitempty"` UsdtTrc20Enabled bool `protobuf:"varint,3,opt,name=usdt_trc20_enabled,json=usdtTrc20Enabled,proto3" json:"usdt_trc20_enabled,omitempty"` UsdtTrc20Address string `protobuf:"bytes,4,opt,name=usdt_trc20_address,json=usdtTrc20Address,proto3" json:"usdt_trc20_address,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *H5RechargeOptionsResponse) Reset() { @@ -15356,39 +15197,38 @@ func (x *H5RechargeOptionsResponse) GetUsdtTrc20Address() string { } type ExternalRechargeOrder struct { - 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"` - 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"` - TargetRegionId int64 `protobuf:"varint,4,opt,name=target_region_id,json=targetRegionId,proto3" json:"target_region_id,omitempty"` - TargetCountryCode string `protobuf:"bytes,5,opt,name=target_country_code,json=targetCountryCode,proto3" json:"target_country_code,omitempty"` - AudienceType string `protobuf:"bytes,6,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` - ProductId int64 `protobuf:"varint,7,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` - ProductName string `protobuf:"bytes,8,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` - CoinAmount int64 `protobuf:"varint,9,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - UsdMinorAmount int64 `protobuf:"varint,10,opt,name=usd_minor_amount,json=usdMinorAmount,proto3" json:"usd_minor_amount,omitempty"` - ProviderCode string `protobuf:"bytes,11,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` - PaymentMethodId int64 `protobuf:"varint,12,opt,name=payment_method_id,json=paymentMethodId,proto3" json:"payment_method_id,omitempty"` - CountryCode string `protobuf:"bytes,13,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` - CurrencyCode string `protobuf:"bytes,14,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` - ProviderAmountMinor int64 `protobuf:"varint,15,opt,name=provider_amount_minor,json=providerAmountMinor,proto3" json:"provider_amount_minor,omitempty"` - PayWay string `protobuf:"bytes,16,opt,name=pay_way,json=payWay,proto3" json:"pay_way,omitempty"` - PayType string `protobuf:"bytes,17,opt,name=pay_type,json=payType,proto3" json:"pay_type,omitempty"` - PayUrl string `protobuf:"bytes,18,opt,name=pay_url,json=payUrl,proto3" json:"pay_url,omitempty"` - ProviderOrderId string `protobuf:"bytes,19,opt,name=provider_order_id,json=providerOrderId,proto3" json:"provider_order_id,omitempty"` - TxHash string `protobuf:"bytes,20,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` - ReceiveAddress string `protobuf:"bytes,21,opt,name=receive_address,json=receiveAddress,proto3" json:"receive_address,omitempty"` - Status string `protobuf:"bytes,22,opt,name=status,proto3" json:"status,omitempty"` - FailureReason string `protobuf:"bytes,23,opt,name=failure_reason,json=failureReason,proto3" json:"failure_reason,omitempty"` - TransactionId string `protobuf:"bytes,24,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,25,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,26,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - IdempotentReplay bool `protobuf:"varint,27,opt,name=idempotent_replay,json=idempotentReplay,proto3" json:"idempotent_replay,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + OrderId string `protobuf:"bytes,1,opt,name=order_id,json=orderId,proto3" json:"order_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"` + TargetRegionId int64 `protobuf:"varint,4,opt,name=target_region_id,json=targetRegionId,proto3" json:"target_region_id,omitempty"` + TargetCountryCode string `protobuf:"bytes,5,opt,name=target_country_code,json=targetCountryCode,proto3" json:"target_country_code,omitempty"` + AudienceType string `protobuf:"bytes,6,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` + ProductId int64 `protobuf:"varint,7,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` + ProductName string `protobuf:"bytes,8,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` + CoinAmount int64 `protobuf:"varint,9,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + UsdMinorAmount int64 `protobuf:"varint,10,opt,name=usd_minor_amount,json=usdMinorAmount,proto3" json:"usd_minor_amount,omitempty"` + ProviderCode string `protobuf:"bytes,11,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` + PaymentMethodId int64 `protobuf:"varint,12,opt,name=payment_method_id,json=paymentMethodId,proto3" json:"payment_method_id,omitempty"` + CountryCode string `protobuf:"bytes,13,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` + CurrencyCode string `protobuf:"bytes,14,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` + ProviderAmountMinor int64 `protobuf:"varint,15,opt,name=provider_amount_minor,json=providerAmountMinor,proto3" json:"provider_amount_minor,omitempty"` + PayWay string `protobuf:"bytes,16,opt,name=pay_way,json=payWay,proto3" json:"pay_way,omitempty"` + PayType string `protobuf:"bytes,17,opt,name=pay_type,json=payType,proto3" json:"pay_type,omitempty"` + PayUrl string `protobuf:"bytes,18,opt,name=pay_url,json=payUrl,proto3" json:"pay_url,omitempty"` + ProviderOrderId string `protobuf:"bytes,19,opt,name=provider_order_id,json=providerOrderId,proto3" json:"provider_order_id,omitempty"` + TxHash string `protobuf:"bytes,20,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` + ReceiveAddress string `protobuf:"bytes,21,opt,name=receive_address,json=receiveAddress,proto3" json:"receive_address,omitempty"` + Status string `protobuf:"bytes,22,opt,name=status,proto3" json:"status,omitempty"` + FailureReason string `protobuf:"bytes,23,opt,name=failure_reason,json=failureReason,proto3" json:"failure_reason,omitempty"` + TransactionId string `protobuf:"bytes,24,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,25,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,26,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + IdempotentReplay bool `protobuf:"varint,27,opt,name=idempotent_replay,json=idempotentReplay,proto3" json:"idempotent_replay,omitempty"` // target_country_id 是下单时目标用户国家快照,支付回调入账直接复用,避免异步回调再查用户主数据。 TargetCountryId int64 `protobuf:"varint,28,opt,name=target_country_id,json=targetCountryId,proto3" json:"target_country_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ExternalRechargeOrder) Reset() { @@ -15618,30 +15458,29 @@ func (x *ExternalRechargeOrder) GetTargetCountryId() int64 { } type CreateH5RechargeOrderRequest struct { - 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"` - TargetUserId int64 `protobuf:"varint,4,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - TargetRegionId int64 `protobuf:"varint,5,opt,name=target_region_id,json=targetRegionId,proto3" json:"target_region_id,omitempty"` - TargetCountryCode string `protobuf:"bytes,6,opt,name=target_country_code,json=targetCountryCode,proto3" json:"target_country_code,omitempty"` - AudienceType string `protobuf:"bytes,7,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` - ProductId int64 `protobuf:"varint,8,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` - ProviderCode string `protobuf:"bytes,9,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` - PaymentMethodId int64 `protobuf:"varint,10,opt,name=payment_method_id,json=paymentMethodId,proto3" json:"payment_method_id,omitempty"` - ReturnUrl string `protobuf:"bytes,11,opt,name=return_url,json=returnUrl,proto3" json:"return_url,omitempty"` - NotifyUrl string `protobuf:"bytes,12,opt,name=notify_url,json=notifyUrl,proto3" json:"notify_url,omitempty"` - ClientIp string `protobuf:"bytes,13,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` - Language string `protobuf:"bytes,14,opt,name=language,proto3" json:"language,omitempty"` + 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"` + TargetUserId int64 `protobuf:"varint,4,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + TargetRegionId int64 `protobuf:"varint,5,opt,name=target_region_id,json=targetRegionId,proto3" json:"target_region_id,omitempty"` + TargetCountryCode string `protobuf:"bytes,6,opt,name=target_country_code,json=targetCountryCode,proto3" json:"target_country_code,omitempty"` + AudienceType string `protobuf:"bytes,7,opt,name=audience_type,json=audienceType,proto3" json:"audience_type,omitempty"` + ProductId int64 `protobuf:"varint,8,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` + ProviderCode string `protobuf:"bytes,9,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` + PaymentMethodId int64 `protobuf:"varint,10,opt,name=payment_method_id,json=paymentMethodId,proto3" json:"payment_method_id,omitempty"` + ReturnUrl string `protobuf:"bytes,11,opt,name=return_url,json=returnUrl,proto3" json:"return_url,omitempty"` + NotifyUrl string `protobuf:"bytes,12,opt,name=notify_url,json=notifyUrl,proto3" json:"notify_url,omitempty"` + ClientIp string `protobuf:"bytes,13,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` + Language string `protobuf:"bytes,14,opt,name=language,proto3" json:"language,omitempty"` // payer_name / payer_account 来自 gateway 重新解析的目标用户资料,不接受 H5 前端自报。 PayerName string `protobuf:"bytes,15,opt,name=payer_name,json=payerName,proto3" json:"payer_name,omitempty"` PayerAccount string `protobuf:"bytes,16,opt,name=payer_account,json=payerAccount,proto3" json:"payer_account,omitempty"` PayerEmail string `protobuf:"bytes,17,opt,name=payer_email,json=payerEmail,proto3" json:"payer_email,omitempty"` // target_country_id 由 gateway 从 user-service 解析目标用户,不接受 H5 前端自报。 TargetCountryId int64 `protobuf:"varint,18,opt,name=target_country_id,json=targetCountryId,proto3" json:"target_country_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CreateH5RechargeOrderRequest) Reset() { @@ -15801,24 +15640,23 @@ func (x *CreateH5RechargeOrderRequest) GetTargetCountryId() int64 { } type CreateTemporaryRechargeOrderRequest struct { - 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"` - CoinAmount int64 `protobuf:"varint,4,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - UsdMinorAmount int64 `protobuf:"varint,5,opt,name=usd_minor_amount,json=usdMinorAmount,proto3" json:"usd_minor_amount,omitempty"` - ProviderCode string `protobuf:"bytes,6,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` - PaymentMethodId int64 `protobuf:"varint,7,opt,name=payment_method_id,json=paymentMethodId,proto3" json:"payment_method_id,omitempty"` - ReturnUrl string `protobuf:"bytes,8,opt,name=return_url,json=returnUrl,proto3" json:"return_url,omitempty"` - NotifyUrl string `protobuf:"bytes,9,opt,name=notify_url,json=notifyUrl,proto3" json:"notify_url,omitempty"` - ClientIp string `protobuf:"bytes,10,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` - Language string `protobuf:"bytes,11,opt,name=language,proto3" json:"language,omitempty"` - PayerName string `protobuf:"bytes,12,opt,name=payer_name,json=payerName,proto3" json:"payer_name,omitempty"` - PayerAccount string `protobuf:"bytes,13,opt,name=payer_account,json=payerAccount,proto3" json:"payer_account,omitempty"` - PayerEmail string `protobuf:"bytes,14,opt,name=payer_email,json=payerEmail,proto3" json:"payer_email,omitempty"` + 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"` + CoinAmount int64 `protobuf:"varint,4,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + UsdMinorAmount int64 `protobuf:"varint,5,opt,name=usd_minor_amount,json=usdMinorAmount,proto3" json:"usd_minor_amount,omitempty"` + ProviderCode string `protobuf:"bytes,6,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` + PaymentMethodId int64 `protobuf:"varint,7,opt,name=payment_method_id,json=paymentMethodId,proto3" json:"payment_method_id,omitempty"` + ReturnUrl string `protobuf:"bytes,8,opt,name=return_url,json=returnUrl,proto3" json:"return_url,omitempty"` + NotifyUrl string `protobuf:"bytes,9,opt,name=notify_url,json=notifyUrl,proto3" json:"notify_url,omitempty"` + ClientIp string `protobuf:"bytes,10,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` + Language string `protobuf:"bytes,11,opt,name=language,proto3" json:"language,omitempty"` + PayerName string `protobuf:"bytes,12,opt,name=payer_name,json=payerName,proto3" json:"payer_name,omitempty"` + PayerAccount string `protobuf:"bytes,13,opt,name=payer_account,json=payerAccount,proto3" json:"payer_account,omitempty"` + PayerEmail string `protobuf:"bytes,14,opt,name=payer_email,json=payerEmail,proto3" json:"payer_email,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CreateTemporaryRechargeOrderRequest) Reset() { @@ -15950,13 +15788,12 @@ func (x *CreateTemporaryRechargeOrderRequest) GetPayerEmail() string { } type GetTemporaryRechargeOrderRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + OrderId string `protobuf:"bytes,3,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` 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"` - OrderId string `protobuf:"bytes,3,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetTemporaryRechargeOrderRequest) Reset() { @@ -16011,17 +15848,16 @@ func (x *GetTemporaryRechargeOrderRequest) GetOrderId() string { } type ListTemporaryRechargeOrdersRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + ProviderCode string `protobuf:"bytes,4,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,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"` 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"` - ProviderCode string `protobuf:"bytes,4,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,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"` + sizeCache protoimpl.SizeCache } func (x *ListTemporaryRechargeOrdersRequest) Reset() { @@ -16104,12 +15940,11 @@ func (x *ListTemporaryRechargeOrdersRequest) GetPageSize() int32 { } type ListTemporaryRechargeOrdersResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Orders []*ExternalRechargeOrder `protobuf:"bytes,1,rep,name=orders,proto3" json:"orders,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` unknownFields protoimpl.UnknownFields - - Orders []*ExternalRechargeOrder `protobuf:"bytes,1,rep,name=orders,proto3" json:"orders,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListTemporaryRechargeOrdersResponse) Reset() { @@ -16157,15 +15992,14 @@ func (x *ListTemporaryRechargeOrdersResponse) GetTotal() int64 { } type SubmitH5RechargeTxRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + OrderId string `protobuf:"bytes,3,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` + TargetUserId int64 `protobuf:"varint,4,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + TxHash string `protobuf:"bytes,5,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` 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"` - OrderId string `protobuf:"bytes,3,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` - TargetUserId int64 `protobuf:"varint,4,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - TxHash string `protobuf:"bytes,5,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` + sizeCache protoimpl.SizeCache } func (x *SubmitH5RechargeTxRequest) Reset() { @@ -16234,14 +16068,13 @@ func (x *SubmitH5RechargeTxRequest) GetTxHash() string { } type GetH5RechargeOrderRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + OrderId string `protobuf:"bytes,3,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` + TargetUserId int64 `protobuf:"varint,4,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` 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"` - OrderId string `protobuf:"bytes,3,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` - TargetUserId int64 `protobuf:"varint,4,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetH5RechargeOrderRequest) Reset() { @@ -16303,11 +16136,10 @@ func (x *GetH5RechargeOrderRequest) GetTargetUserId() int64 { } type H5RechargeOrderResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Order *ExternalRechargeOrder `protobuf:"bytes,1,opt,name=order,proto3" json:"order,omitempty"` unknownFields protoimpl.UnknownFields - - Order *ExternalRechargeOrder `protobuf:"bytes,1,opt,name=order,proto3" json:"order,omitempty"` + sizeCache protoimpl.SizeCache } func (x *H5RechargeOrderResponse) Reset() { @@ -16348,24 +16180,23 @@ func (x *H5RechargeOrderResponse) GetOrder() *ExternalRechargeOrder { } type VerifyCoinSellerRechargeReceiptRequest struct { - 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"` - ProviderCode string `protobuf:"bytes,3,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` - ExternalOrderNo string `protobuf:"bytes,4,opt,name=external_order_no,json=externalOrderNo,proto3" json:"external_order_no,omitempty"` - Chain string `protobuf:"bytes,5,opt,name=chain,proto3" json:"chain,omitempty"` - UsdMinorAmount int64 `protobuf:"varint,6,opt,name=usd_minor_amount,json=usdMinorAmount,proto3" json:"usd_minor_amount,omitempty"` - OrderDateMs int64 `protobuf:"varint,7,opt,name=order_date_ms,json=orderDateMs,proto3" json:"order_date_ms,omitempty"` - ProviderCountryCode string `protobuf:"bytes,8,opt,name=provider_country_code,json=providerCountryCode,proto3" json:"provider_country_code,omitempty"` - ProviderCurrencyCode string `protobuf:"bytes,9,opt,name=provider_currency_code,json=providerCurrencyCode,proto3" json:"provider_currency_code,omitempty"` - ProviderPayType string `protobuf:"bytes,10,opt,name=provider_pay_type,json=providerPayType,proto3" json:"provider_pay_type,omitempty"` - ProviderAmountMinor int64 `protobuf:"varint,11,opt,name=provider_amount_minor,json=providerAmountMinor,proto3" json:"provider_amount_minor,omitempty"` + 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"` + ProviderCode string `protobuf:"bytes,3,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` + ExternalOrderNo string `protobuf:"bytes,4,opt,name=external_order_no,json=externalOrderNo,proto3" json:"external_order_no,omitempty"` + Chain string `protobuf:"bytes,5,opt,name=chain,proto3" json:"chain,omitempty"` + UsdMinorAmount int64 `protobuf:"varint,6,opt,name=usd_minor_amount,json=usdMinorAmount,proto3" json:"usd_minor_amount,omitempty"` + OrderDateMs int64 `protobuf:"varint,7,opt,name=order_date_ms,json=orderDateMs,proto3" json:"order_date_ms,omitempty"` + ProviderCountryCode string `protobuf:"bytes,8,opt,name=provider_country_code,json=providerCountryCode,proto3" json:"provider_country_code,omitempty"` + ProviderCurrencyCode string `protobuf:"bytes,9,opt,name=provider_currency_code,json=providerCurrencyCode,proto3" json:"provider_currency_code,omitempty"` + ProviderPayType string `protobuf:"bytes,10,opt,name=provider_pay_type,json=providerPayType,proto3" json:"provider_pay_type,omitempty"` + ProviderAmountMinor int64 `protobuf:"varint,11,opt,name=provider_amount_minor,json=providerAmountMinor,proto3" json:"provider_amount_minor,omitempty"` // receive_address 由可信后台从 app-scoped SQL 配置读取;非空时覆盖 wallet YAML, // 让运营修改收款地址后立即按新地址校验,同时避免 wallet-service 反向直连 admin 数据库。 ReceiveAddress string `protobuf:"bytes,12,opt,name=receive_address,json=receiveAddress,proto3" json:"receive_address,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *VerifyCoinSellerRechargeReceiptRequest) Reset() { @@ -16483,22 +16314,21 @@ func (x *VerifyCoinSellerRechargeReceiptRequest) GetReceiveAddress() string { } type VerifyCoinSellerRechargeReceiptResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Verified bool `protobuf:"varint,1,opt,name=verified,proto3" json:"verified,omitempty"` - ProviderCode string `protobuf:"bytes,2,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` - ExternalOrderNo string `protobuf:"bytes,3,opt,name=external_order_no,json=externalOrderNo,proto3" json:"external_order_no,omitempty"` - ProviderOrderId string `protobuf:"bytes,4,opt,name=provider_order_id,json=providerOrderId,proto3" json:"provider_order_id,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - CurrencyCode string `protobuf:"bytes,6,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` - ProviderAmountMinor int64 `protobuf:"varint,7,opt,name=provider_amount_minor,json=providerAmountMinor,proto3" json:"provider_amount_minor,omitempty"` - RawJson string `protobuf:"bytes,8,opt,name=raw_json,json=rawJson,proto3" json:"raw_json,omitempty"` - Chain string `protobuf:"bytes,9,opt,name=chain,proto3" json:"chain,omitempty"` - ReceiveAddress string `protobuf:"bytes,10,opt,name=receive_address,json=receiveAddress,proto3" json:"receive_address,omitempty"` - VerifiedAtMs int64 `protobuf:"varint,11,opt,name=verified_at_ms,json=verifiedAtMs,proto3" json:"verified_at_ms,omitempty"` - FailureReason string `protobuf:"bytes,12,opt,name=failure_reason,json=failureReason,proto3" json:"failure_reason,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Verified bool `protobuf:"varint,1,opt,name=verified,proto3" json:"verified,omitempty"` + ProviderCode string `protobuf:"bytes,2,opt,name=provider_code,json=providerCode,proto3" json:"provider_code,omitempty"` + ExternalOrderNo string `protobuf:"bytes,3,opt,name=external_order_no,json=externalOrderNo,proto3" json:"external_order_no,omitempty"` + ProviderOrderId string `protobuf:"bytes,4,opt,name=provider_order_id,json=providerOrderId,proto3" json:"provider_order_id,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + CurrencyCode string `protobuf:"bytes,6,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` + ProviderAmountMinor int64 `protobuf:"varint,7,opt,name=provider_amount_minor,json=providerAmountMinor,proto3" json:"provider_amount_minor,omitempty"` + RawJson string `protobuf:"bytes,8,opt,name=raw_json,json=rawJson,proto3" json:"raw_json,omitempty"` + Chain string `protobuf:"bytes,9,opt,name=chain,proto3" json:"chain,omitempty"` + ReceiveAddress string `protobuf:"bytes,10,opt,name=receive_address,json=receiveAddress,proto3" json:"receive_address,omitempty"` + VerifiedAtMs int64 `protobuf:"varint,11,opt,name=verified_at_ms,json=verifiedAtMs,proto3" json:"verified_at_ms,omitempty"` + FailureReason string `protobuf:"bytes,12,opt,name=failure_reason,json=failureReason,proto3" json:"failure_reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *VerifyCoinSellerRechargeReceiptResponse) Reset() { @@ -16616,15 +16446,14 @@ func (x *VerifyCoinSellerRechargeReceiptResponse) GetFailureReason() string { } type HandleMifapayNotifyRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + MerAccount string `protobuf:"bytes,3,opt,name=mer_account,json=merAccount,proto3" json:"mer_account,omitempty"` + Data string `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` + Sign string `protobuf:"bytes,5,opt,name=sign,proto3" json:"sign,omitempty"` 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"` - MerAccount string `protobuf:"bytes,3,opt,name=mer_account,json=merAccount,proto3" json:"mer_account,omitempty"` - Data string `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` - Sign string `protobuf:"bytes,5,opt,name=sign,proto3" json:"sign,omitempty"` + sizeCache protoimpl.SizeCache } func (x *HandleMifapayNotifyRequest) Reset() { @@ -16693,13 +16522,12 @@ func (x *HandleMifapayNotifyRequest) GetSign() string { } type HandleMifapayNotifyResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Accepted bool `protobuf:"varint,1,opt,name=accepted,proto3" json:"accepted,omitempty"` + ResponseText string `protobuf:"bytes,2,opt,name=response_text,json=responseText,proto3" json:"response_text,omitempty"` + OrderId string `protobuf:"bytes,3,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` unknownFields protoimpl.UnknownFields - - Accepted bool `protobuf:"varint,1,opt,name=accepted,proto3" json:"accepted,omitempty"` - ResponseText string `protobuf:"bytes,2,opt,name=response_text,json=responseText,proto3" json:"response_text,omitempty"` - OrderId string `protobuf:"bytes,3,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *HandleMifapayNotifyResponse) Reset() { @@ -16754,14 +16582,13 @@ func (x *HandleMifapayNotifyResponse) GetOrderId() string { } type HandleV5PayNotifyRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + RawJson string `protobuf:"bytes,3,opt,name=raw_json,json=rawJson,proto3" json:"raw_json,omitempty"` + Fields map[string]string `protobuf:"bytes,4,rep,name=fields,proto3" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` 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"` - RawJson string `protobuf:"bytes,3,opt,name=raw_json,json=rawJson,proto3" json:"raw_json,omitempty"` - Fields map[string]string `protobuf:"bytes,4,rep,name=fields,proto3" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + sizeCache protoimpl.SizeCache } func (x *HandleV5PayNotifyRequest) Reset() { @@ -16823,13 +16650,12 @@ func (x *HandleV5PayNotifyRequest) GetFields() map[string]string { } type HandleV5PayNotifyResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Accepted bool `protobuf:"varint,1,opt,name=accepted,proto3" json:"accepted,omitempty"` + ResponseText string `protobuf:"bytes,2,opt,name=response_text,json=responseText,proto3" json:"response_text,omitempty"` + OrderId string `protobuf:"bytes,3,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` unknownFields protoimpl.UnknownFields - - Accepted bool `protobuf:"varint,1,opt,name=accepted,proto3" json:"accepted,omitempty"` - ResponseText string `protobuf:"bytes,2,opt,name=response_text,json=responseText,proto3" json:"response_text,omitempty"` - OrderId string `protobuf:"bytes,3,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *HandleV5PayNotifyResponse) Reset() { @@ -16884,16 +16710,15 @@ func (x *HandleV5PayNotifyResponse) GetOrderId() string { } type DiamondExchangeRule struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *DiamondExchangeRule) Reset() { @@ -16969,13 +16794,12 @@ func (x *DiamondExchangeRule) GetEnabled() bool { } type GetDiamondExchangeConfigRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetDiamondExchangeConfigRequest) Reset() { @@ -17030,11 +16854,10 @@ func (x *GetDiamondExchangeConfigRequest) GetUserId() int64 { } type GetDiamondExchangeConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Rules []*DiamondExchangeRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"` unknownFields protoimpl.UnknownFields - - Rules []*DiamondExchangeRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetDiamondExchangeConfigResponse) Reset() { @@ -17076,23 +16899,22 @@ func (x *GetDiamondExchangeConfigResponse) GetRules() []*DiamondExchangeRule { // WalletTransaction 是用户钱包流水页使用的分录级投影。 type WalletTransaction struct { - 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"` - TransferUsdMinor int64 `protobuf:"varint,12,opt,name=transfer_usd_minor,json=transferUsdMinor,proto3" json:"transfer_usd_minor,omitempty"` - TransferCurrencyCode string `protobuf:"bytes,13,opt,name=transfer_currency_code,json=transferCurrencyCode,proto3" json:"transfer_currency_code,omitempty"` + 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"` + TransferUsdMinor int64 `protobuf:"varint,12,opt,name=transfer_usd_minor,json=transferUsdMinor,proto3" json:"transfer_usd_minor,omitempty"` + TransferCurrencyCode string `protobuf:"bytes,13,opt,name=transfer_currency_code,json=transferCurrencyCode,proto3" json:"transfer_currency_code,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *WalletTransaction) Reset() { @@ -17217,16 +17039,15 @@ func (x *WalletTransaction) GetTransferCurrencyCode() string { } type ListWalletTransactionsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListWalletTransactionsRequest) Reset() { @@ -17302,12 +17123,11 @@ func (x *ListWalletTransactionsRequest) GetPageSize() int32 { } type ListWalletTransactionsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - Transactions []*WalletTransaction `protobuf:"bytes,1,rep,name=transactions,proto3" json:"transactions,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListWalletTransactionsResponse) Reset() { @@ -17355,19 +17175,18 @@ func (x *ListWalletTransactionsResponse) GetTotal() int64 { } type VipRewardItem struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *VipRewardItem) Reset() { @@ -17466,11 +17285,8 @@ func (x *VipRewardItem) GetAnimationUrl() string { // VipProgramConfig 是按 App 隔离的 VIP 规则开关。业务服务只能依据这些显式策略执行, // 禁止通过 app_code 分支推断升级有效期、权益继承或后台发放语义。 type VipProgramConfig struct { - 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"` + state protoimpl.MessageState `protogen:"open.v1"` + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` // program_type: legacy_timed/tiered_privilege_v1。 ProgramType string `protobuf:"bytes,2,opt,name=program_type,json=programType,proto3" json:"program_type,omitempty"` LevelCount int32 `protobuf:"varint,3,opt,name=level_count,json=levelCount,proto3" json:"level_count,omitempty"` @@ -17490,6 +17306,8 @@ type VipProgramConfig 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 *VipProgramConfig) Reset() { @@ -17623,12 +17441,9 @@ func (x *VipProgramConfig) GetUpdatedAtMs() int64 { // VipBenefit 是服务端可执行的权益事实。resource_id 为 0 表示纯功能特权,非 0 时 // 指向钱包资源;trial_enabled=false 的权益不会进入体验卡产生的 effective_benefits。 type VipBenefit struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BenefitCode string `protobuf:"bytes,1,opt,name=benefit_code,json=benefitCode,proto3" json:"benefit_code,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + BenefitCode string `protobuf:"bytes,1,opt,name=benefit_code,json=benefitCode,proto3" json:"benefit_code,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // benefit_type: decoration/function。 BenefitType string `protobuf:"bytes,3,opt,name=benefit_type,json=benefitType,proto3" json:"benefit_type,omitempty"` // unlock_level 只作为 P1 默认矩阵的来源信息;后台仍按每个等级提交完整权益集合, @@ -17639,12 +17454,15 @@ type VipBenefit struct { ResourceId int64 `protobuf:"varint,7,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` ResourceType string `protobuf:"bytes,8,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` // execution_scope 标识 wallet/room/user/notice 等实际权限执行方,不代表服务间直连。 - ExecutionScope string `protobuf:"bytes,9,opt,name=execution_scope,json=executionScope,proto3" json:"execution_scope,omitempty"` - AutoEquip bool `protobuf:"varint,10,opt,name=auto_equip,json=autoEquip,proto3" json:"auto_equip,omitempty"` - SortOrder int32 `protobuf:"varint,11,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - MetadataJson string `protobuf:"bytes,12,opt,name=metadata_json,json=metadataJson,proto3" json:"metadata_json,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"` + ExecutionScope string `protobuf:"bytes,9,opt,name=execution_scope,json=executionScope,proto3" json:"execution_scope,omitempty"` + AutoEquip bool `protobuf:"varint,10,opt,name=auto_equip,json=autoEquip,proto3" json:"auto_equip,omitempty"` + SortOrder int32 `protobuf:"varint,11,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + MetadataJson string `protobuf:"bytes,12,opt,name=metadata_json,json=metadataJson,proto3" json:"metadata_json,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"` + Presentation *VipBenefitPresentation `protobuf:"bytes,15,opt,name=presentation,proto3" json:"presentation,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *VipBenefit) Reset() { @@ -17775,29 +17593,35 @@ func (x *VipBenefit) GetUpdatedAtMs() int64 { return 0 } -type VipLevel struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields +func (x *VipBenefit) GetPresentation() *VipBenefitPresentation { + if x != nil { + return x.Presentation + } + return nil +} - 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"` +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"` // benefits 是后台为该等级显式保存的最终权益集合,运行时不按 unlock_level 自动继承。 Benefits []*VipBenefit `protobuf:"bytes,16,rep,name=benefits,proto3" json:"benefits,omitempty"` ConfigVersion int64 `protobuf:"varint,17,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *VipLevel) Reset() { @@ -17950,19 +17774,18 @@ func (x *VipLevel) GetConfigVersion() int64 { } type UserVip struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + ProgramType string `protobuf:"bytes,8,opt,name=program_type,json=programType,proto3" json:"program_type,omitempty"` + ConfigVersion int64 `protobuf:"varint,9,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` 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"` - ProgramType string `protobuf:"bytes,8,opt,name=program_type,json=programType,proto3" json:"program_type,omitempty"` - ConfigVersion int64 `protobuf:"varint,9,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UserVip) Reset() { @@ -18061,26 +17884,25 @@ func (x *UserVip) GetConfigVersion() int64 { // VipTrialCard 是体验卡背包权益的 VIP 投影。entitlement_id 复用通用背包佩戴事实, // 切换卡片只改变装备记录,不修改任何卡片自身的 expires_at_ms。 type VipTrialCard struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TrialCardId string `protobuf:"bytes,1,opt,name=trial_card_id,json=trialCardId,proto3" json:"trial_card_id,omitempty"` - EntitlementId string `protobuf:"bytes,2,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` - ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - UserId int64 `protobuf:"varint,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Level int32 `protobuf:"varint,5,opt,name=level,proto3" json:"level,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"` - Equipped bool `protobuf:"varint,8,opt,name=equipped,proto3" json:"equipped,omitempty"` - DurationMs int64 `protobuf:"varint,9,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` - EffectiveAtMs int64 `protobuf:"varint,10,opt,name=effective_at_ms,json=effectiveAtMs,proto3" json:"effective_at_ms,omitempty"` - ExpiresAtMs int64 `protobuf:"varint,11,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - RemainingDurationMs int64 `protobuf:"varint,12,opt,name=remaining_duration_ms,json=remainingDurationMs,proto3" json:"remaining_duration_ms,omitempty"` - GrantSource string `protobuf:"bytes,13,opt,name=grant_source,json=grantSource,proto3" json:"grant_source,omitempty"` - SourceGrantId string `protobuf:"bytes,14,opt,name=source_grant_id,json=sourceGrantId,proto3" json:"source_grant_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"` + state protoimpl.MessageState `protogen:"open.v1"` + TrialCardId string `protobuf:"bytes,1,opt,name=trial_card_id,json=trialCardId,proto3" json:"trial_card_id,omitempty"` + EntitlementId string `protobuf:"bytes,2,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` + ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + UserId int64 `protobuf:"varint,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Level int32 `protobuf:"varint,5,opt,name=level,proto3" json:"level,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"` + Equipped bool `protobuf:"varint,8,opt,name=equipped,proto3" json:"equipped,omitempty"` + DurationMs int64 `protobuf:"varint,9,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` + EffectiveAtMs int64 `protobuf:"varint,10,opt,name=effective_at_ms,json=effectiveAtMs,proto3" json:"effective_at_ms,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,11,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` + RemainingDurationMs int64 `protobuf:"varint,12,opt,name=remaining_duration_ms,json=remainingDurationMs,proto3" json:"remaining_duration_ms,omitempty"` + GrantSource string `protobuf:"bytes,13,opt,name=grant_source,json=grantSource,proto3" json:"grant_source,omitempty"` + SourceGrantId string `protobuf:"bytes,14,opt,name=source_grant_id,json=sourceGrantId,proto3" json:"source_grant_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"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *VipTrialCard) Reset() { @@ -18226,17 +18048,19 @@ func (x *VipTrialCard) GetUpdatedAtMs() int64 { } // VipUserSettings 是用户按 App 隔离的可关闭 VIP 功能偏好。没有持久记录时 wallet -// 仍返回两个默认开启值,updated_at_ms=0;设置本身不授予任何 VIP 权益。 +// 仍返回五个默认开启值,updated_at_ms=0;设置本身不授予任何 VIP 权益。 type VipUserSettings struct { - 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"` - UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - RoomEntryNoticeEnabled bool `protobuf:"varint,3,opt,name=room_entry_notice_enabled,json=roomEntryNoticeEnabled,proto3" json:"room_entry_notice_enabled,omitempty"` - OnlineGlobalNoticeEnabled bool `protobuf:"varint,4,opt,name=online_global_notice_enabled,json=onlineGlobalNoticeEnabled,proto3" json:"online_global_notice_enabled,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,5,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + RoomEntryNoticeEnabled bool `protobuf:"varint,3,opt,name=room_entry_notice_enabled,json=roomEntryNoticeEnabled,proto3" json:"room_entry_notice_enabled,omitempty"` + OnlineGlobalNoticeEnabled bool `protobuf:"varint,4,opt,name=online_global_notice_enabled,json=onlineGlobalNoticeEnabled,proto3" json:"online_global_notice_enabled,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,5,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + HideProfileDataEnabled bool `protobuf:"varint,6,opt,name=hide_profile_data_enabled,json=hideProfileDataEnabled,proto3" json:"hide_profile_data_enabled,omitempty"` + AnonymousProfileVisitEnabled bool `protobuf:"varint,7,opt,name=anonymous_profile_visit_enabled,json=anonymousProfileVisitEnabled,proto3" json:"anonymous_profile_visit_enabled,omitempty"` + LeaderboardInvisibleEnabled bool `protobuf:"varint,8,opt,name=leaderboard_invisible_enabled,json=leaderboardInvisibleEnabled,proto3" json:"leaderboard_invisible_enabled,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *VipUserSettings) Reset() { @@ -18304,23 +18128,43 @@ func (x *VipUserSettings) GetUpdatedAtMs() int64 { return 0 } +func (x *VipUserSettings) GetHideProfileDataEnabled() bool { + if x != nil { + return x.HideProfileDataEnabled + } + return false +} + +func (x *VipUserSettings) GetAnonymousProfileVisitEnabled() bool { + if x != nil { + return x.AnonymousProfileVisitEnabled + } + return false +} + +func (x *VipUserSettings) GetLeaderboardInvisibleEnabled() bool { + if x != nil { + return x.LeaderboardInvisibleEnabled + } + return false +} + // VipState 同时返回付费会员、当前佩戴体验卡和最终生效会员,避免调用方自行合并两层状态。 // effective_benefits 是钱包按 paid/trial 来源、该等级显式矩阵和 trial_enabled 过滤后的资格事实; // 对可关闭通知,执行方还必须结合 user_settings 或调用 CheckVipBenefit。 type VipState struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PaidVip *UserVip `protobuf:"bytes,1,opt,name=paid_vip,json=paidVip,proto3" json:"paid_vip,omitempty"` - EquippedTrialCard *VipTrialCard `protobuf:"bytes,2,opt,name=equipped_trial_card,json=equippedTrialCard,proto3" json:"equipped_trial_card,omitempty"` - EffectiveVip *UserVip `protobuf:"bytes,3,opt,name=effective_vip,json=effectiveVip,proto3" json:"effective_vip,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + PaidVip *UserVip `protobuf:"bytes,1,opt,name=paid_vip,json=paidVip,proto3" json:"paid_vip,omitempty"` + EquippedTrialCard *VipTrialCard `protobuf:"bytes,2,opt,name=equipped_trial_card,json=equippedTrialCard,proto3" json:"equipped_trial_card,omitempty"` + EffectiveVip *UserVip `protobuf:"bytes,3,opt,name=effective_vip,json=effectiveVip,proto3" json:"effective_vip,omitempty"` // effective_source: paid/trial/none。 EffectiveSource string `protobuf:"bytes,4,opt,name=effective_source,json=effectiveSource,proto3" json:"effective_source,omitempty"` EffectiveBenefits []*VipBenefit `protobuf:"bytes,5,rep,name=effective_benefits,json=effectiveBenefits,proto3" json:"effective_benefits,omitempty"` EvaluatedAtMs int64 `protobuf:"varint,6,opt,name=evaluated_at_ms,json=evaluatedAtMs,proto3" json:"evaluated_at_ms,omitempty"` ProgramConfig *VipProgramConfig `protobuf:"bytes,7,opt,name=program_config,json=programConfig,proto3" json:"program_config,omitempty"` UserSettings *VipUserSettings `protobuf:"bytes,8,opt,name=user_settings,json=userSettings,proto3" json:"user_settings,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *VipState) Reset() { @@ -18410,13 +18254,12 @@ func (x *VipState) GetUserSettings() *VipUserSettings { } type ListVipPackagesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListVipPackagesRequest) Reset() { @@ -18471,14 +18314,13 @@ func (x *ListVipPackagesRequest) GetUserId() int64 { } type ListVipPackagesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + State *VipState `protobuf:"bytes,3,opt,name=state,proto3" json:"state,omitempty"` + ProgramConfig *VipProgramConfig `protobuf:"bytes,4,opt,name=program_config,json=programConfig,proto3" json:"program_config,omitempty"` 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"` - State *VipState `protobuf:"bytes,3,opt,name=state,proto3" json:"state,omitempty"` - ProgramConfig *VipProgramConfig `protobuf:"bytes,4,opt,name=program_config,json=programConfig,proto3" json:"program_config,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListVipPackagesResponse) Reset() { @@ -18540,13 +18382,12 @@ func (x *ListVipPackagesResponse) GetProgramConfig() *VipProgramConfig { } type GetMyVipRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetMyVipRequest) Reset() { @@ -18601,12 +18442,11 @@ func (x *GetMyVipRequest) GetUserId() int64 { } type GetMyVipResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Vip *UserVip `protobuf:"bytes,1,opt,name=vip,proto3" json:"vip,omitempty"` + State *VipState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` unknownFields protoimpl.UnknownFields - - Vip *UserVip `protobuf:"bytes,1,opt,name=vip,proto3" json:"vip,omitempty"` - State *VipState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetMyVipResponse) Reset() { @@ -18654,14 +18494,13 @@ func (x *GetMyVipResponse) GetState() *VipState { } type PurchaseVipRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *PurchaseVipRequest) Reset() { @@ -18723,17 +18562,18 @@ func (x *PurchaseVipRequest) GetLevel() int32 { } type PurchaseVipResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + State *VipState `protobuf:"bytes,7,opt,name=state,proto3" json:"state,omitempty"` + // coin_balance 是购买事务提交后的带版本余额快照;coin_balance_after 仅保留旧客户端兼容。 + CoinBalance *AssetBalance `protobuf:"bytes,8,opt,name=coin_balance,json=coinBalance,proto3" json:"coin_balance,omitempty"` 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"` - State *VipState `protobuf:"bytes,7,opt,name=state,proto3" json:"state,omitempty"` + sizeCache protoimpl.SizeCache } func (x *PurchaseVipResponse) Reset() { @@ -18815,17 +18655,23 @@ func (x *PurchaseVipResponse) GetState() *VipState { return nil } -type DebitCPBreakupFeeRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields +func (x *PurchaseVipResponse) GetCoinBalance() *AssetBalance { + if x != nil { + return x.CoinBalance + } + return nil +} - 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"` - RelationshipId string `protobuf:"bytes,4,opt,name=relationship_id,json=relationshipId,proto3" json:"relationship_id,omitempty"` - RelationType string `protobuf:"bytes,5,opt,name=relation_type,json=relationType,proto3" json:"relation_type,omitempty"` - Amount int64 `protobuf:"varint,6,opt,name=amount,proto3" json:"amount,omitempty"` +type DebitCPBreakupFeeRequest 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"` + RelationshipId string `protobuf:"bytes,4,opt,name=relationship_id,json=relationshipId,proto3" json:"relationship_id,omitempty"` + RelationType string `protobuf:"bytes,5,opt,name=relation_type,json=relationType,proto3" json:"relation_type,omitempty"` + Amount int64 `protobuf:"varint,6,opt,name=amount,proto3" json:"amount,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *DebitCPBreakupFeeRequest) Reset() { @@ -18901,14 +18747,13 @@ func (x *DebitCPBreakupFeeRequest) GetAmount() int64 { } type DebitCPBreakupFeeResponse struct { - 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"` - CoinSpent int64 `protobuf:"varint,2,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` - CoinBalanceAfter int64 `protobuf:"varint,3,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` - Balance *AssetBalance `protobuf:"bytes,4,opt,name=balance,proto3" json:"balance,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + CoinSpent int64 `protobuf:"varint,2,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` + CoinBalanceAfter int64 `protobuf:"varint,3,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + Balance *AssetBalance `protobuf:"bytes,4,opt,name=balance,proto3" json:"balance,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *DebitCPBreakupFeeResponse) Reset() { @@ -18970,16 +18815,15 @@ func (x *DebitCPBreakupFeeResponse) GetBalance() *AssetBalance { } type DebitWheelDrawRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + WheelId string `protobuf:"bytes,4,opt,name=wheel_id,json=wheelId,proto3" json:"wheel_id,omitempty"` + DrawCount int32 `protobuf:"varint,5,opt,name=draw_count,json=drawCount,proto3" json:"draw_count,omitempty"` + Amount int64 `protobuf:"varint,6,opt,name=amount,proto3" json:"amount,omitempty"` 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"` - WheelId string `protobuf:"bytes,4,opt,name=wheel_id,json=wheelId,proto3" json:"wheel_id,omitempty"` - DrawCount int32 `protobuf:"varint,5,opt,name=draw_count,json=drawCount,proto3" json:"draw_count,omitempty"` - Amount int64 `protobuf:"varint,6,opt,name=amount,proto3" json:"amount,omitempty"` + sizeCache protoimpl.SizeCache } func (x *DebitWheelDrawRequest) Reset() { @@ -19055,14 +18899,13 @@ func (x *DebitWheelDrawRequest) GetAmount() int64 { } type DebitWheelDrawResponse struct { - 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"` - CoinSpent int64 `protobuf:"varint,2,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` - CoinBalanceAfter int64 `protobuf:"varint,3,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` - Balance *AssetBalance `protobuf:"bytes,4,opt,name=balance,proto3" json:"balance,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + CoinSpent int64 `protobuf:"varint,2,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` + CoinBalanceAfter int64 `protobuf:"varint,3,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + Balance *AssetBalance `protobuf:"bytes,4,opt,name=balance,proto3" json:"balance,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *DebitWheelDrawResponse) Reset() { @@ -19124,17 +18967,16 @@ func (x *DebitWheelDrawResponse) GetBalance() *AssetBalance { } type GrantVipRequest struct { - 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"` + 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 } func (x *GrantVipRequest) Reset() { @@ -19217,15 +19059,14 @@ func (x *GrantVipRequest) GetReason() string { } type GrantVipResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + State *VipState `protobuf:"bytes,5,opt,name=state,proto3" json:"state,omitempty"` 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"` - State *VipState `protobuf:"bytes,5,opt,name=state,proto3" json:"state,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GrantVipResponse) Reset() { @@ -19294,12 +19135,11 @@ func (x *GrantVipResponse) GetState() *VipState { } type GetVipProgramConfigRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetVipProgramConfigRequest) Reset() { @@ -19347,13 +19187,12 @@ func (x *GetVipProgramConfigRequest) GetAppCode() string { } type GetVipProgramConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Config *VipProgramConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + Benefits []*VipBenefit `protobuf:"bytes,2,rep,name=benefits,proto3" json:"benefits,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` unknownFields protoimpl.UnknownFields - - Config *VipProgramConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - Benefits []*VipBenefit `protobuf:"bytes,2,rep,name=benefits,proto3" json:"benefits,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetVipProgramConfigResponse) Reset() { @@ -19410,14 +19249,13 @@ func (x *GetVipProgramConfigResponse) GetServerTimeMs() int64 { // UpdateAdminVipProgramConfigRequest 以完整配置替换单 App 当前规则;config_version 由服务端递增, // 客户端提交的审计时间和操作者字段不会被信任。 type UpdateAdminVipProgramConfigRequest struct { - 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"` - Config *VipProgramConfig `protobuf:"bytes,3,opt,name=config,proto3" json:"config,omitempty"` - OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + 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"` + Config *VipProgramConfig `protobuf:"bytes,3,opt,name=config,proto3" json:"config,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 *UpdateAdminVipProgramConfigRequest) Reset() { @@ -19479,12 +19317,11 @@ func (x *UpdateAdminVipProgramConfigRequest) GetOperatorUserId() int64 { } type UpdateAdminVipProgramConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Config *VipProgramConfig `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 - - Config *VipProgramConfig `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"` + sizeCache protoimpl.SizeCache } func (x *UpdateAdminVipProgramConfigResponse) Reset() { @@ -19533,15 +19370,17 @@ func (x *UpdateAdminVipProgramConfigResponse) GetServerTimeMs() int64 { // UpdateMyVipSettingsRequest 使用 optional 保留 PATCH 语义;显式 false 不能被当成未提交。 type UpdateMyVipSettingsRequest struct { - 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"` - RoomEntryNoticeEnabled *bool `protobuf:"varint,4,opt,name=room_entry_notice_enabled,json=roomEntryNoticeEnabled,proto3,oneof" json:"room_entry_notice_enabled,omitempty"` - OnlineGlobalNoticeEnabled *bool `protobuf:"varint,5,opt,name=online_global_notice_enabled,json=onlineGlobalNoticeEnabled,proto3,oneof" json:"online_global_notice_enabled,omitempty"` + 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"` + RoomEntryNoticeEnabled *bool `protobuf:"varint,4,opt,name=room_entry_notice_enabled,json=roomEntryNoticeEnabled,proto3,oneof" json:"room_entry_notice_enabled,omitempty"` + OnlineGlobalNoticeEnabled *bool `protobuf:"varint,5,opt,name=online_global_notice_enabled,json=onlineGlobalNoticeEnabled,proto3,oneof" json:"online_global_notice_enabled,omitempty"` + HideProfileDataEnabled *bool `protobuf:"varint,6,opt,name=hide_profile_data_enabled,json=hideProfileDataEnabled,proto3,oneof" json:"hide_profile_data_enabled,omitempty"` + AnonymousProfileVisitEnabled *bool `protobuf:"varint,7,opt,name=anonymous_profile_visit_enabled,json=anonymousProfileVisitEnabled,proto3,oneof" json:"anonymous_profile_visit_enabled,omitempty"` + LeaderboardInvisibleEnabled *bool `protobuf:"varint,8,opt,name=leaderboard_invisible_enabled,json=leaderboardInvisibleEnabled,proto3,oneof" json:"leaderboard_invisible_enabled,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *UpdateMyVipSettingsRequest) Reset() { @@ -19609,13 +19448,33 @@ func (x *UpdateMyVipSettingsRequest) GetOnlineGlobalNoticeEnabled() bool { return false } -type UpdateMyVipSettingsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields +func (x *UpdateMyVipSettingsRequest) GetHideProfileDataEnabled() bool { + if x != nil && x.HideProfileDataEnabled != nil { + return *x.HideProfileDataEnabled + } + return false +} - Settings *VipUserSettings `protobuf:"bytes,1,opt,name=settings,proto3" json:"settings,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` +func (x *UpdateMyVipSettingsRequest) GetAnonymousProfileVisitEnabled() bool { + if x != nil && x.AnonymousProfileVisitEnabled != nil { + return *x.AnonymousProfileVisitEnabled + } + return false +} + +func (x *UpdateMyVipSettingsRequest) GetLeaderboardInvisibleEnabled() bool { + if x != nil && x.LeaderboardInvisibleEnabled != nil { + return *x.LeaderboardInvisibleEnabled + } + return false +} + +type UpdateMyVipSettingsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Settings *VipUserSettings `protobuf:"bytes,1,opt,name=settings,proto3" json:"settings,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 *UpdateMyVipSettingsResponse) Reset() { @@ -19665,23 +19524,22 @@ func (x *UpdateMyVipSettingsResponse) GetServerTimeMs() int64 { // VipDailyCoinRebateRun 固化某个 UTC 自然日的返现金额矩阵。批任务开始后即使后台 // 修改等级权益,后续分页也只能复用本 run 的 config_version/level_amounts_json。 type VipDailyCoinRebateRun struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RunId string `protobuf:"bytes,1,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"` - TaskDay string `protobuf:"bytes,2,opt,name=task_day,json=taskDay,proto3" json:"task_day,omitempty"` - DayStartMs int64 `protobuf:"varint,3,opt,name=day_start_ms,json=dayStartMs,proto3" json:"day_start_ms,omitempty"` - DayEndMs int64 `protobuf:"varint,4,opt,name=day_end_ms,json=dayEndMs,proto3" json:"day_end_ms,omitempty"` - ConfigVersion int64 `protobuf:"varint,5,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` - LevelAmountsJson string `protobuf:"bytes,6,opt,name=level_amounts_json,json=levelAmountsJson,proto3" json:"level_amounts_json,omitempty"` - Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` - LastUserId int64 `protobuf:"varint,8,opt,name=last_user_id,json=lastUserId,proto3" json:"last_user_id,omitempty"` - ScannedCount int64 `protobuf:"varint,9,opt,name=scanned_count,json=scannedCount,proto3" json:"scanned_count,omitempty"` - CreatedCount int64 `protobuf:"varint,10,opt,name=created_count,json=createdCount,proto3" json:"created_count,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"` - CompletedAtMs int64 `protobuf:"varint,13,opt,name=completed_at_ms,json=completedAtMs,proto3" json:"completed_at_ms,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + RunId string `protobuf:"bytes,1,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"` + TaskDay string `protobuf:"bytes,2,opt,name=task_day,json=taskDay,proto3" json:"task_day,omitempty"` + DayStartMs int64 `protobuf:"varint,3,opt,name=day_start_ms,json=dayStartMs,proto3" json:"day_start_ms,omitempty"` + DayEndMs int64 `protobuf:"varint,4,opt,name=day_end_ms,json=dayEndMs,proto3" json:"day_end_ms,omitempty"` + ConfigVersion int64 `protobuf:"varint,5,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` + LevelAmountsJson string `protobuf:"bytes,6,opt,name=level_amounts_json,json=levelAmountsJson,proto3" json:"level_amounts_json,omitempty"` + Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` + LastUserId int64 `protobuf:"varint,8,opt,name=last_user_id,json=lastUserId,proto3" json:"last_user_id,omitempty"` + ScannedCount int64 `protobuf:"varint,9,opt,name=scanned_count,json=scannedCount,proto3" json:"scanned_count,omitempty"` + CreatedCount int64 `protobuf:"varint,10,opt,name=created_count,json=createdCount,proto3" json:"created_count,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"` + CompletedAtMs int64 `protobuf:"varint,13,opt,name=completed_at_ms,json=completedAtMs,proto3" json:"completed_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *VipDailyCoinRebateRun) Reset() { @@ -19808,24 +19666,23 @@ func (x *VipDailyCoinRebateRun) GetCompletedAtMs() int64 { // VipDailyCoinRebate 是付费 VIP 在 UTC 日切时生成的可领取金币事实。体验卡不会生成; // status 返回 claimable/claimed/expired,expired 可由查询时钟投影而不改写历史行。 type VipDailyCoinRebate struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RebateId string `protobuf:"bytes,1,opt,name=rebate_id,json=rebateId,proto3" json:"rebate_id,omitempty"` - UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - TaskDay string `protobuf:"bytes,3,opt,name=task_day,json=taskDay,proto3" json:"task_day,omitempty"` - VipLevel int32 `protobuf:"varint,4,opt,name=vip_level,json=vipLevel,proto3" json:"vip_level,omitempty"` - VipName string `protobuf:"bytes,5,opt,name=vip_name,json=vipName,proto3" json:"vip_name,omitempty"` - CoinAmount int64 `protobuf:"varint,6,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` - AvailableAtMs int64 `protobuf:"varint,8,opt,name=available_at_ms,json=availableAtMs,proto3" json:"available_at_ms,omitempty"` - ExpiresAtMs int64 `protobuf:"varint,9,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - ConfigVersion int64 `protobuf:"varint,10,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` - ClaimedAtMs int64 `protobuf:"varint,11,opt,name=claimed_at_ms,json=claimedAtMs,proto3" json:"claimed_at_ms,omitempty"` - WalletTransactionId string `protobuf:"bytes,12,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_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"` + state protoimpl.MessageState `protogen:"open.v1"` + RebateId string `protobuf:"bytes,1,opt,name=rebate_id,json=rebateId,proto3" json:"rebate_id,omitempty"` + UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + TaskDay string `protobuf:"bytes,3,opt,name=task_day,json=taskDay,proto3" json:"task_day,omitempty"` + VipLevel int32 `protobuf:"varint,4,opt,name=vip_level,json=vipLevel,proto3" json:"vip_level,omitempty"` + VipName string `protobuf:"bytes,5,opt,name=vip_name,json=vipName,proto3" json:"vip_name,omitempty"` + CoinAmount int64 `protobuf:"varint,6,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` + AvailableAtMs int64 `protobuf:"varint,8,opt,name=available_at_ms,json=availableAtMs,proto3" json:"available_at_ms,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,9,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` + ConfigVersion int64 `protobuf:"varint,10,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` + ClaimedAtMs int64 `protobuf:"varint,11,opt,name=claimed_at_ms,json=claimedAtMs,proto3" json:"claimed_at_ms,omitempty"` + WalletTransactionId string `protobuf:"bytes,12,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_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 *VipDailyCoinRebate) Reset() { @@ -19959,14 +19816,13 @@ func (x *VipDailyCoinRebate) GetUpdatedAtMs() int64 { // ProcessVipDailyCoinRebateBatchRequest 由 WalletCronService 接收。task_day 为空时按 // wallet-service 当前 UTC 日期处理;同 App+task_day 始终创建或复用同一个 run。 type ProcessVipDailyCoinRebateBatchRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + TaskDay string `protobuf:"bytes,3,opt,name=task_day,json=taskDay,proto3" json:"task_day,omitempty"` + BatchSize int32 `protobuf:"varint,4,opt,name=batch_size,json=batchSize,proto3" json:"batch_size,omitempty"` 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"` - TaskDay string `protobuf:"bytes,3,opt,name=task_day,json=taskDay,proto3" json:"task_day,omitempty"` - BatchSize int32 `protobuf:"varint,4,opt,name=batch_size,json=batchSize,proto3" json:"batch_size,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ProcessVipDailyCoinRebateBatchRequest) Reset() { @@ -20028,15 +19884,14 @@ func (x *ProcessVipDailyCoinRebateBatchRequest) GetBatchSize() int32 { } type ProcessVipDailyCoinRebateBatchResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Run *VipDailyCoinRebateRun `protobuf:"bytes,1,opt,name=run,proto3" json:"run,omitempty"` + ScannedCount int32 `protobuf:"varint,2,opt,name=scanned_count,json=scannedCount,proto3" json:"scanned_count,omitempty"` + CreatedCount int32 `protobuf:"varint,3,opt,name=created_count,json=createdCount,proto3" json:"created_count,omitempty"` + HasMore bool `protobuf:"varint,4,opt,name=has_more,json=hasMore,proto3" json:"has_more,omitempty"` + ServerTimeMs int64 `protobuf:"varint,5,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` unknownFields protoimpl.UnknownFields - - Run *VipDailyCoinRebateRun `protobuf:"bytes,1,opt,name=run,proto3" json:"run,omitempty"` - ScannedCount int32 `protobuf:"varint,2,opt,name=scanned_count,json=scannedCount,proto3" json:"scanned_count,omitempty"` - CreatedCount int32 `protobuf:"varint,3,opt,name=created_count,json=createdCount,proto3" json:"created_count,omitempty"` - HasMore bool `protobuf:"varint,4,opt,name=has_more,json=hasMore,proto3" json:"has_more,omitempty"` - ServerTimeMs int64 `protobuf:"varint,5,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ProcessVipDailyCoinRebateBatchResponse) Reset() { @@ -20105,13 +19960,12 @@ func (x *ProcessVipDailyCoinRebateBatchResponse) GetServerTimeMs() int64 { } type GetMyCurrentVipDailyCoinRebateRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetMyCurrentVipDailyCoinRebateRequest) Reset() { @@ -20166,13 +20020,12 @@ func (x *GetMyCurrentVipDailyCoinRebateRequest) GetUserId() int64 { } type GetMyCurrentVipDailyCoinRebateResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Found bool `protobuf:"varint,1,opt,name=found,proto3" json:"found,omitempty"` + Rebate *VipDailyCoinRebate `protobuf:"bytes,2,opt,name=rebate,proto3" json:"rebate,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` unknownFields protoimpl.UnknownFields - - Found bool `protobuf:"varint,1,opt,name=found,proto3" json:"found,omitempty"` - Rebate *VipDailyCoinRebate `protobuf:"bytes,2,opt,name=rebate,proto3" json:"rebate,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetMyCurrentVipDailyCoinRebateResponse) Reset() { @@ -20227,17 +20080,16 @@ func (x *GetMyCurrentVipDailyCoinRebateResponse) GetServerTimeMs() int64 { } type ListMyVipDailyCoinRebateStatusesRequest struct { - 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"` - 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"` + 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"` + 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"` // rebate_ids 非空时精确恢复指定通知的领取状态,最多 100 个;仍强制按 user_id 隔离。 - RebateIds []string `protobuf:"bytes,6,rep,name=rebate_ids,json=rebateIds,proto3" json:"rebate_ids,omitempty"` + RebateIds []string `protobuf:"bytes,6,rep,name=rebate_ids,json=rebateIds,proto3" json:"rebate_ids,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListMyVipDailyCoinRebateStatusesRequest) Reset() { @@ -20313,13 +20165,12 @@ func (x *ListMyVipDailyCoinRebateStatusesRequest) GetRebateIds() []string { } type ListMyVipDailyCoinRebateStatusesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Rebates []*VipDailyCoinRebate `protobuf:"bytes,1,rep,name=rebates,proto3" json:"rebates,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 - - Rebates []*VipDailyCoinRebate `protobuf:"bytes,1,rep,name=rebates,proto3" json:"rebates,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"` + sizeCache protoimpl.SizeCache } func (x *ListMyVipDailyCoinRebateStatusesResponse) Reset() { @@ -20374,14 +20225,13 @@ func (x *ListMyVipDailyCoinRebateStatusesResponse) GetServerTimeMs() int64 { } type ClaimVipDailyCoinRebateRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + RebateId string `protobuf:"bytes,4,opt,name=rebate_id,json=rebateId,proto3" json:"rebate_id,omitempty"` 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"` - RebateId string `protobuf:"bytes,4,opt,name=rebate_id,json=rebateId,proto3" json:"rebate_id,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ClaimVipDailyCoinRebateRequest) Reset() { @@ -20443,14 +20293,13 @@ func (x *ClaimVipDailyCoinRebateRequest) GetRebateId() string { } type ClaimVipDailyCoinRebateResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Rebate *VipDailyCoinRebate `protobuf:"bytes,1,opt,name=rebate,proto3" json:"rebate,omitempty"` + TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + CoinBalance *AssetBalance `protobuf:"bytes,3,opt,name=coin_balance,json=coinBalance,proto3" json:"coin_balance,omitempty"` + ServerTimeMs int64 `protobuf:"varint,4,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` unknownFields protoimpl.UnknownFields - - Rebate *VipDailyCoinRebate `protobuf:"bytes,1,opt,name=rebate,proto3" json:"rebate,omitempty"` - TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - CoinBalance *AssetBalance `protobuf:"bytes,3,opt,name=coin_balance,json=coinBalance,proto3" json:"coin_balance,omitempty"` - ServerTimeMs int64 `protobuf:"varint,4,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ClaimVipDailyCoinRebateResponse) Reset() { @@ -20514,19 +20363,18 @@ func (x *ClaimVipDailyCoinRebateResponse) GetServerTimeMs() int64 { // GrantVipTrialCardRequest 允许后台直接按 level+duration_ms 发卡;resource_id 为空时按 // vip_trial_card_{level} 解析同 App 预置资源,非空时也必须匹配该等级。 type GrantVipTrialCardRequest struct { - 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"` - DurationMs int64 `protobuf:"varint,5,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` - ResourceId *int64 `protobuf:"varint,6,opt,name=resource_id,json=resourceId,proto3,oneof" json:"resource_id,omitempty"` - GrantSource string `protobuf:"bytes,7,opt,name=grant_source,json=grantSource,proto3" json:"grant_source,omitempty"` - OperatorUserId int64 `protobuf:"varint,8,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - Reason string `protobuf:"bytes,9,opt,name=reason,proto3" json:"reason,omitempty"` + 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"` + DurationMs int64 `protobuf:"varint,5,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` + ResourceId *int64 `protobuf:"varint,6,opt,name=resource_id,json=resourceId,proto3,oneof" json:"resource_id,omitempty"` + GrantSource string `protobuf:"bytes,7,opt,name=grant_source,json=grantSource,proto3" json:"grant_source,omitempty"` + OperatorUserId int64 `protobuf:"varint,8,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + Reason string `protobuf:"bytes,9,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GrantVipTrialCardRequest) Reset() { @@ -20623,13 +20471,12 @@ func (x *GrantVipTrialCardRequest) GetReason() string { } type GrantVipTrialCardResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + TrialCard *VipTrialCard `protobuf:"bytes,1,opt,name=trial_card,json=trialCard,proto3" json:"trial_card,omitempty"` + State *VipState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` unknownFields protoimpl.UnknownFields - - TrialCard *VipTrialCard `protobuf:"bytes,1,opt,name=trial_card,json=trialCard,proto3" json:"trial_card,omitempty"` - State *VipState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GrantVipTrialCardResponse) Reset() { @@ -20684,15 +20531,14 @@ func (x *GrantVipTrialCardResponse) GetServerTimeMs() int64 { } type EquipVipTrialCardRequest struct { - 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"` + 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"` // entitlement_id 是背包实例标识,保证同资源的多张卡也能被精确佩戴。 EntitlementId string `protobuf:"bytes,4,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *EquipVipTrialCardRequest) Reset() { @@ -20754,13 +20600,12 @@ func (x *EquipVipTrialCardRequest) GetEntitlementId() string { } type EquipVipTrialCardResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + TrialCard *VipTrialCard `protobuf:"bytes,1,opt,name=trial_card,json=trialCard,proto3" json:"trial_card,omitempty"` + State *VipState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` unknownFields protoimpl.UnknownFields - - TrialCard *VipTrialCard `protobuf:"bytes,1,opt,name=trial_card,json=trialCard,proto3" json:"trial_card,omitempty"` - State *VipState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *EquipVipTrialCardResponse) Reset() { @@ -20815,13 +20660,12 @@ func (x *EquipVipTrialCardResponse) GetServerTimeMs() int64 { } type UnequipVipTrialCardRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *UnequipVipTrialCardRequest) Reset() { @@ -20876,13 +20720,12 @@ func (x *UnequipVipTrialCardRequest) GetUserId() int64 { } type UnequipVipTrialCardResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Unequipped bool `protobuf:"varint,1,opt,name=unequipped,proto3" json:"unequipped,omitempty"` + State *VipState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` unknownFields protoimpl.UnknownFields - - Unequipped bool `protobuf:"varint,1,opt,name=unequipped,proto3" json:"unequipped,omitempty"` - State *VipState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UnequipVipTrialCardResponse) Reset() { @@ -20939,14 +20782,13 @@ func (x *UnequipVipTrialCardResponse) GetServerTimeMs() int64 { // CheckVipBenefit 供 room/user 等权益执行方校验单个特权。调用方不能只比较 VIP level, // 因为体验卡排除项和 App 配置会改变最终可执行权益集合。 type CheckVipBenefitRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + BenefitCode string `protobuf:"bytes,4,opt,name=benefit_code,json=benefitCode,proto3" json:"benefit_code,omitempty"` 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"` - BenefitCode string `protobuf:"bytes,4,opt,name=benefit_code,json=benefitCode,proto3" json:"benefit_code,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CheckVipBenefitRequest) Reset() { @@ -21008,15 +20850,14 @@ func (x *CheckVipBenefitRequest) GetBenefitCode() string { } type CheckVipBenefitResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Allowed bool `protobuf:"varint,1,opt,name=allowed,proto3" json:"allowed,omitempty"` + Benefit *VipBenefit `protobuf:"bytes,2,opt,name=benefit,proto3" json:"benefit,omitempty"` + State *VipState `protobuf:"bytes,3,opt,name=state,proto3" json:"state,omitempty"` + DenialReason string `protobuf:"bytes,4,opt,name=denial_reason,json=denialReason,proto3" json:"denial_reason,omitempty"` + EvaluatedAtMs int64 `protobuf:"varint,5,opt,name=evaluated_at_ms,json=evaluatedAtMs,proto3" json:"evaluated_at_ms,omitempty"` unknownFields protoimpl.UnknownFields - - Allowed bool `protobuf:"varint,1,opt,name=allowed,proto3" json:"allowed,omitempty"` - Benefit *VipBenefit `protobuf:"bytes,2,opt,name=benefit,proto3" json:"benefit,omitempty"` - State *VipState `protobuf:"bytes,3,opt,name=state,proto3" json:"state,omitempty"` - DenialReason string `protobuf:"bytes,4,opt,name=denial_reason,json=denialReason,proto3" json:"denial_reason,omitempty"` - EvaluatedAtMs int64 `protobuf:"varint,5,opt,name=evaluated_at_ms,json=evaluatedAtMs,proto3" json:"evaluated_at_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CheckVipBenefitResponse) Reset() { @@ -21085,20 +20926,19 @@ func (x *CheckVipBenefitResponse) GetEvaluatedAtMs() int64 { } type AdminVipLevelInput struct { - 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"` + 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"` // benefits 是该等级完整、显式的权益集合;服务端不根据 unlock_level 自动继承。 - Benefits []*VipBenefit `protobuf:"bytes,9,rep,name=benefits,proto3" json:"benefits,omitempty"` + Benefits []*VipBenefit `protobuf:"bytes,9,rep,name=benefits,proto3" json:"benefits,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AdminVipLevelInput) Reset() { @@ -21195,12 +21035,11 @@ func (x *AdminVipLevelInput) GetBenefits() []*VipBenefit { } type ListAdminVipLevelsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListAdminVipLevelsRequest) Reset() { @@ -21248,13 +21087,12 @@ func (x *ListAdminVipLevelsRequest) GetAppCode() string { } type ListAdminVipLevelsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + ProgramConfig *VipProgramConfig `protobuf:"bytes,3,opt,name=program_config,json=programConfig,proto3" json:"program_config,omitempty"` 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"` - ProgramConfig *VipProgramConfig `protobuf:"bytes,3,opt,name=program_config,json=programConfig,proto3" json:"program_config,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListAdminVipLevelsResponse) Reset() { @@ -21309,14 +21147,13 @@ func (x *ListAdminVipLevelsResponse) GetProgramConfig() *VipProgramConfig { } type UpdateAdminVipLevelsRequest struct { - 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"` + 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 } func (x *UpdateAdminVipLevelsRequest) Reset() { @@ -21378,13 +21215,12 @@ func (x *UpdateAdminVipLevelsRequest) GetOperatorUserId() int64 { } type UpdateAdminVipLevelsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + ProgramConfig *VipProgramConfig `protobuf:"bytes,3,opt,name=program_config,json=programConfig,proto3" json:"program_config,omitempty"` 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"` - ProgramConfig *VipProgramConfig `protobuf:"bytes,3,opt,name=program_config,json=programConfig,proto3" json:"program_config,omitempty"` + sizeCache protoimpl.SizeCache } func (x *UpdateAdminVipLevelsResponse) Reset() { @@ -21440,19 +21276,18 @@ func (x *UpdateAdminVipLevelsResponse) GetProgramConfig() *VipProgramConfig { // CreditTaskRewardRequest 是 activity-service 领取任务奖励时调用的钱包入账命令。 type CreditTaskRewardRequest struct { - 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"` - RewardAssetType string `protobuf:"bytes,9,opt,name=reward_asset_type,json=rewardAssetType,proto3" json:"reward_asset_type,omitempty"` + 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"` + RewardAssetType string `protobuf:"bytes,9,opt,name=reward_asset_type,json=rewardAssetType,proto3" json:"reward_asset_type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CreditTaskRewardRequest) Reset() { @@ -21550,14 +21385,13 @@ func (x *CreditTaskRewardRequest) GetRewardAssetType() string { // CreditTaskRewardResponse 返回任务奖励入账流水和用户奖励资产账后余额。 type CreditTaskRewardResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *CreditTaskRewardResponse) Reset() { @@ -21620,22 +21454,21 @@ func (x *CreditTaskRewardResponse) GetGrantedAtMs() int64 { // CreditLuckyGiftRewardRequest 是 activity-service 抽奖 outbox 补偿 worker 调用的钱包入账命令。 type CreditLuckyGiftRewardRequest struct { - 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"` + 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"` // country_id 是中奖用户所属国家,钱包 outbox 原样发布给统计服务,避免返奖只落到区域未知国家。 - CountryId int64 `protobuf:"varint,11,opt,name=country_id,json=countryId,proto3" json:"country_id,omitempty"` + CountryId int64 `protobuf:"varint,11,opt,name=country_id,json=countryId,proto3" json:"country_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CreditLuckyGiftRewardRequest) Reset() { @@ -21747,14 +21580,13 @@ func (x *CreditLuckyGiftRewardRequest) GetCountryId() int64 { // CreditLuckyGiftRewardResponse 返回幸运礼物返奖入账流水和用户 COIN 账后余额。 type CreditLuckyGiftRewardResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *CreditLuckyGiftRewardResponse) Reset() { @@ -21817,19 +21649,18 @@ func (x *CreditLuckyGiftRewardResponse) GetGrantedAtMs() int64 { // CreditWheelRewardRequest 是 activity-service 转盘金币奖品 outbox 调用的钱包入账命令。 type CreditWheelRewardRequest struct { - 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"` - WheelId string `protobuf:"bytes,6,opt,name=wheel_id,json=wheelId,proto3" json:"wheel_id,omitempty"` - SelectedTierId string `protobuf:"bytes,7,opt,name=selected_tier_id,json=selectedTierId,proto3" json:"selected_tier_id,omitempty"` - Reason string `protobuf:"bytes,8,opt,name=reason,proto3" json:"reason,omitempty"` - VisibleRegionId int64 `protobuf:"varint,9,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + 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"` + WheelId string `protobuf:"bytes,6,opt,name=wheel_id,json=wheelId,proto3" json:"wheel_id,omitempty"` + SelectedTierId string `protobuf:"bytes,7,opt,name=selected_tier_id,json=selectedTierId,proto3" json:"selected_tier_id,omitempty"` + Reason string `protobuf:"bytes,8,opt,name=reason,proto3" json:"reason,omitempty"` + VisibleRegionId int64 `protobuf:"varint,9,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CreditWheelRewardRequest) Reset() { @@ -21927,14 +21758,13 @@ func (x *CreditWheelRewardRequest) GetVisibleRegionId() int64 { // CreditWheelRewardResponse 返回转盘金币奖品入账流水和用户 COIN 账后余额。 type CreditWheelRewardResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *CreditWheelRewardResponse) Reset() { @@ -21997,22 +21827,21 @@ func (x *CreditWheelRewardResponse) GetGrantedAtMs() int64 { // CreditRoomTurnoverRewardRequest 是 activity-service 每周房间流水奖励结算后的金币入账命令。 type CreditRoomTurnoverRewardRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *CreditRoomTurnoverRewardRequest) Reset() { @@ -22131,14 +21960,13 @@ func (x *CreditRoomTurnoverRewardRequest) GetReason() string { // CreditRoomTurnoverRewardResponse 返回房间流水奖励入账流水和用户 COIN 账后余额。 type CreditRoomTurnoverRewardResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *CreditRoomTurnoverRewardResponse) Reset() { @@ -22201,21 +22029,20 @@ func (x *CreditRoomTurnoverRewardResponse) GetGrantedAtMs() int64 { // CreditInviteActivityRewardRequest 是 activity-service 邀请活动达标后发起的 COIN 奖励入账命令。 type CreditInviteActivityRewardRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + ClaimId string `protobuf:"bytes,5,opt,name=claim_id,json=claimId,proto3" json:"claim_id,omitempty"` + RewardType string `protobuf:"bytes,6,opt,name=reward_type,json=rewardType,proto3" json:"reward_type,omitempty"` + TierId int64 `protobuf:"varint,7,opt,name=tier_id,json=tierId,proto3" json:"tier_id,omitempty"` + TierCode string `protobuf:"bytes,8,opt,name=tier_code,json=tierCode,proto3" json:"tier_code,omitempty"` + CycleKey string `protobuf:"bytes,9,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` + ReachedValue int64 `protobuf:"varint,10,opt,name=reached_value,json=reachedValue,proto3" json:"reached_value,omitempty"` + Reason string `protobuf:"bytes,11,opt,name=reason,proto3" json:"reason,omitempty"` 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"` - ClaimId string `protobuf:"bytes,5,opt,name=claim_id,json=claimId,proto3" json:"claim_id,omitempty"` - RewardType string `protobuf:"bytes,6,opt,name=reward_type,json=rewardType,proto3" json:"reward_type,omitempty"` - TierId int64 `protobuf:"varint,7,opt,name=tier_id,json=tierId,proto3" json:"tier_id,omitempty"` - TierCode string `protobuf:"bytes,8,opt,name=tier_code,json=tierCode,proto3" json:"tier_code,omitempty"` - CycleKey string `protobuf:"bytes,9,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` - ReachedValue int64 `protobuf:"varint,10,opt,name=reached_value,json=reachedValue,proto3" json:"reached_value,omitempty"` - Reason string `protobuf:"bytes,11,opt,name=reason,proto3" json:"reason,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CreditInviteActivityRewardRequest) Reset() { @@ -22327,14 +22154,13 @@ func (x *CreditInviteActivityRewardRequest) GetReason() string { // CreditInviteActivityRewardResponse 返回邀请活动奖励入账流水和用户 COIN 账后余额。 type CreditInviteActivityRewardResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *CreditInviteActivityRewardResponse) Reset() { @@ -22397,20 +22223,19 @@ func (x *CreditInviteActivityRewardResponse) GetGrantedAtMs() int64 { // CreditAgencyOpeningRewardRequest 是 activity-service 代理开业流水档位结算后的 COIN 入账命令。 type CreditAgencyOpeningRewardRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + ApplicationId string `protobuf:"bytes,5,opt,name=application_id,json=applicationId,proto3" json:"application_id,omitempty"` + CycleId string `protobuf:"bytes,6,opt,name=cycle_id,json=cycleId,proto3" json:"cycle_id,omitempty"` + AgencyId int64 `protobuf:"varint,7,opt,name=agency_id,json=agencyId,proto3" json:"agency_id,omitempty"` + RankNo int32 `protobuf:"varint,8,opt,name=rank_no,json=rankNo,proto3" json:"rank_no,omitempty"` + ScoreCoins int64 `protobuf:"varint,9,opt,name=score_coins,json=scoreCoins,proto3" json:"score_coins,omitempty"` + Reason string `protobuf:"bytes,10,opt,name=reason,proto3" json:"reason,omitempty"` 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"` - ApplicationId string `protobuf:"bytes,5,opt,name=application_id,json=applicationId,proto3" json:"application_id,omitempty"` - CycleId string `protobuf:"bytes,6,opt,name=cycle_id,json=cycleId,proto3" json:"cycle_id,omitempty"` - AgencyId int64 `protobuf:"varint,7,opt,name=agency_id,json=agencyId,proto3" json:"agency_id,omitempty"` - RankNo int32 `protobuf:"varint,8,opt,name=rank_no,json=rankNo,proto3" json:"rank_no,omitempty"` - ScoreCoins int64 `protobuf:"varint,9,opt,name=score_coins,json=scoreCoins,proto3" json:"score_coins,omitempty"` - Reason string `protobuf:"bytes,10,opt,name=reason,proto3" json:"reason,omitempty"` + sizeCache protoimpl.SizeCache } func (x *CreditAgencyOpeningRewardRequest) Reset() { @@ -22515,14 +22340,13 @@ func (x *CreditAgencyOpeningRewardRequest) GetReason() string { // CreditAgencyOpeningRewardResponse 返回代理开业奖励入账流水和用户 COIN 账后余额。 type CreditAgencyOpeningRewardResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *CreditAgencyOpeningRewardResponse) Reset() { @@ -22585,22 +22409,21 @@ func (x *CreditAgencyOpeningRewardResponse) GetGrantedAtMs() int64 { // ApplyGameCoinChangeRequest 是 game-service 唯一可以调用的钱包游戏改账入口。 type ApplyGameCoinChangeRequest struct { - 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"` + 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 } func (x *ApplyGameCoinChangeRequest) Reset() { @@ -22719,13 +22542,12 @@ func (x *ApplyGameCoinChangeRequest) GetRequestHash() string { // ApplyGameCoinChangeResponse 返回游戏改账流水和用户 COIN 账后余额。 type ApplyGameCoinChangeResponse struct { - 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"` + 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 } func (x *ApplyGameCoinChangeResponse) Reset() { @@ -22780,21 +22602,20 @@ func (x *ApplyGameCoinChangeResponse) GetIdempotentReplay() bool { } type RedPacketConfig struct { - 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"` + 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 } func (x *RedPacketConfig) Reset() { @@ -22905,21 +22726,20 @@ func (x *RedPacketConfig) GetRuleUrl() string { } type RedPacketClaim struct { - 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"` + 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 } func (x *RedPacketClaim) Reset() { @@ -23030,32 +22850,31 @@ func (x *RedPacketClaim) GetUpdatedAtMs() int64 { } type RedPacket struct { - 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"` + 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 } func (x *RedPacket) Reset() { @@ -23243,12 +23062,11 @@ func (x *RedPacket) GetRefundedAtMs() int64 { } type GetRedPacketConfigRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetRedPacketConfigRequest) Reset() { @@ -23296,12 +23114,11 @@ func (x *GetRedPacketConfigRequest) GetAppCode() string { } type GetRedPacketConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetRedPacketConfigResponse) Reset() { @@ -23349,20 +23166,19 @@ func (x *GetRedPacketConfigResponse) GetServerTimeMs() int64 { } type UpdateRedPacketConfigRequest struct { - 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"` + 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 } func (x *UpdateRedPacketConfigRequest) Reset() { @@ -23466,12 +23282,11 @@ func (x *UpdateRedPacketConfigRequest) GetRuleUrl() string { } type UpdateRedPacketConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *UpdateRedPacketConfigResponse) Reset() { @@ -23519,19 +23334,18 @@ func (x *UpdateRedPacketConfigResponse) GetServerTimeMs() int64 { } type CreateRedPacketRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *CreateRedPacketRequest) Reset() { @@ -23628,13 +23442,12 @@ func (x *CreateRedPacketRequest) GetPacketCount() int32 { } type CreateRedPacketResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *CreateRedPacketResponse) Reset() { @@ -23689,15 +23502,14 @@ func (x *CreateRedPacketResponse) GetServerTimeMs() int64 { } type ClaimRedPacketRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ClaimRedPacketRequest) Reset() { @@ -23766,14 +23578,13 @@ func (x *ClaimRedPacketRequest) GetUserId() int64 { } type ClaimRedPacketResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ClaimRedPacketResponse) Reset() { @@ -23835,22 +23646,21 @@ func (x *ClaimRedPacketResponse) GetPacket() *RedPacket { } type ListRedPacketsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListRedPacketsRequest) Reset() { @@ -23968,13 +23778,12 @@ func (x *ListRedPacketsRequest) GetPageSize() int32 { } type ListRedPacketsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ListRedPacketsResponse) Reset() { @@ -24029,15 +23838,14 @@ func (x *ListRedPacketsResponse) GetServerTimeMs() int64 { } type GetRedPacketRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetRedPacketRequest) Reset() { @@ -24106,12 +23914,11 @@ func (x *GetRedPacketRequest) GetIncludeClaims() bool { } type GetRedPacketResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetRedPacketResponse) Reset() { @@ -24159,13 +23966,12 @@ func (x *GetRedPacketResponse) GetServerTimeMs() int64 { } type ExpireRedPacketsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *ExpireRedPacketsRequest) Reset() { @@ -24220,13 +24026,12 @@ func (x *ExpireRedPacketsRequest) GetBatchSize() int32 { } type ExpireRedPacketsResponse struct { - 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"` + 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 } func (x *ExpireRedPacketsResponse) Reset() { @@ -24281,14 +24086,13 @@ func (x *ExpireRedPacketsResponse) GetServerTimeMs() int64 { } type RetryRedPacketRefundRequest struct { - 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"` + 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 } func (x *RetryRedPacketRefundRequest) Reset() { @@ -24350,13 +24154,12 @@ func (x *RetryRedPacketRefundRequest) GetOperatorUserId() int64 { } type RetryRedPacketRefundResponse struct { - 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"` + 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 } func (x *RetryRedPacketRefundResponse) Reset() { @@ -24412,16 +24215,13 @@ func (x *RetryRedPacketRefundResponse) GetServerTimeMs() int64 { // CronBatchRequest 是 cron-service 触发 wallet-service 后台批处理的统一请求。 type CronBatchRequest struct { - 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"` + 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"` // trigger_mode 为空时由 wallet-service 按 automatic 处理;后台手动结算显式传 manual。 TriggerMode string `protobuf:"bytes,7,opt,name=trigger_mode,json=triggerMode,proto3" json:"trigger_mode,omitempty"` // cycle_key 为空时由 wallet-service 按当前 UTC 月处理;后台手动补结可指定周期。 @@ -24430,6 +24230,8 @@ type CronBatchRequest struct { UserIds []int64 `protobuf:"varint,9,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` // settlement_role 为空时结算完整 Host/Agency 权益;后台人工入口可传 host 或 agency 拆分钱包。 SettlementRole string `protobuf:"bytes,10,opt,name=settlement_role,json=settlementRole,proto3" json:"settlement_role,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CronBatchRequest) Reset() { @@ -24534,15 +24336,14 @@ func (x *CronBatchRequest) GetSettlementRole() string { // CronBatchResponse 返回一个批处理 run 的执行摘要。 type CronBatchResponse struct { - 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"` + 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 } func (x *CronBatchResponse) Reset() { @@ -24611,25 +24412,24 @@ func (x *CronBatchResponse) GetHasMore() bool { } type ResourceShopPurchaseOrder struct { - 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"` - OrderId string `protobuf:"bytes,2,opt,name=order_id,json=orderId,proto3" json:"order_id,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"` - ShopItemId int64 `protobuf:"varint,5,opt,name=shop_item_id,json=shopItemId,proto3" json:"shop_item_id,omitempty"` - ResourceId int64 `protobuf:"varint,6,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - Resource *Resource `protobuf:"bytes,7,opt,name=resource,proto3" json:"resource,omitempty"` - DurationDays int32 `protobuf:"varint,8,opt,name=duration_days,json=durationDays,proto3" json:"duration_days,omitempty"` - PriceCoin int64 `protobuf:"varint,9,opt,name=price_coin,json=priceCoin,proto3" json:"price_coin,omitempty"` - Status string `protobuf:"bytes,10,opt,name=status,proto3" json:"status,omitempty"` - WalletTransactionId string `protobuf:"bytes,11,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` - ResourceGrantId string `protobuf:"bytes,12,opt,name=resource_grant_id,json=resourceGrantId,proto3" json:"resource_grant_id,omitempty"` - EntitlementId string `protobuf:"bytes,13,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_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"` + state protoimpl.MessageState `protogen:"open.v1"` + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + OrderId string `protobuf:"bytes,2,opt,name=order_id,json=orderId,proto3" json:"order_id,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"` + ShopItemId int64 `protobuf:"varint,5,opt,name=shop_item_id,json=shopItemId,proto3" json:"shop_item_id,omitempty"` + ResourceId int64 `protobuf:"varint,6,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + Resource *Resource `protobuf:"bytes,7,opt,name=resource,proto3" json:"resource,omitempty"` + DurationDays int32 `protobuf:"varint,8,opt,name=duration_days,json=durationDays,proto3" json:"duration_days,omitempty"` + PriceCoin int64 `protobuf:"varint,9,opt,name=price_coin,json=priceCoin,proto3" json:"price_coin,omitempty"` + Status string `protobuf:"bytes,10,opt,name=status,proto3" json:"status,omitempty"` + WalletTransactionId string `protobuf:"bytes,11,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` + ResourceGrantId string `protobuf:"bytes,12,opt,name=resource_grant_id,json=resourceGrantId,proto3" json:"resource_grant_id,omitempty"` + EntitlementId string `protobuf:"bytes,13,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_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 } func (x *ResourceShopPurchaseOrder) Reset() { @@ -24768,18 +24568,17 @@ func (x *ResourceShopPurchaseOrder) GetUpdatedAtMs() int64 { } type ListResourceShopPurchaseOrdersRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,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 - - 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"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,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"` + sizeCache protoimpl.SizeCache } func (x *ListResourceShopPurchaseOrdersRequest) Reset() { @@ -24869,12 +24668,11 @@ func (x *ListResourceShopPurchaseOrdersRequest) GetPageSize() int32 { } type ListResourceShopPurchaseOrdersResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Orders []*ResourceShopPurchaseOrder `protobuf:"bytes,1,rep,name=orders,proto3" json:"orders,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` unknownFields protoimpl.UnknownFields - - Orders []*ResourceShopPurchaseOrder `protobuf:"bytes,1,rep,name=orders,proto3" json:"orders,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListResourceShopPurchaseOrdersResponse) Reset() { @@ -24922,12 +24720,11 @@ func (x *ListResourceShopPurchaseOrdersResponse) GetTotal() int64 { } type GetGiftCatalogVersionRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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 - - 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"` + sizeCache protoimpl.SizeCache } func (x *GetGiftCatalogVersionRequest) Reset() { @@ -24975,11 +24772,10 @@ func (x *GetGiftCatalogVersionRequest) GetAppCode() string { } type GetGiftCatalogVersionResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Version int64 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` unknownFields protoimpl.UnknownFields - - Version int64 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetGiftCatalogVersionResponse) Reset() { @@ -25021,13 +24817,12 @@ func (x *GetGiftCatalogVersionResponse) GetVersion() int64 { // HostRevenueStats 聚合主播在自然日区间内的收益 POINT 和送礼用户;gateway 对外仍按产品文案展示为钻石。 type HostRevenueStats struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - DiamondEarnings int64 `protobuf:"varint,1,opt,name=diamond_earnings,json=diamondEarnings,proto3" json:"diamond_earnings,omitempty"` - DiamondExchanged int64 `protobuf:"varint,2,opt,name=diamond_exchanged,json=diamondExchanged,proto3" json:"diamond_exchanged,omitempty"` - GiftSenders int64 `protobuf:"varint,3,opt,name=gift_senders,json=giftSenders,proto3" json:"gift_senders,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + DiamondEarnings int64 `protobuf:"varint,1,opt,name=diamond_earnings,json=diamondEarnings,proto3" json:"diamond_earnings,omitempty"` + DiamondExchanged int64 `protobuf:"varint,2,opt,name=diamond_exchanged,json=diamondExchanged,proto3" json:"diamond_exchanged,omitempty"` + GiftSenders int64 `protobuf:"varint,3,opt,name=gift_senders,json=giftSenders,proto3" json:"gift_senders,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *HostRevenueStats) Reset() { @@ -25082,15 +24877,14 @@ func (x *HostRevenueStats) GetGiftSenders() int64 { } type GetHostRevenueStatsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + 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"` 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"` - 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"` + sizeCache protoimpl.SizeCache } func (x *GetHostRevenueStatsRequest) Reset() { @@ -25159,11 +24953,10 @@ func (x *GetHostRevenueStatsRequest) GetEndAtMs() int64 { } type GetHostRevenueStatsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Stats *HostRevenueStats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"` unknownFields protoimpl.UnknownFields - - Stats *HostRevenueStats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetHostRevenueStatsResponse) Reset() { @@ -25205,12 +24998,11 @@ func (x *GetHostRevenueStatsResponse) GetStats() *HostRevenueStats { // AgencyPointShareStats 只统计独立 Agency 分成流水,不把 owner 自己的主播礼物收益重复算入分成。 type AgencyPointShareStats struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ShareIncome int64 `protobuf:"varint,1,opt,name=share_income,json=shareIncome,proto3" json:"share_income,omitempty"` - GiftedHostCount int64 `protobuf:"varint,2,opt,name=gifted_host_count,json=giftedHostCount,proto3" json:"gifted_host_count,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + ShareIncome int64 `protobuf:"varint,1,opt,name=share_income,json=shareIncome,proto3" json:"share_income,omitempty"` + GiftedHostCount int64 `protobuf:"varint,2,opt,name=gifted_host_count,json=giftedHostCount,proto3" json:"gifted_host_count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AgencyPointShareStats) Reset() { @@ -25258,15 +25050,14 @@ func (x *AgencyPointShareStats) GetGiftedHostCount() int64 { } type GetAgencyPointShareStatsRequest struct { - 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"` - AgencyOwnerUserId int64 `protobuf:"varint,3,opt,name=agency_owner_user_id,json=agencyOwnerUserId,proto3" json:"agency_owner_user_id,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"` + 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"` + AgencyOwnerUserId int64 `protobuf:"varint,3,opt,name=agency_owner_user_id,json=agencyOwnerUserId,proto3" json:"agency_owner_user_id,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"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GetAgencyPointShareStatsRequest) Reset() { @@ -25335,11 +25126,10 @@ func (x *GetAgencyPointShareStatsRequest) GetEndAtMs() int64 { } type GetAgencyPointShareStatsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Stats *AgencyPointShareStats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"` unknownFields protoimpl.UnknownFields - - Stats *AgencyPointShareStats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetAgencyPointShareStatsResponse) Reset() { @@ -25380,12 +25170,11 @@ func (x *GetAgencyPointShareStatsResponse) GetStats() *AgencyPointShareStats { } type AgencyHostGiftStats struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - GiftIncome int64 `protobuf:"varint,1,opt,name=gift_income,json=giftIncome,proto3" json:"gift_income,omitempty"` - GiftedHostCount int64 `protobuf:"varint,2,opt,name=gifted_host_count,json=giftedHostCount,proto3" json:"gifted_host_count,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + GiftIncome int64 `protobuf:"varint,1,opt,name=gift_income,json=giftIncome,proto3" json:"gift_income,omitempty"` + GiftedHostCount int64 `protobuf:"varint,2,opt,name=gifted_host_count,json=giftedHostCount,proto3" json:"gifted_host_count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AgencyHostGiftStats) Reset() { @@ -25433,15 +25222,14 @@ func (x *AgencyHostGiftStats) GetGiftedHostCount() int64 { } type GetAgencyHostGiftStatsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + HostUserIds []int64 `protobuf:"varint,3,rep,packed,name=host_user_ids,json=hostUserIds,proto3" json:"host_user_ids,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"` 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"` - HostUserIds []int64 `protobuf:"varint,3,rep,packed,name=host_user_ids,json=hostUserIds,proto3" json:"host_user_ids,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"` + sizeCache protoimpl.SizeCache } func (x *GetAgencyHostGiftStatsRequest) Reset() { @@ -25510,11 +25298,10 @@ func (x *GetAgencyHostGiftStatsRequest) GetEndAtMs() int64 { } type GetAgencyHostGiftStatsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Stats *AgencyHostGiftStats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"` unknownFields protoimpl.UnknownFields - - Stats *AgencyHostGiftStats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetAgencyHostGiftStatsResponse) Reset() { @@ -25557,19 +25344,18 @@ func (x *GetAgencyHostGiftStatsResponse) GetStats() *AgencyHostGiftStats { // PointWithdrawalCoinSellerConfig 是按 App 隔离的 POINT 提现币商白名单与兑换比例。 // 比例用整数分子/分母保存,避免浮点金额在 H5、gateway 和账本间产生舍入分歧。 type PointWithdrawalCoinSellerConfig struct { - 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"` - SellerUserId int64 `protobuf:"varint,2,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` - SortOrder int32 `protobuf:"varint,3,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - PointAmount int64 `protobuf:"varint,4,opt,name=point_amount,json=pointAmount,proto3" json:"point_amount,omitempty"` - SellerCoinAmount int64 `protobuf:"varint,5,opt,name=seller_coin_amount,json=sellerCoinAmount,proto3" json:"seller_coin_amount,omitempty"` - ServiceCountryCodes []string `protobuf:"bytes,6,rep,name=service_country_codes,json=serviceCountryCodes,proto3" json:"service_country_codes,omitempty"` - Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,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"` + state protoimpl.MessageState `protogen:"open.v1"` + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + SellerUserId int64 `protobuf:"varint,2,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` + SortOrder int32 `protobuf:"varint,3,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + PointAmount int64 `protobuf:"varint,4,opt,name=point_amount,json=pointAmount,proto3" json:"point_amount,omitempty"` + SellerCoinAmount int64 `protobuf:"varint,5,opt,name=seller_coin_amount,json=sellerCoinAmount,proto3" json:"seller_coin_amount,omitempty"` + ServiceCountryCodes []string `protobuf:"bytes,6,rep,name=service_country_codes,json=serviceCountryCodes,proto3" json:"service_country_codes,omitempty"` + Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,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 *PointWithdrawalCoinSellerConfig) Reset() { @@ -25666,15 +25452,14 @@ func (x *PointWithdrawalCoinSellerConfig) GetUpdatedAtMs() int64 { } type ListPointWithdrawalCoinSellersRequest struct { - 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"` + 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"` // country_code 由 gateway 从登录用户资料注入;为空只用于 Admin/内部查询。 CountryCode string `protobuf:"bytes,3,opt,name=country_code,json=countryCode,proto3" json:"country_code,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 *ListPointWithdrawalCoinSellersRequest) Reset() { @@ -25736,11 +25521,10 @@ func (x *ListPointWithdrawalCoinSellersRequest) GetIncludeDisabled() bool { } type ListPointWithdrawalCoinSellersResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Sellers []*PointWithdrawalCoinSellerConfig `protobuf:"bytes,1,rep,name=sellers,proto3" json:"sellers,omitempty"` unknownFields protoimpl.UnknownFields - - Sellers []*PointWithdrawalCoinSellerConfig `protobuf:"bytes,1,rep,name=sellers,proto3" json:"sellers,omitempty"` + sizeCache protoimpl.SizeCache } func (x *ListPointWithdrawalCoinSellersResponse) Reset() { @@ -25781,18 +25565,17 @@ func (x *ListPointWithdrawalCoinSellersResponse) GetSellers() []*PointWithdrawal } type TransferPointToCoinSellerRequest struct { - 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"` - SourceUserId int64 `protobuf:"varint,3,opt,name=source_user_id,json=sourceUserId,proto3" json:"source_user_id,omitempty"` - SellerUserId int64 `protobuf:"varint,4,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` - PointAmount int64 `protobuf:"varint,5,opt,name=point_amount,json=pointAmount,proto3" json:"point_amount,omitempty"` + 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"` + SourceUserId int64 `protobuf:"varint,3,opt,name=source_user_id,json=sourceUserId,proto3" json:"source_user_id,omitempty"` + SellerUserId int64 `protobuf:"varint,4,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` + PointAmount int64 `protobuf:"varint,5,opt,name=point_amount,json=pointAmount,proto3" json:"point_amount,omitempty"` // source_country_code 由 gateway 从用户资料读取,wallet 会再次校验币商服务国家。 SourceCountryCode string `protobuf:"bytes,6,opt,name=source_country_code,json=sourceCountryCode,proto3" json:"source_country_code,omitempty"` Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *TransferPointToCoinSellerRequest) Reset() { @@ -25875,17 +25658,16 @@ func (x *TransferPointToCoinSellerRequest) GetReason() string { } type TransferPointToCoinSellerResponse struct { - 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"` - SourcePointBalanceAfter int64 `protobuf:"varint,2,opt,name=source_point_balance_after,json=sourcePointBalanceAfter,proto3" json:"source_point_balance_after,omitempty"` - SellerBalanceAfter int64 `protobuf:"varint,3,opt,name=seller_balance_after,json=sellerBalanceAfter,proto3" json:"seller_balance_after,omitempty"` - PointAmount int64 `protobuf:"varint,4,opt,name=point_amount,json=pointAmount,proto3" json:"point_amount,omitempty"` - SellerCoinAmount int64 `protobuf:"varint,5,opt,name=seller_coin_amount,json=sellerCoinAmount,proto3" json:"seller_coin_amount,omitempty"` - RatioPointAmount int64 `protobuf:"varint,6,opt,name=ratio_point_amount,json=ratioPointAmount,proto3" json:"ratio_point_amount,omitempty"` - RatioSellerCoinAmount int64 `protobuf:"varint,7,opt,name=ratio_seller_coin_amount,json=ratioSellerCoinAmount,proto3" json:"ratio_seller_coin_amount,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + SourcePointBalanceAfter int64 `protobuf:"varint,2,opt,name=source_point_balance_after,json=sourcePointBalanceAfter,proto3" json:"source_point_balance_after,omitempty"` + SellerBalanceAfter int64 `protobuf:"varint,3,opt,name=seller_balance_after,json=sellerBalanceAfter,proto3" json:"seller_balance_after,omitempty"` + PointAmount int64 `protobuf:"varint,4,opt,name=point_amount,json=pointAmount,proto3" json:"point_amount,omitempty"` + SellerCoinAmount int64 `protobuf:"varint,5,opt,name=seller_coin_amount,json=sellerCoinAmount,proto3" json:"seller_coin_amount,omitempty"` + RatioPointAmount int64 `protobuf:"varint,6,opt,name=ratio_point_amount,json=ratioPointAmount,proto3" json:"ratio_point_amount,omitempty"` + RatioSellerCoinAmount int64 `protobuf:"varint,7,opt,name=ratio_seller_coin_amount,json=ratioSellerCoinAmount,proto3" json:"ratio_seller_coin_amount,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *TransferPointToCoinSellerResponse) Reset() { @@ -25968,14 +25750,13 @@ func (x *TransferPointToCoinSellerResponse) GetRatioSellerCoinAmount() int64 { } type GetPointWithdrawalConfigRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + 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"` + NowMs int64 `protobuf:"varint,4,opt,name=now_ms,json=nowMs,proto3" json:"now_ms,omitempty"` 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"` - NowMs int64 `protobuf:"varint,4,opt,name=now_ms,json=nowMs,proto3" json:"now_ms,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetPointWithdrawalConfigRequest) Reset() { @@ -26037,15 +25818,14 @@ func (x *GetPointWithdrawalConfigRequest) GetNowMs() int64 { } type GetPointWithdrawalConfigResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Found bool `protobuf:"varint,1,opt,name=found,proto3" json:"found,omitempty"` - PointsPerUsd int64 `protobuf:"varint,2,opt,name=points_per_usd,json=pointsPerUsd,proto3" json:"points_per_usd,omitempty"` - FeeBps int32 `protobuf:"varint,3,opt,name=fee_bps,json=feeBps,proto3" json:"fee_bps,omitempty"` - MinimumPoints int64 `protobuf:"varint,4,opt,name=minimum_points,json=minimumPoints,proto3" json:"minimum_points,omitempty"` - PolicyInstanceCode string `protobuf:"bytes,5,opt,name=policy_instance_code,json=policyInstanceCode,proto3" json:"policy_instance_code,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Found bool `protobuf:"varint,1,opt,name=found,proto3" json:"found,omitempty"` + PointsPerUsd int64 `protobuf:"varint,2,opt,name=points_per_usd,json=pointsPerUsd,proto3" json:"points_per_usd,omitempty"` + FeeBps int32 `protobuf:"varint,3,opt,name=fee_bps,json=feeBps,proto3" json:"fee_bps,omitempty"` + MinimumPoints int64 `protobuf:"varint,4,opt,name=minimum_points,json=minimumPoints,proto3" json:"minimum_points,omitempty"` + PolicyInstanceCode string `protobuf:"bytes,5,opt,name=policy_instance_code,json=policyInstanceCode,proto3" json:"policy_instance_code,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GetPointWithdrawalConfigResponse) Reset() { @@ -26113,5834 +25893,3157 @@ func (x *GetPointWithdrawalConfigResponse) GetPolicyInstanceCode() string { return "" } +// VipBenefitPreviewItem 是同一权益下的一项预览内容;独立稳定键允许 Flutter 在多图、动态资源间切换, +// 且不会把数组下标误当成资源身份。 +type VipBenefitPreviewItem struct { + state protoimpl.MessageState `protogen:"open.v1"` + PreviewId string `protobuf:"bytes,1,opt,name=preview_id,json=previewId,proto3" json:"preview_id,omitempty"` + Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` + // media_type: image/animation;animation 使用 animation_url,静态兜底使用 preview_url/asset_url。 + MediaType string `protobuf:"bytes,3,opt,name=media_type,json=mediaType,proto3" json:"media_type,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"` + // composition_type: none/user_avatar_center/user_avatar_waveform,客户端据此把当前用户头像合成到预览中。 + CompositionType string `protobuf:"bytes,7,opt,name=composition_type,json=compositionType,proto3" json:"composition_type,omitempty"` + SortOrder int32 `protobuf:"varint,8,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VipBenefitPreviewItem) Reset() { + *x = VipBenefitPreviewItem{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[295] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VipBenefitPreviewItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VipBenefitPreviewItem) ProtoMessage() {} + +func (x *VipBenefitPreviewItem) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[295] + 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 VipBenefitPreviewItem.ProtoReflect.Descriptor instead. +func (*VipBenefitPreviewItem) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{295} +} + +func (x *VipBenefitPreviewItem) GetPreviewId() string { + if x != nil { + return x.PreviewId + } + return "" +} + +func (x *VipBenefitPreviewItem) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *VipBenefitPreviewItem) GetMediaType() string { + if x != nil { + return x.MediaType + } + return "" +} + +func (x *VipBenefitPreviewItem) GetAssetUrl() string { + if x != nil { + return x.AssetUrl + } + return "" +} + +func (x *VipBenefitPreviewItem) GetPreviewUrl() string { + if x != nil { + return x.PreviewUrl + } + return "" +} + +func (x *VipBenefitPreviewItem) GetAnimationUrl() string { + if x != nil { + return x.AnimationUrl + } + return "" +} + +func (x *VipBenefitPreviewItem) GetCompositionType() string { + if x != nil { + return x.CompositionType + } + return "" +} + +func (x *VipBenefitPreviewItem) GetSortOrder() int32 { + if x != nil { + return x.SortOrder + } + return 0 +} + +type VipBenefitNumericReward struct { + state protoimpl.MessageState `protogen:"open.v1"` + Label string `protobuf:"bytes,1,opt,name=label,proto3" json:"label,omitempty"` + Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` + Unit string `protobuf:"bytes,3,opt,name=unit,proto3" json:"unit,omitempty"` + // period: once/daily/monthly,由服务端配置返回,客户端只展示不据此结算。 + Period string `protobuf:"bytes,4,opt,name=period,proto3" json:"period,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VipBenefitNumericReward) Reset() { + *x = VipBenefitNumericReward{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[296] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VipBenefitNumericReward) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VipBenefitNumericReward) ProtoMessage() {} + +func (x *VipBenefitNumericReward) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[296] + 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 VipBenefitNumericReward.ProtoReflect.Descriptor instead. +func (*VipBenefitNumericReward) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{296} +} + +func (x *VipBenefitNumericReward) GetLabel() string { + if x != nil { + return x.Label + } + return "" +} + +func (x *VipBenefitNumericReward) GetValue() int64 { + if x != nil { + return x.Value + } + return 0 +} + +func (x *VipBenefitNumericReward) GetUnit() string { + if x != nil { + return x.Unit + } + return "" +} + +func (x *VipBenefitNumericReward) GetPeriod() string { + if x != nil { + return x.Period + } + return "" +} + +// VipBenefitPresentation 是 Flutter 可直接渲染的结构化特权说明。metadata_json 继续保留后台扩展和 +// 历史兼容,但客户端不得按 benefit_code 自行解析 metadata_json 生成预览。 +type VipBenefitPresentation struct { + state protoimpl.MessageState `protogen:"open.v1"` + Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` + PreviewItems []*VipBenefitPreviewItem `protobuf:"bytes,2,rep,name=preview_items,json=previewItems,proto3" json:"preview_items,omitempty"` + NumericReward *VipBenefitNumericReward `protobuf:"bytes,3,opt,name=numeric_reward,json=numericReward,proto3" json:"numeric_reward,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VipBenefitPresentation) Reset() { + *x = VipBenefitPresentation{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[297] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VipBenefitPresentation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VipBenefitPresentation) ProtoMessage() {} + +func (x *VipBenefitPresentation) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[297] + 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 VipBenefitPresentation.ProtoReflect.Descriptor instead. +func (*VipBenefitPresentation) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{297} +} + +func (x *VipBenefitPresentation) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *VipBenefitPresentation) GetPreviewItems() []*VipBenefitPreviewItem { + if x != nil { + return x.PreviewItems + } + return nil +} + +func (x *VipBenefitPresentation) GetNumericReward() *VipBenefitNumericReward { + if x != nil { + return x.NumericReward + } + return nil +} + +// RevokeUserResourceRequest targets one entitlement instead of its source grant. This keeps +// resource-group siblings intact when an operator removes a single badge/frame from a user. +type RevokeUserResourceRequest 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"` + EntitlementId string `protobuf:"bytes,4,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_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"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RevokeUserResourceRequest) Reset() { + *x = RevokeUserResourceRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[298] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RevokeUserResourceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RevokeUserResourceRequest) ProtoMessage() {} + +func (x *RevokeUserResourceRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[298] + 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 RevokeUserResourceRequest.ProtoReflect.Descriptor instead. +func (*RevokeUserResourceRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{298} +} + +func (x *RevokeUserResourceRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *RevokeUserResourceRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *RevokeUserResourceRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *RevokeUserResourceRequest) GetEntitlementId() string { + if x != nil { + return x.EntitlementId + } + return "" +} + +func (x *RevokeUserResourceRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *RevokeUserResourceRequest) GetOperatorUserId() int64 { + if x != nil { + return x.OperatorUserId + } + return 0 +} + +type RevokeUserResourceResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Resource *UserResourceEntitlement `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RevokeUserResourceResponse) Reset() { + *x = RevokeUserResourceResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[299] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RevokeUserResourceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RevokeUserResourceResponse) ProtoMessage() {} + +func (x *RevokeUserResourceResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[299] + 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 RevokeUserResourceResponse.ProtoReflect.Descriptor instead. +func (*RevokeUserResourceResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{299} +} + +func (x *RevokeUserResourceResponse) GetResource() *UserResourceEntitlement { + if x != nil { + return x.Resource + } + return nil +} + var File_proto_wallet_v1_wallet_proto protoreflect.FileDescriptor -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, - 0xb8, 0x04, 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, 0x12, 0x25, - 0x0a, 0x0e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, - 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xa5, 0x04, 0x0a, 0x16, 0x44, - 0x65, 0x62, 0x69, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 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, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 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, 0x03, 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, 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, - 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, 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, - 0x0d, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x0e, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x22, 0xc2, 0x0b, 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, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x70, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, - 0x63, 0x70, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, - 0x0a, 0x09, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x67, 0x69, 0x66, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x67, - 0x69, 0x66, 0x74, 0x5f, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0f, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x67, 0x69, 0x66, 0x74, 0x49, 0x63, 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x12, - 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x67, 0x69, 0x66, - 0x74, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x2a, 0x0a, - 0x11, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x67, 0x69, 0x66, 0x74, 0x45, 0x66, - 0x66, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, - 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x35, 0x0a, 0x17, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x6e, - 0x63, 0x6f, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x67, 0x69, 0x66, 0x74, 0x49, 0x6e, 0x63, 0x6f, - 0x6d, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x19, - 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x5f, 0x62, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x16, 0x67, 0x69, 0x66, 0x74, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x68, 0x6f, 0x73, 0x74, 0x5f, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x16, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0e, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x65, - 0x64, 0x12, 0x37, 0x0a, 0x18, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, - 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x17, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x15, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x15, 0x68, 0x6f, - 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x68, 0x6f, 0x73, 0x74, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x44, 0x0a, - 0x1f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, - 0x18, 0x19, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, - 0x6f, 0x64, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, - 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x3d, 0x0a, 0x1b, - 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x74, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x1b, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x18, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x54, 0x65, 0x6d, 0x70, - 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x62, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x1c, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x18, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, - 0x5f, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x5f, 0x64, 0x61, 0x79, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, - 0x18, 0x1d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, - 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x39, 0x0a, - 0x19, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, - 0x5f, 0x64, 0x61, 0x79, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x16, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x54, 0x68, 0x69, 0x72, 0x74, 0x79, - 0x44, 0x61, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x2f, 0x0a, 0x14, 0x6c, 0x61, 0x73, 0x74, - 0x5f, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, - 0x18, 0x1f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1c, 0x0a, 0x0a, 0x70, 0x61, 0x69, - 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x20, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x70, - 0x61, 0x69, 0x64, 0x41, 0x74, 0x4d, 0x73, 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, 0xbc, 0x03, 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, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, - 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 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, 0xda, 0x02, 0x0a, 0x15, 0x44, 0x65, 0x62, 0x69, 0x74, 0x52, 0x6f, - 0x62, 0x6f, 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, 0x28, 0x0a, 0x10, 0x73, 0x65, 0x6e, 0x64, 0x65, - 0x72, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 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, 0x91, 0x02, 0x0a, 0x17, 0x54, 0x65, 0x61, 0x6d, 0x48, - 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x12, - 0x44, 0x0a, 0x1f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x6f, 0x73, - 0x74, 0x5f, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, - 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, - 0x74, 0x65, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x55, 0x73, 0x64, - 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x40, 0x0a, 0x1d, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x64, - 0x5f, 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, 0x19, 0x73, 0x65, - 0x74, 0x74, 0x6c, 0x65, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x55, - 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x11, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 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, 0x22, 0xc2, 0x01, 0x0a, 0x1d, 0x47, - 0x65, 0x74, 0x54, 0x65, 0x61, 0x6d, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, - 0x53, 0x74, 0x61, 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, 0x31, 0x0a, 0x15, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, - 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x12, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x77, 0x6e, - 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x79, 0x63, - 0x6c, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x63, - 0x79, 0x63, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x77, 0x5f, - 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6e, 0x6f, 0x77, 0x4d, 0x73, 0x22, - 0x86, 0x01, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x54, 0x65, 0x61, 0x6d, 0x48, 0x6f, 0x73, 0x74, 0x53, - 0x61, 0x6c, 0x61, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 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, 0x54, 0x65, 0x61, 0x6d, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, - 0x72, 0x79, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x52, 0x05, 0x73, 0x74, 0x61, - 0x74, 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, 0xad, 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, - 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x72, 0x65, 0x6d, 0x61, 0x72, 0x6b, 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, 0xf8, 0x01, 0x0a, 0x25, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x43, 0x6f, - 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x54, 0x6f, 0x43, - 0x68, 0x69, 0x6c, 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, 0x24, 0x0a, 0x0e, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, - 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 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, - 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xed, 0x01, 0x0a, - 0x26, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, - 0x6c, 0x65, 0x72, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x54, 0x6f, 0x43, 0x68, 0x69, 0x6c, 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, 0x30, - 0x0a, 0x14, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, - 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x63, - 0x68, 0x69, 0x6c, 0x64, 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, 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, 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, 0x87, 0x02, 0x0a, 0x1d, 0x46, 0x72, 0x65, 0x65, 0x7a, 0x65, 0x53, 0x61, - 0x6c, 0x61, 0x72, 0x79, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 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, 0x12, 0x25, 0x0a, 0x0e, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x52, 0x65, 0x66, 0x22, 0xaa, 0x01, - 0x0a, 0x1e, 0x46, 0x72, 0x65, 0x65, 0x7a, 0x65, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x57, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 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, 0x28, 0x0a, 0x10, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, - 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x73, 0x61, 0x6c, 0x61, - 0x72, 0x79, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x22, 0xc6, 0x02, 0x0a, 0x1d, 0x53, - 0x65, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x57, 0x69, 0x74, 0x68, 0x64, - 0x72, 0x61, 0x77, 0x61, 0x6c, 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, 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, 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, 0x3a, 0x0a, 0x19, 0x77, 0x69, 0x74, 0x68, 0x64, - 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x77, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x22, 0xaa, 0x01, 0x0a, 0x1e, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x61, - 0x6c, 0x61, 0x72, 0x79, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 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, 0x28, 0x0a, 0x10, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, - 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0e, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, - 0x22, 0xc7, 0x02, 0x0a, 0x1e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x61, 0x6c, 0x61, - 0x72, 0x79, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 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, 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, 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, 0x3a, - 0x0a, 0x19, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x61, 0x70, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x17, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x41, 0x70, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xab, 0x01, 0x0a, 0x1f, 0x52, - 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x57, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 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, 0x28, - 0x0a, 0x10, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, - 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, - 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x22, 0x90, 0x03, 0x0a, 0x1c, 0x46, 0x72, 0x65, - 0x65, 0x7a, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, - 0x61, 0x6c, 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, 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, 0x2c, 0x0a, 0x12, 0x67, 0x72, 0x6f, 0x73, 0x73, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, - 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x67, 0x72, - 0x6f, 0x73, 0x73, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, - 0x0a, 0x10, 0x66, 0x65, 0x65, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x66, 0x65, 0x65, 0x50, 0x6f, 0x69, - 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6e, 0x65, 0x74, 0x5f, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0e, 0x6e, 0x65, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, - 0x5f, 0x75, 0x73, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x73, 0x50, 0x65, 0x72, 0x55, 0x73, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x65, 0x65, 0x5f, - 0x62, 0x70, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x66, 0x65, 0x65, 0x42, 0x70, - 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, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, - 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, - 0x43, 0x6f, 0x64, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, - 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x52, 0x65, 0x66, 0x22, 0xc0, 0x02, 0x0a, 0x1d, - 0x46, 0x72, 0x65, 0x65, 0x7a, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, - 0x72, 0x61, 0x77, 0x61, 0x6c, 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, 0x2c, 0x0a, - 0x12, 0x67, 0x72, 0x6f, 0x73, 0x73, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x67, 0x72, 0x6f, 0x73, 0x73, - 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x66, - 0x65, 0x65, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x66, 0x65, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6e, 0x65, 0x74, 0x5f, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0e, 0x6e, 0x65, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x24, 0x0a, 0x0e, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x75, 0x73, - 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x50, - 0x65, 0x72, 0x55, 0x73, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x65, 0x65, 0x5f, 0x62, 0x70, 0x73, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x66, 0x65, 0x65, 0x42, 0x70, 0x73, 0x22, 0xcf, - 0x03, 0x0a, 0x1c, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 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, 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, 0x2c, 0x0a, 0x12, 0x67, 0x72, 0x6f, 0x73, 0x73, 0x5f, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x10, 0x67, 0x72, 0x6f, 0x73, 0x73, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x65, 0x65, 0x5f, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, - 0x66, 0x65, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, - 0x0a, 0x10, 0x6e, 0x65, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6e, 0x65, 0x74, 0x50, 0x6f, 0x69, - 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0c, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x50, 0x65, 0x72, 0x55, 0x73, 0x64, 0x12, 0x17, - 0x0a, 0x07, 0x66, 0x65, 0x65, 0x5f, 0x62, 0x70, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x06, 0x66, 0x65, 0x65, 0x42, 0x70, 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, 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, 0x3a, 0x0a, 0x19, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, - 0x61, 0x6c, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, - 0x77, 0x61, 0x6c, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x22, 0xc0, 0x02, 0x0a, 0x1d, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 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, 0x2c, 0x0a, 0x12, 0x67, 0x72, 0x6f, 0x73, 0x73, 0x5f, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, - 0x67, 0x72, 0x6f, 0x73, 0x73, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x28, 0x0a, 0x10, 0x66, 0x65, 0x65, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x66, 0x65, 0x65, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6e, 0x65, - 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6e, 0x65, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x5f, 0x70, - 0x65, 0x72, 0x5f, 0x75, 0x73, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x73, 0x50, 0x65, 0x72, 0x55, 0x73, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x65, - 0x65, 0x5f, 0x62, 0x70, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x66, 0x65, 0x65, - 0x42, 0x70, 0x73, 0x22, 0xd0, 0x03, 0x0a, 0x1d, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 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, 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, 0x2c, 0x0a, 0x12, - 0x67, 0x72, 0x6f, 0x73, 0x73, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x67, 0x72, 0x6f, 0x73, 0x73, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x65, - 0x65, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x66, 0x65, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6e, 0x65, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, - 0x6e, 0x65, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, - 0x0a, 0x0e, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x64, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x50, 0x65, - 0x72, 0x55, 0x73, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x65, 0x65, 0x5f, 0x62, 0x70, 0x73, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x66, 0x65, 0x65, 0x42, 0x70, 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, 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, 0x3a, 0x0a, 0x19, 0x77, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x77, - 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xc1, 0x02, 0x0a, 0x1e, 0x52, 0x65, 0x6c, 0x65, 0x61, - 0x73, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, - 0x6c, 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, 0x2c, 0x0a, 0x12, 0x67, 0x72, 0x6f, - 0x73, 0x73, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x67, 0x72, 0x6f, 0x73, 0x73, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x65, 0x65, 0x5f, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0e, 0x66, 0x65, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6e, 0x65, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6e, 0x65, 0x74, - 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x64, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0c, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x50, 0x65, 0x72, 0x55, 0x73, - 0x64, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x65, 0x65, 0x5f, 0x62, 0x70, 0x73, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x06, 0x66, 0x65, 0x65, 0x42, 0x70, 0x73, 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, 0xcb, - 0x03, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 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, 0x1f, 0x0a, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, - 0x6f, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x69, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x26, 0x0a, - 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x5f, 0x6e, 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x4e, 0x6f, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, - 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x34, 0x0a, 0x05, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x18, 0x07, 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, 0x12, - 0x2b, 0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x08, 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, 0x09, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, - 0x12, 0x3a, 0x0a, 0x1a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x2e, 0x0a, 0x13, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x68, - 0x61, 0x73, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x22, 0x9c, 0x03, 0x0a, - 0x1f, 0x50, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 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, 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, 0x17, 0x0a, 0x07, 0x70, 0x69, 0x6e, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x69, 0x6e, 0x4b, 0x65, 0x79, 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, 0x3e, 0x0a, 0x1c, 0x65, 0x78, 0x70, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, - 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x3f, 0x0a, 0x1c, 0x65, 0x78, 0x70, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, - 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, - 0x18, 0x08, 0x20, 0x03, 0x28, 0x03, 0x52, 0x11, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, - 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, - 0x64, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x66, 0x0a, 0x20, 0x50, - 0x69, 0x6e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x53, - 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x42, 0x0a, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 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, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x08, 0x73, 0x6e, 0x61, 0x70, 0x73, - 0x68, 0x6f, 0x74, 0x22, 0xd3, 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, 0x12, - 0x28, 0x0a, 0x10, 0x63, 0x70, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x70, 0x52, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 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, 0xb8, 0x05, 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, 0x12, 0x2c, - 0x0a, 0x12, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, - 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x16, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, - 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x48, 0x61, - 0x73, 0x68, 0x12, 0x4b, 0x0a, 0x13, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x67, 0x69, 0x66, - 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x11, 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, 0x11, 0x70, 0x69, - 0x6e, 0x6e, 0x65, 0x64, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 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, 0xd7, 0x04, 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, 0x12, 0x22, 0x0a, 0x0d, - 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0e, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, - 0x12, 0x2b, 0x0a, 0x12, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, 0x65, - 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x23, 0x0a, - 0x0d, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x10, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 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, 0x9c, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, - 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, 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, 0xa4, 0x01, 0x0a, 0x1b, 0x42, 0x61, 0x74, 0x63, 0x68, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 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, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x49, 0x64, 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, 0x57, 0x0a, - 0x1c, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 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, 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, 0x80, 0x01, 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, 0x12, 0x2e, 0x0a, 0x13, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x68, - 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 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, 0xf8, - 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, 0x12, - 0x28, 0x0a, 0x10, 0x63, 0x70, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x70, 0x52, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, 0xc3, 0x01, 0x0a, 0x1d, 0x42, 0x61, - 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 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, 0x3e, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 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, 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, - 0x53, 0x0a, 0x1e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 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, 0x22, 0xf8, 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, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x70, 0x5f, 0x72, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x63, 0x70, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 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, 0x96, 0x01, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 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, 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, 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, 0xbd, 0x02, - 0x0a, 0x1f, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x50, 0x69, 0x6e, 0x6e, 0x65, 0x64, 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, 0x1f, 0x0a, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x69, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, - 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, 0x12, 0x34, 0x0a, 0x16, 0x65, 0x78, 0x70, 0x65, 0x63, - 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x68, 0x61, 0x73, - 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x48, 0x61, 0x73, 0x68, 0x22, 0xb3, 0x01, - 0x0a, 0x1a, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x47, 0x72, 0x61, 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, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x61, 0x6e, 0x74, 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, 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, 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, 0xa1, 0x08, 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, 0x12, 0x32, 0x0a, - 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x69, 0x6e, 0x6f, - 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, - 0x64, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x35, 0x0a, 0x17, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x70, - 0x61, 0x69, 0x64, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x63, 0x6f, 0x64, - 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x75, 0x73, 0x65, 0x72, 0x50, 0x61, 0x69, - 0x64, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x33, 0x0a, - 0x16, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x69, 0x64, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x18, 0x16, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x75, - 0x73, 0x65, 0x72, 0x50, 0x61, 0x69, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x69, 0x63, - 0x72, 0x6f, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x66, - 0x65, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x18, 0x17, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x46, 0x65, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, - 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x78, - 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x18, 0x18, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, 0x61, 0x78, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x12, 0x2c, - 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x6e, 0x65, 0x74, 0x5f, 0x6d, - 0x69, 0x63, 0x72, 0x6f, 0x18, 0x19, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x12, 0x29, 0x0a, 0x11, - 0x70, 0x61, 0x69, 0x64, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, - 0x73, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x61, 0x69, 0x64, 0x53, 0x79, 0x6e, - 0x63, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0x93, 0x03, 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, 0x12, 0x1d, - 0x0a, 0x0a, 0x70, 0x61, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x0d, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x69, 0x64, 0x53, 0x74, 0x61, 0x74, 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, 0xc8, 0x02, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, - 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 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, 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, - 0x22, 0x85, 0x01, 0x0a, 0x19, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, - 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x1d, - 0x0a, 0x0a, 0x62, 0x69, 0x6c, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x09, 0x62, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, - 0x0b, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 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, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x75, 0x73, 0x64, 0x4d, 0x69, 0x6e, - 0x6f, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc9, 0x02, 0x0a, 0x1e, 0x47, 0x65, 0x74, - 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x53, 0x75, 0x6d, 0x6d, - 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x05, 0x74, - 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 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, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, - 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x4b, 0x0a, - 0x0b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2a, 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, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0a, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x50, 0x6c, 0x61, 0x79, 0x12, 0x4b, 0x0a, 0x0b, 0x74, 0x68, - 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2a, 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, 0x53, 0x75, - 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0a, 0x74, 0x68, 0x69, - 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x6f, 0x69, 0x6e, 0x5f, - 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 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, 0x53, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x79, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x65, - 0x6c, 0x6c, 0x65, 0x72, 0x22, 0x8b, 0x02, 0x0a, 0x11, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x63, - 0x68, 0x61, 0x72, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 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, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x72, 0x65, 0x63, - 0x68, 0x61, 0x72, 0x67, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x69, 0x6e, - 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x33, 0x0a, 0x16, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, - 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x55, 0x73, 0x64, - 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x31, 0x0a, 0x15, 0x66, - 0x69, 0x72, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x64, 0x5f, 0x61, - 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x66, 0x69, 0x72, 0x73, - 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 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, 0x77, 0x0a, 0x20, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x53, 0x74, 0x61, 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, 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, 0x22, 0x5d, 0x0a, 0x21, 0x42, - 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x63, 0x68, 0x61, - 0x72, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x38, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 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, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x73, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x9c, 0x02, 0x0a, 0x1e, 0x47, - 0x65, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 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, 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, 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, 0x1e, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, - 0x18, 0x06, 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, 0x07, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x2a, 0x0a, - 0x11, 0x74, 0x7a, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x75, 0x74, - 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x74, 0x7a, 0x4f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x4d, 0x69, 0x6e, 0x75, 0x74, 0x65, 0x73, 0x22, 0xd9, 0x02, 0x0a, 0x17, 0x52, 0x65, - 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x42, - 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x55, 0x73, 0x64, 0x4d, 0x69, - 0x6e, 0x6f, 0x72, 0x12, 0x31, 0x0a, 0x15, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, - 0x74, 0x79, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x12, 0x74, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x55, 0x73, - 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x31, 0x0a, 0x15, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, - 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, - 0x72, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x43, 0x6f, 0x69, - 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x17, 0x74, 0x68, 0x69, 0x72, 0x64, - 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x74, 0x68, 0x69, 0x72, 0x64, 0x50, - 0x61, 0x72, 0x74, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x35, - 0x0a, 0x17, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x63, 0x6f, - 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x14, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x69, 0x6e, 0x41, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x80, 0x01, 0x0a, 0x18, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, - 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x42, 0x75, 0x63, 0x6b, - 0x65, 0x74, 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, - 0x1d, 0x0a, 0x0a, 0x62, 0x69, 0x6c, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x09, 0x62, 0x69, 0x6c, 0x6c, 0x43, 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, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x75, 0x73, 0x64, 0x4d, 0x69, 0x6e, - 0x6f, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc0, 0x02, 0x0a, 0x1b, 0x52, 0x65, 0x63, - 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x50, - 0x61, 0x69, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x5f, 0x62, 0x69, 0x6c, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x5f, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x73, 0x79, 0x6e, 0x63, - 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x75, 0x6e, 0x73, 0x79, 0x6e, - 0x63, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0d, 0x75, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, - 0x0a, 0x11, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, - 0x6e, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x65, 0x64, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x29, 0x0a, 0x11, 0x65, 0x73, - 0x74, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x65, 0x73, 0x74, 0x46, 0x65, 0x65, 0x55, 0x73, 0x64, - 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x29, 0x0a, 0x11, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x61, 0x78, - 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0e, 0x65, 0x73, 0x74, 0x54, 0x61, 0x78, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, - 0x12, 0x29, 0x0a, 0x11, 0x65, 0x73, 0x74, 0x5f, 0x6e, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x64, 0x5f, - 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x65, 0x73, 0x74, - 0x4e, 0x65, 0x74, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x22, 0x76, 0x0a, 0x1f, 0x52, - 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x53, 0x61, 0x6c, 0x61, 0x72, - 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x25, - 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, - 0x72, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x55, 0x73, 0x64, 0x4d, 0x69, - 0x6e, 0x6f, 0x72, 0x22, 0xd0, 0x02, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, - 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x05, 0x64, 0x61, 0x69, 0x6c, 0x79, - 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, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, - 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, - 0x52, 0x05, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x12, 0x43, 0x0a, 0x07, 0x72, 0x65, 0x67, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 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, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x42, 0x75, 0x63, - 0x6b, 0x65, 0x74, 0x52, 0x07, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4d, 0x0a, 0x0b, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2c, 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, - 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x50, 0x61, 0x69, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, - 0x0a, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x50, 0x61, 0x69, 0x64, 0x12, 0x59, 0x0a, 0x0f, 0x73, - 0x61, 0x6c, 0x61, 0x72, 0x79, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 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, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, - 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0e, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x22, 0x86, 0x01, 0x0a, 0x21, 0x52, 0x65, 0x66, 0x72, 0x65, - 0x73, 0x68, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x50, - 0x72, 0x69, 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, 0x27, 0x0a, 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x22, - 0xfe, 0x01, 0x0a, 0x12, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x50, 0x72, 0x69, 0x63, 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, 0x23, 0x0a, - 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 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, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x70, - 0x61, 0x69, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x12, 0x1b, - 0x0a, 0x09, 0x74, 0x61, 0x78, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x08, 0x74, 0x61, 0x78, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x6e, - 0x65, 0x74, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, - 0x6e, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x12, 0x20, 0x0a, 0x0c, 0x73, 0x79, 0x6e, 0x63, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, - 0x73, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x22, 0x61, 0x0a, 0x22, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x47, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x70, 0x72, 0x69, 0x63, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x50, - 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x06, 0x70, 0x72, 0x69, - 0x63, 0x65, 0x73, 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, 0xa4, 0x06, 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, 0x12, 0x23, 0x0a, - 0x0d, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x16, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, - 0x65, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x70, 0x70, 0x56, 0x69, 0x73, 0x69, - 0x62, 0x6c, 0x65, 0x22, 0xce, 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, 0x12, - 0x23, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, - 0x54, 0x79, 0x70, 0x65, 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, 0x9c, - 0x03, 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, 0x12, 0x1d, - 0x0a, 0x0a, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, 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, 0x9d, 0x02, 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, - 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, - 0x65, 0x54, 0x79, 0x70, 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, 0xbb, - 0x03, 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, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, - 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x5f, 0x76, 0x69, - 0x73, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0a, 0x61, - 0x70, 0x70, 0x56, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, - 0x5f, 0x61, 0x70, 0x70, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0xda, 0x03, 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, 0x12, 0x23, - 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x62, - 0x6c, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x70, 0x70, 0x56, - 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x61, 0x70, - 0x70, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 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, - 0xa6, 0x04, 0x0a, 0x17, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 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, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, - 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, - 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, - 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, - 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x5f, - 0x77, 0x61, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x79, 0x57, 0x61, - 0x79, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x61, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, - 0x08, 0x6c, 0x6f, 0x67, 0x6f, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6c, 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x6c, 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, 0x2f, 0x0a, 0x14, 0x75, 0x73, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x63, 0x79, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, - 0x75, 0x73, 0x64, 0x54, 0x6f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x61, 0x74, - 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, - 0x0e, 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, 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, 0x22, 0xfa, 0x01, 0x0a, 0x18, 0x54, 0x68, 0x69, - 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 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, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x64, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, 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, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, - 0x72, 0x12, 0x42, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, - 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x07, 0x6d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x73, 0x22, 0xd7, 0x01, 0x0a, 0x24, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x68, - 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, - 0x68, 0x61, 0x6e, 0x6e, 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, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x64, 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, 0x38, 0x0a, 0x18, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, - 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, - 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x22, - 0x6e, 0x0a, 0x25, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, - 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x69, - 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x22, - 0xc4, 0x01, 0x0a, 0x27, 0x53, 0x65, 0x74, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, - 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 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, 0x1b, 0x0a, 0x09, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x04, 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, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, - 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x63, 0x0a, 0x1f, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, - 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x06, 0x6d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 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, 0x54, 0x68, 0x69, 0x72, - 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0xd6, 0x01, 0x0a, 0x22, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, - 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x61, 0x74, 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, 0x1b, 0x0a, 0x09, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x08, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x75, 0x73, 0x64, - 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x72, 0x61, 0x74, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x73, 0x64, 0x54, 0x6f, 0x43, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x61, 0x74, 0x65, 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, 0x98, 0x01, 0x0a, 0x20, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, - 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x53, 0x79, 0x6e, 0x63, 0x49, 0x73, 0x73, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f, 0x64, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0xae, 0x01, 0x0a, 0x23, 0x53, 0x79, 0x6e, 0x63, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, - 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 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, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, - 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 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, 0xed, 0x02, 0x0a, 0x24, 0x53, 0x79, 0x6e, 0x63, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, - 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x32, - 0x0a, 0x15, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, - 0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x73, - 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x66, 0x65, 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x13, 0x66, 0x65, 0x74, 0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, - 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x49, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x73, 0x18, - 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, - 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, - 0x79, 0x6e, 0x63, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x73, - 0x22, 0xf9, 0x01, 0x0a, 0x18, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, - 0x70, 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, 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, 0x28, 0x0a, - 0x10, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, - 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x65, - 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x88, 0x02, 0x0a, - 0x19, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 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, 0x51, 0x0a, 0x0f, 0x70, 0x61, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 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, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x0e, 0x70, 0x61, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x75, - 0x73, 0x64, 0x74, 0x5f, 0x74, 0x72, 0x63, 0x32, 0x30, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x75, 0x73, 0x64, 0x74, 0x54, 0x72, 0x63, - 0x32, 0x30, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x75, 0x73, 0x64, - 0x74, 0x5f, 0x74, 0x72, 0x63, 0x32, 0x30, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x75, 0x73, 0x64, 0x74, 0x54, 0x72, 0x63, 0x32, 0x30, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x8e, 0x08, 0x0a, 0x15, 0x45, 0x78, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, - 0x72, 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, 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, 0x28, 0x0a, - 0x10, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, - 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x65, - 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, - 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x07, 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, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, - 0x0a, 0x0b, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09, 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, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x75, 0x73, 0x64, 0x4d, 0x69, - 0x6e, 0x6f, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2a, - 0x0a, 0x11, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x70, 0x61, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, - 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0e, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f, - 0x64, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x61, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x13, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x5f, 0x77, 0x61, - 0x79, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x79, 0x57, 0x61, 0x79, 0x12, - 0x19, 0x0a, 0x08, 0x70, 0x61, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x70, 0x61, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x61, - 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x79, - 0x55, 0x72, 0x6c, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x63, 0x65, - 0x69, 0x76, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x16, 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, 0x17, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x19, 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, 0x1a, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, - 0x2b, 0x0a, 0x11, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, - 0x70, 0x6c, 0x61, 0x79, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x64, 0x65, 0x6d, - 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x12, 0x2a, 0x0a, 0x11, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x69, - 0x64, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, 0x22, 0x94, 0x05, 0x0a, 0x1c, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, - 0x65, 0x72, 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, 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, 0x28, 0x0a, 0x10, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, - 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, - 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x65, - 0x6e, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x64, 0x75, - 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x70, 0x72, 0x6f, - 0x64, 0x75, 0x63, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x70, - 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, - 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x74, 0x69, - 0x66, 0x79, 0x55, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, - 0x69, 0x70, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x49, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x0e, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x1d, - 0x0a, 0x0a, 0x70, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0f, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x79, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, - 0x0d, 0x70, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x10, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x79, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, - 0x6c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x79, 0x65, 0x72, 0x45, 0x6d, - 0x61, 0x69, 0x6c, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, 0x22, - 0xf6, 0x03, 0x0a, 0x23, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, - 0x61, 0x72, 0x79, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, - 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, 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, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x61, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x75, 0x73, 0x64, - 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, - 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x70, 0x61, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, - 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, - 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, - 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x79, 0x65, 0x72, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x79, 0x65, 0x72, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x79, 0x65, 0x72, - 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, - 0x79, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x77, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x54, - 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, - 0x4f, 0x72, 0x64, 0x65, 0x72, 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, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x49, - 0x64, 0x22, 0xe6, 0x01, 0x0a, 0x22, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, - 0x61, 0x72, 0x79, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 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, 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, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 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, 0x22, 0x7b, 0x0a, 0x23, 0x4c, 0x69, - 0x73, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x63, 0x68, 0x61, - 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x6f, 0x72, 0x64, 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, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x06, 0x6f, 0x72, 0x64, 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, 0x22, 0xaf, 0x01, 0x0a, 0x19, 0x53, 0x75, 0x62, 0x6d, - 0x69, 0x74, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x54, 0x78, 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, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 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, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0x96, 0x01, 0x0a, 0x19, 0x47, 0x65, - 0x74, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, - 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, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 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, 0x22, 0x57, 0x0a, 0x17, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, - 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, - 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, - 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, - 0x72, 0x64, 0x65, 0x72, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x8a, 0x04, 0x0a, 0x26, - 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, - 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 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, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x64, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x6e, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4e, - 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x64, 0x5f, 0x6d, - 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0e, 0x75, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x5f, - 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x44, - 0x61, 0x74, 0x65, 0x4d, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x63, - 0x6f, 0x64, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, - 0x2a, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x79, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x50, 0x61, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6d, - 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, - 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, - 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xda, 0x03, 0x0a, 0x27, 0x56, 0x65, 0x72, - 0x69, 0x66, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x63, - 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, - 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x64, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x6e, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4e, - 0x6f, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x6f, 0x72, - 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4f, 0x72, 0x64, 0x65, 0x72, 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, 0x23, 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, - 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6d, 0x69, - 0x6e, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x19, - 0x0a, 0x08, 0x72, 0x61, 0x77, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x72, 0x61, 0x77, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, - 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, - 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x76, 0x65, 0x72, 0x69, - 0x66, 0x69, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x25, - 0x0a, 0x0e, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x52, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x9f, 0x01, 0x0a, 0x1a, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, - 0x4d, 0x69, 0x66, 0x61, 0x70, 0x61, 0x79, 0x4e, 0x6f, 0x74, 0x69, 0x66, 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, 0x1f, - 0x0a, 0x0b, 0x6d, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x73, 0x69, 0x67, 0x6e, 0x22, 0x79, 0x0a, 0x1b, 0x48, 0x61, 0x6e, 0x64, 0x6c, - 0x65, 0x4d, 0x69, 0x66, 0x61, 0x70, 0x61, 0x79, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, - 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, - 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, - 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x54, 0x65, 0x78, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, - 0x49, 0x64, 0x22, 0xf9, 0x01, 0x0a, 0x18, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x56, 0x35, 0x50, - 0x61, 0x79, 0x4e, 0x6f, 0x74, 0x69, 0x66, 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, 0x19, 0x0a, 0x08, 0x72, 0x61, 0x77, - 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x61, 0x77, - 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, - 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x56, 0x35, 0x50, - 0x61, 0x79, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 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, 0x77, - 0x0a, 0x19, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x56, 0x35, 0x50, 0x61, 0x79, 0x4e, 0x6f, 0x74, - 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, - 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, - 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x65, 0x78, 0x74, 0x12, 0x19, 0x0a, 0x08, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x49, 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, 0xfa, - 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, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x66, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x0c, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x55, 0x73, 0x64, - 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x16, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, - 0x72, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, - 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x43, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f, 0x64, 0x65, 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, 0xdb, 0x04, 0x0a, 0x10, 0x56, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x67, - 0x72, 0x61, 0x6d, 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, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x67, - 0x72, 0x61, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x65, 0x76, 0x65, 0x6c, - 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6c, 0x65, - 0x76, 0x65, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x18, 0x73, 0x61, 0x6d, 0x65, - 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x5f, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x73, 0x61, 0x6d, 0x65, - 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x12, 0x32, 0x0a, 0x15, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x5f, 0x65, 0x78, 0x70, - 0x69, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x13, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x3a, 0x0a, 0x19, 0x64, 0x6f, 0x77, 0x6e, 0x67, 0x72, 0x61, - 0x64, 0x65, 0x5f, 0x70, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x64, 0x6f, 0x77, 0x6e, 0x67, 0x72, - 0x61, 0x64, 0x65, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x12, 0x3c, 0x0a, 0x1a, 0x62, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x68, - 0x65, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x62, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x49, 0x6e, - 0x68, 0x65, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, - 0x1d, 0x0a, 0x0a, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x2c, - 0x0a, 0x12, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x63, 0x61, 0x72, 0x64, 0x5f, 0x65, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x74, 0x72, 0x69, 0x61, - 0x6c, 0x43, 0x61, 0x72, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 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, 0xe0, 0x03, 0x0a, 0x0a, 0x56, 0x69, 0x70, 0x42, 0x65, 0x6e, 0x65, 0x66, 0x69, - 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x64, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, - 0x43, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x65, 0x6e, 0x65, - 0x66, 0x69, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x62, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x75, - 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x0b, 0x75, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x65, 0x76, 0x65, 0x6c, 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, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, - 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x74, - 0x72, 0x69, 0x61, 0x6c, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x07, 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, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, - 0x63, 0x6f, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, - 0x74, 0x6f, 0x5f, 0x65, 0x71, 0x75, 0x69, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, - 0x61, 0x75, 0x74, 0x6f, 0x45, 0x71, 0x75, 0x69, 0x70, 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, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4a, 0x73, 0x6f, 0x6e, 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, 0xdc, 0x05, 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, 0x12, 0x37, 0x0a, 0x08, 0x62, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x73, - 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x42, 0x65, 0x6e, 0x65, - 0x66, 0x69, 0x74, 0x52, 0x08, 0x62, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x73, 0x12, 0x25, 0x0a, - 0x0e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x11, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x9a, 0x02, 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, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x67, 0x72, - 0x61, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, - 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x54, 0x79, 0x70, 0x65, 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, 0x22, 0xa5, 0x04, 0x0a, 0x0c, 0x56, 0x69, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, - 0x72, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x63, 0x61, 0x72, 0x64, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x72, 0x69, 0x61, 0x6c, - 0x43, 0x61, 0x72, 0x64, 0x49, 0x64, 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, 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, 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, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 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, 0x1a, 0x0a, 0x08, 0x65, 0x71, 0x75, - 0x69, 0x70, 0x70, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x65, 0x71, 0x75, - 0x69, 0x70, 0x70, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 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, - 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, - 0x4d, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, - 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x13, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x67, 0x72, - 0x61, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0e, 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, 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, 0x22, 0xe5, 0x01, 0x0a, 0x0f, 0x56, 0x69, - 0x70, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 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, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x39, 0x0a, 0x19, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, - 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x72, 0x6f, 0x6f, 0x6d, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x4e, - 0x6f, 0x74, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x3f, 0x0a, 0x1c, - 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x6e, 0x6f, - 0x74, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x19, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, - 0x4e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x22, 0x0a, - 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, - 0x73, 0x22, 0xfd, 0x03, 0x0a, 0x08, 0x56, 0x69, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x33, - 0x0a, 0x08, 0x70, 0x61, 0x69, 0x64, 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, 0x07, 0x70, 0x61, 0x69, 0x64, - 0x56, 0x69, 0x70, 0x12, 0x4d, 0x0a, 0x13, 0x65, 0x71, 0x75, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, - 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x63, 0x61, 0x72, 0x64, 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, 0x56, 0x69, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x52, - 0x11, 0x65, 0x71, 0x75, 0x69, 0x70, 0x70, 0x65, 0x64, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, - 0x72, 0x64, 0x12, 0x3d, 0x0a, 0x0d, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, - 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, 0x0c, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x56, 0x69, - 0x70, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x65, 0x66, 0x66, - 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x12, - 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x65, 0x6e, 0x65, 0x66, 0x69, - 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x42, 0x65, - 0x6e, 0x65, 0x66, 0x69, 0x74, 0x52, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, - 0x42, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x76, 0x61, 0x6c, - 0x75, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0d, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, - 0x12, 0x48, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x50, 0x72, - 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, - 0x67, 0x72, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x45, 0x0a, 0x0d, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 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, 0x86, - 0x02, 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, 0x12, 0x2f, 0x0a, 0x05, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, - 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x48, 0x0a, - 0x0e, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x56, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x67, 0x72, - 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, - 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x6f, 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, 0x12, 0x2f, 0x0a, - 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, - 0x69, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 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, 0xc4, 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, 0x12, 0x2f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x22, 0xd3, 0x01, 0x0a, 0x18, 0x44, 0x65, 0x62, 0x69, 0x74, 0x43, 0x50, - 0x42, 0x72, 0x65, 0x61, 0x6b, 0x75, 0x70, 0x46, 0x65, 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, 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, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x68, 0x69, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, 0x12, 0x23, 0x0a, - 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc8, 0x01, 0x0a, 0x19, 0x44, - 0x65, 0x62, 0x69, 0x74, 0x43, 0x50, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x75, 0x70, 0x46, 0x65, 0x65, - 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, - 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x02, 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, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x63, 0x6f, 0x69, 0x6e, - 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x07, - 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, 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, 0xbc, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x62, 0x69, 0x74, 0x57, - 0x68, 0x65, 0x65, 0x6c, 0x44, 0x72, 0x61, 0x77, 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, 0x19, 0x0a, 0x08, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x1d, 0x0a, - 0x0a, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x09, 0x64, 0x72, 0x61, 0x77, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, - 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc5, 0x01, 0x0a, 0x16, 0x44, 0x65, 0x62, 0x69, 0x74, 0x57, 0x68, - 0x65, 0x65, 0x6c, 0x44, 0x72, 0x61, 0x77, 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, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, - 0x70, 0x65, 0x6e, 0x74, 0x18, 0x02, 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, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x10, 0x63, 0x6f, 0x69, 0x6e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, - 0x74, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, - 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, 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, 0xff, 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, 0x12, 0x2f, 0x0a, 0x05, - 0x73, 0x74, 0x61, 0x74, 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, 0x56, 0x69, - 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x56, 0x0a, - 0x1a, 0x47, 0x65, 0x74, 0x56, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 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, 0xb7, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x56, 0x69, 0x70, - 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x56, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x67, 0x72, - 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x37, 0x0a, 0x08, 0x62, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x42, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x52, - 0x08, 0x62, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x73, 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, - 0xc3, 0x01, 0x0a, 0x22, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, - 0x69, 0x70, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 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, 0x39, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x86, 0x01, 0x0a, 0x23, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, - 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, - 0x56, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 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, 0x1a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x79, 0x56, 0x69, 0x70, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 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, 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, 0x3e, 0x0a, 0x19, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x6e, - 0x6f, 0x74, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x16, 0x72, 0x6f, 0x6f, 0x6d, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x4e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x88, 0x01, 0x01, - 0x12, 0x44, 0x0a, 0x1c, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, - 0x6c, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x48, 0x01, 0x52, 0x19, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x4e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x88, 0x01, 0x01, 0x42, 0x1c, 0x0a, 0x1a, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x42, 0x1f, 0x0a, 0x1d, 0x5f, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, - 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x81, 0x01, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x4d, 0x79, 0x56, 0x69, 0x70, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 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, 0x56, 0x69, 0x70, 0x55, 0x73, 0x65, - 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 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, 0xd2, 0x03, 0x0a, 0x15, 0x56, 0x69, - 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, - 0x52, 0x75, 0x6e, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x61, - 0x73, 0x6b, 0x5f, 0x64, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x61, - 0x73, 0x6b, 0x44, 0x61, 0x79, 0x12, 0x20, 0x0a, 0x0c, 0x64, 0x61, 0x79, 0x5f, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x61, 0x79, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x4d, 0x73, 0x12, 0x1c, 0x0a, 0x0a, 0x64, 0x61, 0x79, 0x5f, 0x65, - 0x6e, 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x64, 0x61, 0x79, - 0x45, 0x6e, 0x64, 0x4d, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x12, - 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x5f, 0x6a, 0x73, - 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x41, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x4a, 0x73, 0x6f, 0x6e, 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, 0x20, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x63, 0x61, - 0x6e, 0x6e, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 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, 0x26, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, - 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0d, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xe9, - 0x03, 0x0a, 0x12, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, - 0x65, 0x62, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x62, 0x61, 0x74, 0x65, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x62, 0x61, 0x74, 0x65, - 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, 0x74, - 0x61, 0x73, 0x6b, 0x5f, 0x64, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, - 0x61, 0x73, 0x6b, 0x44, 0x61, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x69, 0x70, 0x5f, 0x6c, 0x65, - 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x76, 0x69, 0x70, 0x4c, 0x65, - 0x76, 0x65, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x69, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x69, 0x70, 0x4e, 0x61, 0x6d, 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, - 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x61, 0x76, 0x61, 0x69, 0x6c, - 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0d, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x74, 0x4d, 0x73, 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, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x6c, - 0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0b, 0x63, 0x6c, 0x61, 0x69, 0x6d, 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, 0x0c, 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, 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, 0x9b, 0x01, 0x0a, 0x25, 0x50, - 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, - 0x69, 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, 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, 0x19, - 0x0a, 0x08, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x64, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x44, 0x61, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, 0x74, - 0x63, 0x68, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, - 0x61, 0x74, 0x63, 0x68, 0x53, 0x69, 0x7a, 0x65, 0x22, 0xed, 0x01, 0x0a, 0x26, 0x50, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, - 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x03, 0x72, 0x75, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, - 0x65, 0x62, 0x61, 0x74, 0x65, 0x52, 0x75, 0x6e, 0x52, 0x03, 0x72, 0x75, 0x6e, 0x12, 0x23, 0x0a, - 0x0d, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x73, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x61, 0x73, 0x5f, 0x6d, - 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x68, 0x61, 0x73, 0x4d, 0x6f, - 0x72, 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, 0x7a, 0x0a, 0x25, 0x47, 0x65, 0x74, 0x4d, - 0x79, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, - 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, 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, 0x22, 0xa1, 0x01, 0x0a, 0x26, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x43, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x74, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, - 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, 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, 0x3b, 0x0a, 0x06, 0x72, 0x65, 0x62, 0x61, 0x74, 0x65, 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, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, - 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, 0x52, 0x06, 0x72, 0x65, 0x62, 0x61, - 0x74, 0x65, 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, 0xcc, 0x01, 0x0a, 0x27, 0x4c, 0x69, 0x73, - 0x74, 0x4d, 0x79, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, - 0x65, 0x62, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 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, 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, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x62, 0x61, - 0x74, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, - 0x62, 0x61, 0x74, 0x65, 0x49, 0x64, 0x73, 0x22, 0xa5, 0x01, 0x0a, 0x28, 0x4c, 0x69, 0x73, 0x74, - 0x4d, 0x79, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, - 0x62, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x07, 0x72, 0x65, 0x62, 0x61, 0x74, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, - 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, 0x52, 0x07, 0x72, 0x65, 0x62, 0x61, - 0x74, 0x65, 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, - 0x90, 0x01, 0x0a, 0x1e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, - 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, 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, 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, 0x62, 0x61, 0x74, 0x65, 0x5f, - 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x62, 0x61, 0x74, 0x65, - 0x49, 0x64, 0x22, 0xed, 0x01, 0x0a, 0x1f, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x69, 0x70, 0x44, - 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x72, 0x65, 0x62, 0x61, 0x74, 0x65, - 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, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, - 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, 0x52, 0x06, 0x72, 0x65, 0x62, - 0x61, 0x74, 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, 0x40, 0x0a, 0x0c, 0x63, 0x6f, - 0x69, 0x6e, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x03, 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, - 0x0b, 0x63, 0x6f, 0x69, 0x6e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 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, 0x22, 0xcc, 0x02, 0x0a, 0x18, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x56, 0x69, 0x70, 0x54, - 0x72, 0x69, 0x61, 0x6c, 0x43, 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, - 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, - 0x6c, 0x65, 0x76, 0x65, 0x6c, 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, 0x24, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x0a, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x88, 0x01, 0x01, 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, 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, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, - 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x19, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x56, 0x69, 0x70, 0x54, 0x72, - 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3c, 0x0a, 0x0a, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x63, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, - 0x72, 0x64, 0x52, 0x09, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x12, 0x2f, 0x0a, - 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, - 0x69, 0x70, 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, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, - 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x94, 0x01, 0x0a, 0x18, 0x45, 0x71, 0x75, 0x69, 0x70, 0x56, 0x69, - 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 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, 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, 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x19, - 0x45, 0x71, 0x75, 0x69, 0x70, 0x56, 0x69, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x0a, 0x74, 0x72, 0x69, - 0x61, 0x6c, 0x5f, 0x63, 0x61, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x56, 0x69, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x52, 0x09, 0x74, 0x72, - 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x12, 0x2f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 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, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x6f, - 0x0a, 0x1a, 0x55, 0x6e, 0x65, 0x71, 0x75, 0x69, 0x70, 0x56, 0x69, 0x70, 0x54, 0x72, 0x69, 0x61, - 0x6c, 0x43, 0x61, 0x72, 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, 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, - 0x94, 0x01, 0x0a, 0x1b, 0x55, 0x6e, 0x65, 0x71, 0x75, 0x69, 0x70, 0x56, 0x69, 0x70, 0x54, 0x72, - 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x1e, 0x0a, 0x0a, 0x75, 0x6e, 0x65, 0x71, 0x75, 0x69, 0x70, 0x70, 0x65, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0a, 0x75, 0x6e, 0x65, 0x71, 0x75, 0x69, 0x70, 0x70, 0x65, 0x64, 0x12, - 0x2f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x56, 0x69, 0x70, 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, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x16, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x56, 0x69, 0x70, 0x42, 0x65, 0x6e, 0x65, 0x66, 0x69, 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, 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, 0x21, 0x0a, 0x0c, 0x62, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x5f, - 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x65, 0x6e, 0x65, - 0x66, 0x69, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x22, 0xe8, 0x01, 0x0a, 0x17, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x56, 0x69, 0x70, 0x42, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 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, 0x35, 0x0a, - 0x07, 0x62, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x56, 0x69, 0x70, 0x42, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x52, 0x07, 0x62, 0x65, 0x6e, - 0x65, 0x66, 0x69, 0x74, 0x12, 0x2f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x6e, 0x69, 0x61, 0x6c, 0x5f, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, - 0x6e, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x76, - 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0d, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, - 0x4d, 0x73, 0x22, 0xea, 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, 0x12, 0x37, 0x0a, 0x08, 0x62, 0x65, 0x6e, 0x65, 0x66, 0x69, - 0x74, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x42, 0x65, - 0x6e, 0x65, 0x66, 0x69, 0x74, 0x52, 0x08, 0x62, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x73, 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, 0xbf, 0x01, 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, 0x12, 0x48, - 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x67, - 0x72, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x67, 0x72, - 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0xc1, 0x01, 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, 0x12, 0x48, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, - 0x70, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, - 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xa8, 0x02, - 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, 0x12, 0x2a, 0x0a, 0x11, - 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 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, 0xdd, 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, 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, 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, - 0xb4, 0x02, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 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, 0x19, 0x0a, - 0x08, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x54, 0x69, 0x65, 0x72, - 0x49, 0x64, 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, 0x2a, 0x0a, 0x11, 0x76, 0x69, - 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, - 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xb7, 0x01, 0x0a, 0x19, 0x43, 0x72, 0x65, 0x64, 0x69, - 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 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, 0xe7, 0x02, 0x0a, 0x21, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 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, 0x19, 0x0a, 0x08, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x49, 0x64, 0x12, 0x1f, 0x0a, - 0x0b, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, - 0x0a, 0x07, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x07, 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, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x69, 0x65, 0x72, - 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x5f, 0x6b, 0x65, - 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x4b, 0x65, - 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x65, 0x61, 0x63, 0x68, 0x65, - 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0xc0, - 0x01, 0x0a, 0x22, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 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, 0xcb, 0x02, 0x0a, 0x20, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x41, 0x67, 0x65, 0x6e, - 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 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, 0x25, - 0x0a, 0x0e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x49, 0x64, - 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x64, 0x12, 0x17, 0x0a, - 0x07, 0x72, 0x61, 0x6e, 0x6b, 0x5f, 0x6e, 0x6f, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, - 0x72, 0x61, 0x6e, 0x6b, 0x4e, 0x6f, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f, - 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x73, 0x63, 0x6f, - 0x72, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, - 0xbf, 0x01, 0x0a, 0x21, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, - 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 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, 0xc3, - 0x02, 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, - 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x4d, - 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x4b, 0x65, 0x79, - 0x12, 0x19, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x09, 0x20, 0x03, - 0x28, 0x03, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x73, - 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x52, 0x6f, 0x6c, 0x65, 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, 0x22, 0xae, 0x04, - 0x0a, 0x19, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x50, 0x75, - 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 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, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 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, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 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, 0x05, 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, 0x06, 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, 0x07, 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, 0x23, 0x0a, 0x0d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x64, 0x61, 0x79, 0x73, 0x18, 0x08, 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, 0x63, 0x6f, 0x69, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x70, 0x72, - 0x69, 0x63, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 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, 0x0b, 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, 0x2a, 0x0a, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, - 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, - 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x0d, 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, 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, 0x82, - 0x02, 0x0a, 0x25, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, - 0x68, 0x6f, 0x70, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x4f, 0x72, 0x64, 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, 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, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 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, 0x82, 0x01, 0x0a, 0x26, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, - 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, - 0x0a, 0x06, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, - 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, 0x50, 0x75, 0x72, - 0x63, 0x68, 0x61, 0x73, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x06, 0x6f, 0x72, 0x64, 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, 0x22, 0x58, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x47, - 0x69, 0x66, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 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, 0x39, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x47, 0x69, 0x66, 0x74, 0x43, 0x61, 0x74, - 0x61, 0x6c, 0x6f, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x8d, 0x01, - 0x0a, 0x10, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x76, 0x65, 0x6e, 0x75, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x5f, 0x65, 0x61, - 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x64, 0x69, - 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x45, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x2b, 0x0a, - 0x11, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x5f, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, - 0x64, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x69, - 0x66, 0x74, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0b, 0x67, 0x69, 0x66, 0x74, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x22, 0xb4, 0x01, - 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x76, 0x65, 0x6e, 0x75, 0x65, - 0x53, 0x74, 0x61, 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, 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, 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, 0x22, 0x56, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, - 0x65, 0x76, 0x65, 0x6e, 0x75, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 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, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x76, 0x65, 0x6e, 0x75, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x22, 0x66, 0x0a, 0x15, - 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x65, 0x5f, 0x69, - 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x73, 0x68, 0x61, - 0x72, 0x65, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x67, 0x69, 0x66, 0x74, - 0x65, 0x64, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0f, 0x67, 0x69, 0x66, 0x74, 0x65, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc8, 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, - 0x63, 0x79, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x53, 0x74, 0x61, 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, 0x2f, 0x0a, 0x14, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x11, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x55, 0x73, 0x65, - 0x72, 0x49, 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, 0x22, - 0x60, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, - 0x73, 0x22, 0x62, 0x0a, 0x13, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x47, - 0x69, 0x66, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x69, 0x66, 0x74, - 0x5f, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x67, - 0x69, 0x66, 0x74, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x67, 0x69, 0x66, - 0x74, 0x65, 0x64, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x67, 0x69, 0x66, 0x74, 0x65, 0x64, 0x48, 0x6f, 0x73, 0x74, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xb9, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x53, 0x74, 0x61, 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, 0x22, 0x0a, 0x0d, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x49, 0x64, 0x73, 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, 0x22, 0x5c, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, - 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x47, - 0x69, 0x66, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x22, - 0xe6, 0x02, 0x0a, 0x1f, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, - 0x77, 0x61, 0x6c, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 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, 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, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, - 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, - 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x10, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x69, 0x6e, 0x41, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x13, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 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, 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, 0x22, 0xaf, 0x01, 0x0a, 0x25, 0x4c, 0x69, 0x73, - 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, - 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 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, 0x21, 0x0a, 0x0c, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 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, 0x74, 0x0a, 0x26, 0x4c, 0x69, - 0x73, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, - 0x6c, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x07, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, - 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, - 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, - 0x22, 0x93, 0x02, 0x0a, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x50, 0x6f, 0x69, - 0x6e, 0x74, 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, 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, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x03, 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, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, - 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, - 0x0a, 0x13, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, - 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 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, 0xf1, 0x02, 0x0a, 0x21, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x66, 0x65, 0x72, 0x50, 0x6f, 0x69, 0x6e, 0x74, 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, 0x3b, 0x0a, 0x1a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 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, 0x21, 0x0a, 0x0c, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, - 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x10, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, - 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x5f, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x10, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x37, 0x0a, 0x18, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x5f, 0x73, 0x65, 0x6c, 0x6c, 0x65, - 0x72, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x15, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, - 0x43, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x8f, 0x01, 0x0a, 0x1f, 0x47, - 0x65, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, - 0x6c, 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, 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, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x77, 0x5f, 0x6d, 0x73, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6e, 0x6f, 0x77, 0x4d, 0x73, 0x22, 0xd0, 0x01, 0x0a, - 0x20, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, - 0x77, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x24, 0x0a, 0x0e, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0c, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x50, 0x65, 0x72, 0x55, 0x73, 0x64, 0x12, 0x17, 0x0a, - 0x07, 0x66, 0x65, 0x65, 0x5f, 0x62, 0x70, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, - 0x66, 0x65, 0x65, 0x42, 0x70, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, - 0x6d, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, - 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x30, 0x0a, - 0x14, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x32, - 0xf4, 0x03, 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, 0x12, 0x91, 0x01, 0x0a, 0x1e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x56, 0x69, - 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, - 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x56, - 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, - 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, - 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe0, 0x72, 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, 0x5e, 0x0a, 0x0f, - 0x44, 0x65, 0x62, 0x69, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x47, 0x69, 0x66, 0x74, 0x12, - 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x65, 0x62, 0x69, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 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, - 0x5c, 0x0a, 0x0e, 0x44, 0x65, 0x62, 0x69, 0x74, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x47, 0x69, 0x66, - 0x74, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x69, 0x74, 0x52, 0x6f, 0x62, 0x6f, 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, 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, 0x70, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, - 0x65, 0x76, 0x65, 0x6e, 0x75, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x2b, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x76, 0x65, 0x6e, 0x75, 0x65, 0x53, 0x74, 0x61, 0x74, - 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, 0x47, 0x65, 0x74, 0x48, 0x6f, - 0x73, 0x74, 0x52, 0x65, 0x76, 0x65, 0x6e, 0x75, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x73, 0x12, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 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, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, - 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x79, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x53, 0x74, 0x61, 0x74, - 0x73, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, - 0x74, 0x47, 0x69, 0x66, 0x74, 0x53, 0x74, 0x61, 0x74, 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, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, - 0x74, 0x47, 0x69, 0x66, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x79, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x54, 0x65, 0x61, 0x6d, 0x48, 0x6f, 0x73, - 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x2e, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x54, 0x65, 0x61, 0x6d, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, - 0x53, 0x74, 0x61, 0x74, 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, 0x47, - 0x65, 0x74, 0x54, 0x65, 0x61, 0x6d, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, - 0x53, 0x74, 0x61, 0x74, 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, 0x91, 0x01, 0x0a, 0x1e, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, - 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x54, 0x6f, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x12, 0x36, 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, 0x53, 0x65, 0x6c, 0x6c, 0x65, - 0x72, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x54, 0x6f, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 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, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x54, 0x6f, - 0x43, 0x68, 0x69, 0x6c, 0x64, 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, 0x91, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x43, 0x6f, 0x69, 0x6e, 0x53, - 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x12, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x69, - 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x43, 0x6f, 0x69, 0x6e, - 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x61, 0x6c, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x19, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x66, 0x65, 0x72, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x54, 0x6f, 0x43, 0x6f, 0x69, 0x6e, 0x53, - 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x31, 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, - 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x54, 0x6f, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, - 0x72, 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, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x66, 0x65, 0x72, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x54, 0x6f, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, - 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7f, 0x0a, 0x18, - 0x47, 0x65, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, - 0x61, 0x6c, 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, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 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, - 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x79, 0x0a, - 0x16, 0x46, 0x72, 0x65, 0x65, 0x7a, 0x65, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x57, 0x69, 0x74, - 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x7a, 0x65, - 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, - 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, 0x46, 0x72, 0x65, 0x65, 0x7a, 0x65, - 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x79, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x74, - 0x6c, 0x65, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, - 0x61, 0x6c, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x61, 0x6c, 0x61, 0x72, - 0x79, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 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, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x61, 0x6c, 0x61, 0x72, - 0x79, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x17, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x61, - 0x6c, 0x61, 0x72, 0x79, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x12, 0x2f, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x57, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 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, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x57, - 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x76, 0x0a, 0x15, 0x46, 0x72, 0x65, 0x65, 0x7a, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x72, 0x65, - 0x65, 0x7a, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, - 0x61, 0x6c, 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, 0x46, 0x72, 0x65, 0x65, - 0x7a, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, - 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x76, 0x0a, 0x15, 0x53, 0x65, 0x74, - 0x74, 0x6c, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, - 0x61, 0x6c, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 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, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, - 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x79, 0x0a, 0x16, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x12, 0x2e, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x61, 0x6c, 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, 0x52, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x61, 0x6c, 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, 0x5b, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 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, 0x44, 0x65, 0x6c, 0x65, 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, 0x73, 0x0a, 0x14, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 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, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 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, 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, 0x7f, 0x0a, 0x18, 0x50, 0x69, 0x6e, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, - 0x68, 0x6f, 0x74, 0x12, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 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, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, - 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, 0x76, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x47, 0x69, 0x66, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, - 0x6f, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x47, - 0x69, 0x66, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 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, 0x47, 0x69, - 0x66, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 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, 0x79, 0x0a, 0x16, 0x42, - 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 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, 0x61, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 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, 0x44, 0x65, 0x6c, 0x65, 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, 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, 0x74, - 0x0a, 0x18, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x50, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x30, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72, 0x61, - 0x6e, 0x74, 0x50, 0x69, 0x6e, 0x6e, 0x65, 0x64, 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, 0x13, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x12, 0x2b, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x61, 0x6e, - 0x74, 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, 0x91, 0x01, 0x0a, 0x1e, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, - 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x36, - 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, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 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, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, - 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 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, 0x79, 0x0a, 0x16, - 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x53, - 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 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, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x19, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x31, 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, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x53, 0x74, 0x61, 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, 0x42, 0x61, 0x74, 0x63, 0x68, - 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x17, - 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, - 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, - 0x77, 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, 0x47, 0x65, 0x74, 0x52, 0x65, - 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, - 0x65, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x85, 0x01, 0x0a, 0x1a, 0x52, - 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x50, 0x61, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x50, 0x72, 0x69, 0x63, 0x65, 0x73, 0x12, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, - 0x65, 0x73, 0x68, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x50, 0x72, 0x69, 0x63, 0x65, 0x73, 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, - 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x50, 0x61, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x69, 0x63, 0x65, 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, 0x8e, 0x01, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, - 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 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, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, - 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8e, 0x01, 0x0a, 0x20, 0x53, 0x65, 0x74, - 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x38, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x65, 0x74, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 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, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, - 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x84, 0x01, 0x0a, 0x1b, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x52, 0x61, 0x74, 0x65, 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, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x8b, 0x01, 0x0a, 0x1c, 0x53, 0x79, 0x6e, 0x63, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, - 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x73, 0x12, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, - 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x54, 0x68, - 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, - 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 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, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70, - 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, - 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 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, - 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 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, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, - 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x7e, 0x0a, 0x1c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, - 0x61, 0x72, 0x79, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, - 0x12, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, - 0x72, 0x79, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 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, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, - 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x78, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, - 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x31, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 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, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, - 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x88, 0x01, 0x0a, 0x1b, 0x4c, - 0x69, 0x73, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x33, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, - 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x52, - 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x12, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x48, - 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x54, 0x78, 0x12, 0x2a, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, - 0x62, 0x6d, 0x69, 0x74, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x54, 0x78, - 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, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x6a, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, - 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x35, 0x52, - 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 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, 0x48, 0x35, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, - 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x94, 0x01, - 0x0a, 0x1f, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, - 0x65, 0x72, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, - 0x74, 0x12, 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, - 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x63, 0x65, - 0x69, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, - 0x69, 0x66, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x63, - 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70, 0x0a, 0x13, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x4d, 0x69, - 0x66, 0x61, 0x70, 0x61, 0x79, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x12, 0x2b, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x61, - 0x6e, 0x64, 0x6c, 0x65, 0x4d, 0x69, 0x66, 0x61, 0x70, 0x61, 0x79, 0x4e, 0x6f, 0x74, 0x69, 0x66, - 0x79, 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, 0x48, 0x61, 0x6e, 0x64, 0x6c, - 0x65, 0x4d, 0x69, 0x66, 0x61, 0x70, 0x61, 0x79, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x11, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, - 0x56, 0x35, 0x50, 0x61, 0x79, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x12, 0x29, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x61, - 0x6e, 0x64, 0x6c, 0x65, 0x56, 0x35, 0x50, 0x61, 0x79, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 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, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x56, - 0x35, 0x50, 0x61, 0x79, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 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, 0x70, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x56, 0x69, 0x70, 0x50, 0x72, - 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2b, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x56, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 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, 0x47, 0x65, 0x74, 0x56, 0x69, - 0x70, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x64, 0x0a, 0x0f, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x56, 0x69, 0x70, 0x42, 0x65, 0x6e, 0x65, 0x66, 0x69, 0x74, 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x56, 0x69, 0x70, 0x42, 0x65, 0x6e, 0x65, 0x66, 0x69, 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, 0x68, 0x65, 0x63, 0x6b, 0x56, 0x69, 0x70, 0x42, 0x65, - 0x6e, 0x65, 0x66, 0x69, 0x74, 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, 0x6a, 0x0a, 0x11, 0x44, 0x65, 0x62, 0x69, 0x74, - 0x43, 0x50, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x75, 0x70, 0x46, 0x65, 0x65, 0x12, 0x29, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, - 0x65, 0x62, 0x69, 0x74, 0x43, 0x50, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x75, 0x70, 0x46, 0x65, 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, 0x44, 0x65, 0x62, 0x69, 0x74, 0x43, - 0x50, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x75, 0x70, 0x46, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x0e, 0x44, 0x65, 0x62, 0x69, 0x74, 0x57, 0x68, 0x65, 0x65, - 0x6c, 0x44, 0x72, 0x61, 0x77, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x69, 0x74, 0x57, 0x68, 0x65, - 0x65, 0x6c, 0x44, 0x72, 0x61, 0x77, 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, - 0x44, 0x65, 0x62, 0x69, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x44, 0x72, 0x61, 0x77, 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, 0x6a, 0x0a, 0x11, 0x47, 0x72, 0x61, 0x6e, 0x74, - 0x56, 0x69, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x12, 0x29, 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, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, - 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, 0x72, 0x61, 0x6e, 0x74, 0x56, - 0x69, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x11, 0x45, 0x71, 0x75, 0x69, 0x70, 0x56, 0x69, 0x70, 0x54, - 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x71, 0x75, 0x69, 0x70, - 0x56, 0x69, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, 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, 0x56, 0x69, 0x70, 0x54, 0x72, - 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x70, 0x0a, 0x13, 0x55, 0x6e, 0x65, 0x71, 0x75, 0x69, 0x70, 0x56, 0x69, 0x70, 0x54, 0x72, 0x69, - 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, 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, - 0x56, 0x69, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, 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, 0x56, 0x69, 0x70, - 0x54, 0x72, 0x69, 0x61, 0x6c, 0x43, 0x61, 0x72, 0x64, 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, 0x88, 0x01, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x33, 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, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 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, 0x50, 0x72, 0x6f, 0x67, 0x72, - 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x70, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x79, 0x56, 0x69, 0x70, 0x53, - 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 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, - 0x4d, 0x79, 0x56, 0x69, 0x70, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 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, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x79, 0x56, - 0x69, 0x70, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x91, 0x01, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x43, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, - 0x65, 0x62, 0x61, 0x74, 0x65, 0x12, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x43, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, - 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x4d, 0x79, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x56, 0x69, 0x70, 0x44, - 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x97, 0x01, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x4d, - 0x79, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x62, - 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x38, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x4d, 0x79, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, - 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x79, 0x56, 0x69, - 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x7c, 0x0a, 0x17, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, - 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, - 0x61, 0x69, 0x6d, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x52, - 0x65, 0x62, 0x61, 0x74, 0x65, 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, 0x43, - 0x6c, 0x61, 0x69, 0x6d, 0x56, 0x69, 0x70, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x6f, 0x69, 0x6e, - 0x52, 0x65, 0x62, 0x61, 0x74, 0x65, 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, - 0x6a, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x52, 0x65, - 0x77, 0x61, 0x72, 0x64, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, - 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x57, 0x68, 0x65, - 0x65, 0x6c, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 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, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 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, 0x85, 0x01, 0x0a, - 0x1a, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, 0x32, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, - 0x65, 0x64, 0x69, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 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, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x19, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x77, 0x61, - 0x72, 0x64, 0x12, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, - 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 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, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 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, -} +const file_proto_wallet_v1_wallet_proto_rawDesc = "" + + "\n" + + "\x1cproto/wallet/v1/wallet.proto\x12\x0fhyapp.wallet.v1\"\xb8\x04\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\x12%\n" + + "\x0eentitlement_id\x18\x0e \x01(\tR\rentitlementId\x12#\n" + + "\rcharge_source\x18\x0f \x01(\tR\fchargeSource\"\xa5\x04\n" + + "\x16DebitDirectGiftRequest\x12\x1d\n" + + "\n" + + "command_id\x18\x01 \x01(\tR\tcommandId\x12$\n" + + "\x0esender_user_id\x18\x02 \x01(\x03R\fsenderUserId\x12$\n" + + "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\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" + + "\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" + + "\x0eentitlement_id\x18\r \x01(\tR\rentitlementId\x12#\n" + + "\rcharge_source\x18\x0e \x01(\tR\fchargeSource\"\xc2\v\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\x12(\n" + + "\x10cp_relation_type\x18\r \x01(\tR\x0ecpRelationType\x12\x1b\n" + + "\tgift_name\x18\x0e \x01(\tR\bgiftName\x12\"\n" + + "\rgift_icon_url\x18\x0f \x01(\tR\vgiftIconUrl\x12,\n" + + "\x12gift_animation_url\x18\x10 \x01(\tR\x10giftAnimationUrl\x12*\n" + + "\x11gift_effect_types\x18\x11 \x03(\tR\x0fgiftEffectTypes\x12%\n" + + "\x0eentitlement_id\x18\x12 \x01(\tR\rentitlementId\x12#\n" + + "\rcharge_source\x18\x13 \x01(\tR\fchargeSource\x125\n" + + "\x17gift_income_coin_amount\x18\x14 \x01(\x03R\x14giftIncomeCoinAmount\x129\n" + + "\x19gift_income_balance_after\x18\x15 \x01(\x03R\x16giftIncomeBalanceAfter\x12(\n" + + "\x10host_point_added\x18\x16 \x01(\x03R\x0ehostPointAdded\x127\n" + + "\x18host_point_balance_after\x18\x17 \x01(\x03R\x15hostPointBalanceAfter\x121\n" + + "\x15host_point_asset_type\x18\x18 \x01(\tR\x12hostPointAssetType\x12D\n" + + "\x1fhost_point_policy_instance_code\x18\x19 \x01(\tR\x1bhostPointPolicyInstanceCode\x127\n" + + "\x18host_point_template_code\x18\x1a \x01(\tR\x15hostPointTemplateCode\x12=\n" + + "\x1bhost_point_template_version\x18\x1b \x01(\tR\x18hostPointTemplateVersion\x12'\n" + + "\x0fbalance_version\x18\x1c \x01(\x03R\x0ebalanceVersion\x127\n" + + "\x18recharge_seven_day_coins\x18\x1d \x01(\x03R\x15rechargeSevenDayCoins\x129\n" + + "\x19recharge_thirty_day_coins\x18\x1e \x01(\x03R\x16rechargeThirtyDayCoins\x12/\n" + + "\x14last_recharged_at_ms\x18\x1f \x01(\x03R\x11lastRechargedAtMs\x12\x1c\n" + + "\n" + + "paid_at_ms\x18 \x01(\x03R\bpaidAtMs\"\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\"\xbc\x03\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\x12%\n" + + "\x0eentitlement_id\x18\v \x01(\tR\rentitlementId\x12#\n" + + "\rcharge_source\x18\f \x01(\tR\fchargeSource\"\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\"\xda\x02\n" + + "\x15DebitRobotGiftRequest\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" + + "\x10sender_region_id\x18\n" + + " \x01(\x03R\x0esenderRegionId\"\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\"\x91\x02\n" + + "\x17TeamHostSalaryCycleStat\x12\x1b\n" + + "\tcycle_key\x18\x01 \x01(\tR\bcycleKey\x12D\n" + + "\x1festimated_host_salary_usd_minor\x18\x02 \x01(\x03R\x1bestimatedHostSalaryUsdMinor\x12@\n" + + "\x1dsettled_host_salary_usd_minor\x18\x03 \x01(\x03R\x19settledHostSalaryUsdMinor\x12*\n" + + "\x11active_host_count\x18\x04 \x01(\x05R\x0factiveHostCount\x12%\n" + + "\x0etotal_diamonds\x18\x05 \x01(\x03R\rtotalDiamonds\"\xc2\x01\n" + + "\x1dGetTeamHostSalaryStatsRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x121\n" + + "\x15agency_owner_user_ids\x18\x03 \x03(\x03R\x12agencyOwnerUserIds\x12\x1d\n" + + "\n" + + "cycle_keys\x18\x04 \x03(\tR\tcycleKeys\x12\x15\n" + + "\x06now_ms\x18\x05 \x01(\x03R\x05nowMs\"\x86\x01\n" + + "\x1eGetTeamHostSalaryStatsResponse\x12>\n" + + "\x05stats\x18\x01 \x03(\v2(.hyapp.wallet.v1.TeamHostSalaryCycleStatR\x05stats\x12$\n" + + "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xad\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\x12\x16\n" + + "\x06remark\x18\t \x01(\tR\x06remark\"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\"\xf9\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\x12*\n" + + "\x11seller_country_id\x18\f \x01(\x03R\x0fsellerCountryId\x12(\n" + + "\x10seller_region_id\x18\r \x01(\x03R\x0esellerRegionId\"\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\"\xd5\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\x12*\n" + + "\x11target_country_id\x18\t \x01(\x03R\x0ftargetCountryId\"\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\"\xf8\x01\n" + + "%TransferCoinSellerStockToChildRequest\x12\x1d\n" + + "\n" + + "command_id\x18\x01 \x01(\tR\tcommandId\x12$\n" + + "\x0eparent_user_id\x18\x02 \x01(\x03R\fparentUserId\x12\"\n" + + "\rchild_user_id\x18\x03 \x01(\x03R\vchildUserId\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\x1b\n" + + "\tregion_id\x18\a \x01(\x03R\bregionId\"\xed\x01\n" + + "&TransferCoinSellerStockToChildResponse\x12%\n" + + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x120\n" + + "\x14parent_balance_after\x18\x02 \x01(\x03R\x12parentBalanceAfter\x12.\n" + + "\x13child_balance_after\x18\x03 \x01(\x03R\x11childBalanceAfter\x12\x16\n" + + "\x06amount\x18\x04 \x01(\x03R\x06amount\x12\"\n" + + "\rcreated_at_ms\x18\x05 \x01(\x03R\vcreatedAtMs\"\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\"\x87\x02\n" + + "\x1dFreezeSalaryWithdrawalRequest\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\x12%\n" + + "\x0ewithdrawal_ref\x18\a \x01(\tR\rwithdrawalRef\"\xaa\x01\n" + + "\x1eFreezeSalaryWithdrawalResponse\x12%\n" + + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x127\n" + + "\abalance\x18\x02 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\x12(\n" + + "\x10salary_usd_minor\x18\x03 \x01(\x03R\x0esalaryUsdMinor\"\xc6\x02\n" + + "\x1dSettleSalaryWithdrawalRequest\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(\n" + + "\x10operator_user_id\x18\x05 \x01(\x03R\x0eoperatorUserId\x12\x16\n" + + "\x06reason\x18\x06 \x01(\tR\x06reason\x12\x19\n" + + "\bapp_code\x18\a \x01(\tR\aappCode\x12:\n" + + "\x19withdrawal_application_id\x18\b \x01(\tR\x17withdrawalApplicationId\"\xaa\x01\n" + + "\x1eSettleSalaryWithdrawalResponse\x12%\n" + + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x127\n" + + "\abalance\x18\x02 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\x12(\n" + + "\x10salary_usd_minor\x18\x03 \x01(\x03R\x0esalaryUsdMinor\"\xc7\x02\n" + + "\x1eReleaseSalaryWithdrawalRequest\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(\n" + + "\x10operator_user_id\x18\x05 \x01(\x03R\x0eoperatorUserId\x12\x16\n" + + "\x06reason\x18\x06 \x01(\tR\x06reason\x12\x19\n" + + "\bapp_code\x18\a \x01(\tR\aappCode\x12:\n" + + "\x19withdrawal_application_id\x18\b \x01(\tR\x17withdrawalApplicationId\"\xab\x01\n" + + "\x1fReleaseSalaryWithdrawalResponse\x12%\n" + + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x127\n" + + "\abalance\x18\x02 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\x12(\n" + + "\x10salary_usd_minor\x18\x03 \x01(\x03R\x0esalaryUsdMinor\"\x90\x03\n" + + "\x1cFreezePointWithdrawalRequest\x12\x1d\n" + + "\n" + + "command_id\x18\x01 \x01(\tR\tcommandId\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1d\n" + + "\n" + + "asset_type\x18\x03 \x01(\tR\tassetType\x12,\n" + + "\x12gross_point_amount\x18\x04 \x01(\x03R\x10grossPointAmount\x12(\n" + + "\x10fee_point_amount\x18\x05 \x01(\x03R\x0efeePointAmount\x12(\n" + + "\x10net_point_amount\x18\x06 \x01(\x03R\x0enetPointAmount\x12$\n" + + "\x0epoints_per_usd\x18\a \x01(\x03R\fpointsPerUsd\x12\x17\n" + + "\afee_bps\x18\b \x01(\x05R\x06feeBps\x12\x16\n" + + "\x06reason\x18\t \x01(\tR\x06reason\x12\x19\n" + + "\bapp_code\x18\n" + + " \x01(\tR\aappCode\x12%\n" + + "\x0ewithdrawal_ref\x18\v \x01(\tR\rwithdrawalRef\"\xc0\x02\n" + + "\x1dFreezePointWithdrawalResponse\x12%\n" + + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x127\n" + + "\abalance\x18\x02 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\x12,\n" + + "\x12gross_point_amount\x18\x03 \x01(\x03R\x10grossPointAmount\x12(\n" + + "\x10fee_point_amount\x18\x04 \x01(\x03R\x0efeePointAmount\x12(\n" + + "\x10net_point_amount\x18\x05 \x01(\x03R\x0enetPointAmount\x12$\n" + + "\x0epoints_per_usd\x18\x06 \x01(\x03R\fpointsPerUsd\x12\x17\n" + + "\afee_bps\x18\a \x01(\x05R\x06feeBps\"\xcf\x03\n" + + "\x1cSettlePointWithdrawalRequest\x12\x1d\n" + + "\n" + + "command_id\x18\x01 \x01(\tR\tcommandId\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1d\n" + + "\n" + + "asset_type\x18\x03 \x01(\tR\tassetType\x12,\n" + + "\x12gross_point_amount\x18\x04 \x01(\x03R\x10grossPointAmount\x12(\n" + + "\x10fee_point_amount\x18\x05 \x01(\x03R\x0efeePointAmount\x12(\n" + + "\x10net_point_amount\x18\x06 \x01(\x03R\x0enetPointAmount\x12$\n" + + "\x0epoints_per_usd\x18\a \x01(\x03R\fpointsPerUsd\x12\x17\n" + + "\afee_bps\x18\b \x01(\x05R\x06feeBps\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\x12:\n" + + "\x19withdrawal_application_id\x18\f \x01(\tR\x17withdrawalApplicationId\"\xc0\x02\n" + + "\x1dSettlePointWithdrawalResponse\x12%\n" + + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x127\n" + + "\abalance\x18\x02 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\x12,\n" + + "\x12gross_point_amount\x18\x03 \x01(\x03R\x10grossPointAmount\x12(\n" + + "\x10fee_point_amount\x18\x04 \x01(\x03R\x0efeePointAmount\x12(\n" + + "\x10net_point_amount\x18\x05 \x01(\x03R\x0enetPointAmount\x12$\n" + + "\x0epoints_per_usd\x18\x06 \x01(\x03R\fpointsPerUsd\x12\x17\n" + + "\afee_bps\x18\a \x01(\x05R\x06feeBps\"\xd0\x03\n" + + "\x1dReleasePointWithdrawalRequest\x12\x1d\n" + + "\n" + + "command_id\x18\x01 \x01(\tR\tcommandId\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1d\n" + + "\n" + + "asset_type\x18\x03 \x01(\tR\tassetType\x12,\n" + + "\x12gross_point_amount\x18\x04 \x01(\x03R\x10grossPointAmount\x12(\n" + + "\x10fee_point_amount\x18\x05 \x01(\x03R\x0efeePointAmount\x12(\n" + + "\x10net_point_amount\x18\x06 \x01(\x03R\x0enetPointAmount\x12$\n" + + "\x0epoints_per_usd\x18\a \x01(\x03R\fpointsPerUsd\x12\x17\n" + + "\afee_bps\x18\b \x01(\x05R\x06feeBps\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\x12:\n" + + "\x19withdrawal_application_id\x18\f \x01(\tR\x17withdrawalApplicationId\"\xc1\x02\n" + + "\x1eReleasePointWithdrawalResponse\x12%\n" + + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x127\n" + + "\abalance\x18\x02 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\x12,\n" + + "\x12gross_point_amount\x18\x03 \x01(\x03R\x10grossPointAmount\x12(\n" + + "\x10fee_point_amount\x18\x04 \x01(\x03R\x0efeePointAmount\x12(\n" + + "\x10net_point_amount\x18\x05 \x01(\x03R\x0enetPointAmount\x12$\n" + + "\x0epoints_per_usd\x18\x06 \x01(\x03R\fpointsPerUsd\x12\x17\n" + + "\afee_bps\x18\a \x01(\x05R\x06feeBps\"\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\"\xcb\x03\n" + + "\x15ResourceGroupSnapshot\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x1f\n" + + "\vsnapshot_id\x18\x02 \x01(\tR\n" + + "snapshotId\x12\x17\n" + + "\apin_key\x18\x03 \x01(\tR\x06pinKey\x12&\n" + + "\x0fsource_group_id\x18\x04 \x01(\x03R\rsourceGroupId\x12\x1d\n" + + "\n" + + "version_no\x18\x05 \x01(\x03R\tversionNo\x12#\n" + + "\rsnapshot_hash\x18\x06 \x01(\tR\fsnapshotHash\x124\n" + + "\x05group\x18\a \x01(\v2\x1e.hyapp.wallet.v1.ResourceGroupR\x05group\x12+\n" + + "\x12created_by_user_id\x18\b \x01(\x03R\x0fcreatedByUserId\x12\"\n" + + "\rcreated_at_ms\x18\t \x01(\x03R\vcreatedAtMs\x12:\n" + + "\x1asource_group_updated_at_ms\x18\n" + + " \x01(\x03R\x16sourceGroupUpdatedAtMs\x12.\n" + + "\x13source_content_hash\x18\v \x01(\tR\x11sourceContentHash\"\x9c\x03\n" + + "\x1fPinResourceGroupSnapshotRequest\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\x17\n" + + "\apin_key\x18\x04 \x01(\tR\x06pinKey\x12(\n" + + "\x10operator_user_id\x18\x05 \x01(\x03R\x0eoperatorUserId\x12>\n" + + "\x1cexpected_group_updated_at_ms\x18\x06 \x01(\x03R\x18expectedGroupUpdatedAtMs\x12?\n" + + "\x1cexpected_source_content_hash\x18\a \x01(\tR\x19expectedSourceContentHash\x12.\n" + + "\x13required_region_ids\x18\b \x03(\x03R\x11requiredRegionIds\x120\n" + + "\x14required_all_regions\x18\t \x01(\bR\x12requiredAllRegions\"f\n" + + " PinResourceGroupSnapshotResponse\x12B\n" + + "\bsnapshot\x18\x01 \x01(\v2&.hyapp.wallet.v1.ResourceGroupSnapshotR\bsnapshot\"\xd3\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\x12(\n" + + "\x10cp_relation_type\x18\x17 \x01(\tR\x0ecpRelationType\"\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\"\xb8\x05\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\x12,\n" + + "\x12source_snapshot_id\x18\x0f \x01(\tR\x10sourceSnapshotId\x124\n" + + "\x16resource_snapshot_hash\x18\x10 \x01(\tR\x14resourceSnapshotHash\x12K\n" + + "\x13pinned_gift_configs\x18\x11 \x03(\v2\x1b.hyapp.wallet.v1.GiftConfigR\x11pinnedGiftConfigs\"\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\"\xd7\x04\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\x12\"\n" + + "\rrevoked_at_ms\x18\x0e \x01(\x03R\vrevokedAtMs\x12+\n" + + "\x12revoked_by_user_id\x18\x0f \x01(\x03R\x0frevokedByUserId\x12#\n" + + "\rrevoke_reason\x18\x10 \x01(\tR\frevokeReason\"\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\"\x9c\x01\n" + + "\x15DeleteResourceRequest\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" + + "\x10operator_user_id\x18\x04 \x01(\x03R\x0eoperatorUserId\"\xa4\x01\n" + + "\x1bBatchDeleteResourcesRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12!\n" + + "\fresource_ids\x18\x03 \x03(\x03R\vresourceIds\x12(\n" + + "\x10operator_user_id\x18\x04 \x01(\x03R\x0eoperatorUserId\"W\n" + + "\x1cBatchDeleteResourcesResponse\x127\n" + + "\tresources\x18\x01 \x03(\v2\x19.hyapp.wallet.v1.ResourceR\tresources\"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\"\x80\x01\n" + + "\x18GetResourceGroupResponse\x124\n" + + "\x05group\x18\x01 \x01(\v2\x1e.hyapp.wallet.v1.ResourceGroupR\x05group\x12.\n" + + "\x13source_content_hash\x18\x02 \x01(\tR\x11sourceContentHash\"\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\"\xf8\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\x12(\n" + + "\x10cp_relation_type\x18\x15 \x01(\tR\x0ecpRelationType\"\xc3\x01\n" + + "\x1dBatchCreateGiftConfigsRequest\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.CreateGiftConfigRequestR\x05items\x12(\n" + + "\x10operator_user_id\x18\x04 \x01(\x03R\x0eoperatorUserId\"S\n" + + "\x1eBatchCreateGiftConfigsResponse\x121\n" + + "\x05gifts\x18\x01 \x03(\v2\x1b.hyapp.wallet.v1.GiftConfigR\x05gifts\"\xf8\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\x12(\n" + + "\x10cp_relation_type\x18\x15 \x01(\tR\x0ecpRelationType\"\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\"\x96\x01\n" + + "\x17DeleteGiftConfigRequest\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(\n" + + "\x10operator_user_id\x18\x04 \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\"\xbd\x02\n" + + "\x1fGrantPinnedResourceGroupRequest\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" + + "\vsnapshot_id\x18\x04 \x01(\tR\n" + + "snapshotId\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\x124\n" + + "\x16expected_snapshot_hash\x18\b \x01(\tR\x14expectedSnapshotHash\"\xb3\x01\n" + + "\x1aRevokeResourceGrantRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x19\n" + + "\bgrant_id\x18\x03 \x01(\tR\agrantId\x12\x16\n" + + "\x06reason\x18\x04 \x01(\tR\x06reason\x12(\n" + + "\x10operator_user_id\x18\x05 \x01(\x03R\x0eoperatorUserId\"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\"\xa9\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\x12\x1d\n" + + "\n" + + "coin_price\x18\b \x01(\x03R\tcoinPrice\"\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\"\xa1\b\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\x122\n" + + "\x15provider_amount_minor\x18\x13 \x01(\x03R\x13providerAmountMinor\x12#\n" + + "\rprovider_code\x18\x14 \x01(\tR\fproviderCode\x125\n" + + "\x17user_paid_currency_code\x18\x15 \x01(\tR\x14userPaidCurrencyCode\x123\n" + + "\x16user_paid_amount_micro\x18\x16 \x01(\x03R\x13userPaidAmountMicro\x12,\n" + + "\x12provider_fee_micro\x18\x17 \x01(\x03R\x10providerFeeMicro\x12,\n" + + "\x12provider_tax_micro\x18\x18 \x01(\x03R\x10providerTaxMicro\x12,\n" + + "\x12provider_net_micro\x18\x19 \x01(\x03R\x10providerNetMicro\x12)\n" + + "\x11paid_synced_at_ms\x18\x1a \x01(\x03R\x0epaidSyncedAtMs\"\x93\x03\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\x12\x1d\n" + + "\n" + + "paid_state\x18\r \x01(\tR\tpaidState\"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\"\xc8\x02\n" + + "\x1dGetRechargeBillSummaryRequest\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\"\x85\x01\n" + + "\x19RechargeBillSummaryBucket\x12\x1d\n" + + "\n" + + "bill_count\x18\x01 \x01(\x03R\tbillCount\x12\x1f\n" + + "\vcoin_amount\x18\x02 \x01(\x03R\n" + + "coinAmount\x12(\n" + + "\x10usd_minor_amount\x18\x03 \x01(\x03R\x0eusdMinorAmount\"\xc9\x02\n" + + "\x1eGetRechargeBillSummaryResponse\x12@\n" + + "\x05total\x18\x01 \x01(\v2*.hyapp.wallet.v1.RechargeBillSummaryBucketR\x05total\x12K\n" + + "\vgoogle_play\x18\x02 \x01(\v2*.hyapp.wallet.v1.RechargeBillSummaryBucketR\n" + + "googlePlay\x12K\n" + + "\vthird_party\x18\x03 \x01(\v2*.hyapp.wallet.v1.RechargeBillSummaryBucketR\n" + + "thirdParty\x12K\n" + + "\vcoin_seller\x18\x04 \x01(\v2*.hyapp.wallet.v1.RechargeBillSummaryBucketR\n" + + "coinSeller\"\x8b\x02\n" + + "\x11UserRechargeStats\x12\x17\n" + + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12%\n" + + "\x0erecharge_count\x18\x02 \x01(\x03R\rrechargeCount\x12*\n" + + "\x11total_coin_amount\x18\x03 \x01(\x03R\x0ftotalCoinAmount\x123\n" + + "\x16total_usd_minor_amount\x18\x04 \x01(\x03R\x13totalUsdMinorAmount\x121\n" + + "\x15first_recharged_at_ms\x18\x05 \x01(\x03R\x12firstRechargedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x06 \x01(\x03R\vupdatedAtMs\"w\n" + + " BatchGetUserRechargeStatsRequest\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\"]\n" + + "!BatchGetUserRechargeStatsResponse\x128\n" + + "\x05items\x18\x01 \x03(\v2\".hyapp.wallet.v1.UserRechargeStatsR\x05items\"\x9c\x02\n" + + "\x1eGetRechargeBillOverviewRequest\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" + + "\rrecharge_type\x18\x04 \x01(\tR\frechargeType\x12\x16\n" + + "\x06status\x18\x05 \x01(\tR\x06status\x12\x1e\n" + + "\vstart_at_ms\x18\x06 \x01(\x03R\tstartAtMs\x12\x1a\n" + + "\tend_at_ms\x18\a \x01(\x03R\aendAtMs\x12*\n" + + "\x11tz_offset_minutes\x18\b \x01(\x05R\x0ftzOffsetMinutes\"\xd9\x02\n" + + "\x17RechargeBillDailyBucket\x12\x12\n" + + "\x04date\x18\x01 \x01(\tR\x04date\x12(\n" + + "\x10google_usd_minor\x18\x02 \x01(\x03R\x0egoogleUsdMinor\x121\n" + + "\x15third_party_usd_minor\x18\x03 \x01(\x03R\x12thirdPartyUsdMinor\x121\n" + + "\x15coin_seller_usd_minor\x18\x04 \x01(\x03R\x12coinSellerUsdMinor\x12,\n" + + "\x12google_coin_amount\x18\x05 \x01(\x03R\x10googleCoinAmount\x125\n" + + "\x17third_party_coin_amount\x18\x06 \x01(\x03R\x14thirdPartyCoinAmount\x125\n" + + "\x17coin_seller_coin_amount\x18\a \x01(\x03R\x14coinSellerCoinAmount\"\x80\x01\n" + + "\x18RechargeBillRegionBucket\x12\x1b\n" + + "\tregion_id\x18\x01 \x01(\x03R\bregionId\x12\x1d\n" + + "\n" + + "bill_count\x18\x02 \x01(\x03R\tbillCount\x12(\n" + + "\x10usd_minor_amount\x18\x03 \x01(\x03R\x0eusdMinorAmount\"\xc0\x02\n" + + "\x1bRechargeBillGooglePaidStats\x12*\n" + + "\x11google_bill_count\x18\x01 \x01(\x03R\x0fgoogleBillCount\x12!\n" + + "\fsynced_count\x18\x02 \x01(\x03R\vsyncedCount\x12%\n" + + "\x0eunsynced_count\x18\x03 \x01(\x03R\runsyncedCount\x12*\n" + + "\x11covered_usd_minor\x18\x04 \x01(\x03R\x0fcoveredUsdMinor\x12)\n" + + "\x11est_fee_usd_minor\x18\x05 \x01(\x03R\x0eestFeeUsdMinor\x12)\n" + + "\x11est_tax_usd_minor\x18\x06 \x01(\x03R\x0eestTaxUsdMinor\x12)\n" + + "\x11est_net_usd_minor\x18\a \x01(\x03R\x0eestNetUsdMinor\"v\n" + + "\x1fRechargeBillSalaryTransferStats\x12%\n" + + "\x0etransfer_count\x18\x01 \x01(\x03R\rtransferCount\x12,\n" + + "\x12transfer_usd_minor\x18\x02 \x01(\x03R\x10transferUsdMinor\"\xd0\x02\n" + + "\x1fGetRechargeBillOverviewResponse\x12>\n" + + "\x05daily\x18\x01 \x03(\v2(.hyapp.wallet.v1.RechargeBillDailyBucketR\x05daily\x12C\n" + + "\aregions\x18\x02 \x03(\v2).hyapp.wallet.v1.RechargeBillRegionBucketR\aregions\x12M\n" + + "\vgoogle_paid\x18\x03 \x01(\v2,.hyapp.wallet.v1.RechargeBillGooglePaidStatsR\n" + + "googlePaid\x12Y\n" + + "\x0fsalary_transfer\x18\x04 \x01(\v20.hyapp.wallet.v1.RechargeBillSalaryTransferStatsR\x0esalaryTransfer\"\x86\x01\n" + + "!RefreshGooglePaymentPricesRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12'\n" + + "\x0ftransaction_ids\x18\x03 \x03(\tR\x0etransactionIds\"\xfe\x01\n" + + "\x12GooglePaymentPrice\x12%\n" + + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x12#\n" + + "\rcurrency_code\x18\x02 \x01(\tR\fcurrencyCode\x12*\n" + + "\x11paid_amount_micro\x18\x03 \x01(\x03R\x0fpaidAmountMicro\x12\x1b\n" + + "\ttax_micro\x18\x04 \x01(\x03R\btaxMicro\x12\x1b\n" + + "\tnet_micro\x18\x05 \x01(\x03R\bnetMicro\x12 \n" + + "\fsynced_at_ms\x18\x06 \x01(\x03R\n" + + "syncedAtMs\x12\x14\n" + + "\x05error\x18\a \x01(\tR\x05error\"a\n" + + "\"RefreshGooglePaymentPricesResponse\x12;\n" + + "\x06prices\x18\x01 \x03(\v2#.hyapp.wallet.v1.GooglePaymentPriceR\x06prices\"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\"\xa4\x06\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\x12#\n" + + "\raudience_type\x18\x16 \x01(\tR\faudienceType\x12\x1f\n" + + "\vapp_visible\x18\x17 \x01(\bR\n" + + "appVisible\"\xce\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\x12#\n" + + "\raudience_type\x18\x06 \x01(\tR\faudienceType\"x\n" + + "\x1cListRechargeProductsResponse\x12<\n" + + "\bproducts\x18\x01 \x03(\v2 .hyapp.wallet.v1.RechargeProductR\bproducts\x12\x1a\n" + + "\bchannels\x18\x02 \x03(\tR\bchannels\"\x9c\x03\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\x12\x1d\n" + + "\n" + + "country_id\x18\f \x01(\x03R\tcountryId\"\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\"\x9d\x02\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\x12#\n" + + "\raudience_type\x18\t \x01(\tR\faudienceType\"w\n" + + "!ListAdminRechargeProductsResponse\x12<\n" + + "\bproducts\x18\x01 \x03(\v2 .hyapp.wallet.v1.RechargeProductR\bproducts\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\xbb\x03\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\x12#\n" + + "\raudience_type\x18\v \x01(\tR\faudienceType\x12$\n" + + "\vapp_visible\x18\f \x01(\bH\x00R\n" + + "appVisible\x88\x01\x01B\x0e\n" + + "\f_app_visible\"\xda\x03\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\x12#\n" + + "\raudience_type\x18\f \x01(\tR\faudienceType\x12$\n" + + "\vapp_visible\x18\r \x01(\bH\x00R\n" + + "appVisible\x88\x01\x01B\x0e\n" + + "\f_app_visible\"\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\"\xa6\x04\n" + + "\x17ThirdPartyPaymentMethod\x12\x1b\n" + + "\tmethod_id\x18\x01 \x01(\x03R\bmethodId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12#\n" + + "\rprovider_code\x18\x03 \x01(\tR\fproviderCode\x12#\n" + + "\rprovider_name\x18\x04 \x01(\tR\fproviderName\x12!\n" + + "\fcountry_code\x18\x05 \x01(\tR\vcountryCode\x12!\n" + + "\fcountry_name\x18\x06 \x01(\tR\vcountryName\x12#\n" + + "\rcurrency_code\x18\a \x01(\tR\fcurrencyCode\x12\x17\n" + + "\apay_way\x18\b \x01(\tR\x06payWay\x12\x19\n" + + "\bpay_type\x18\t \x01(\tR\apayType\x12\x1f\n" + + "\vmethod_name\x18\n" + + " \x01(\tR\n" + + "methodName\x12\x19\n" + + "\blogo_url\x18\v \x01(\tR\alogoUrl\x12\x16\n" + + "\x06status\x18\f \x01(\tR\x06status\x12/\n" + + "\x14usd_to_currency_rate\x18\r \x01(\tR\x11usdToCurrencyRate\x12\x1d\n" + + "\n" + + "sort_order\x18\x0e \x01(\x05R\tsortOrder\x12\"\n" + + "\rcreated_at_ms\x18\x0f \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x10 \x01(\x03R\vupdatedAtMs\"\xfa\x01\n" + + "\x18ThirdPartyPaymentChannel\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12#\n" + + "\rprovider_code\x18\x02 \x01(\tR\fproviderCode\x12#\n" + + "\rprovider_name\x18\x03 \x01(\tR\fproviderName\x12\x16\n" + + "\x06status\x18\x04 \x01(\tR\x06status\x12\x1d\n" + + "\n" + + "sort_order\x18\x05 \x01(\x05R\tsortOrder\x12B\n" + + "\amethods\x18\x06 \x03(\v2(.hyapp.wallet.v1.ThirdPartyPaymentMethodR\amethods\"\xd7\x01\n" + + "$ListThirdPartyPaymentChannelsRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12#\n" + + "\rprovider_code\x18\x03 \x01(\tR\fproviderCode\x12\x16\n" + + "\x06status\x18\x04 \x01(\tR\x06status\x128\n" + + "\x18include_disabled_methods\x18\x05 \x01(\bR\x16includeDisabledMethods\"n\n" + + "%ListThirdPartyPaymentChannelsResponse\x12E\n" + + "\bchannels\x18\x01 \x03(\v2).hyapp.wallet.v1.ThirdPartyPaymentChannelR\bchannels\"\xc4\x01\n" + + "'SetThirdPartyPaymentMethodStatusRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1b\n" + + "\tmethod_id\x18\x03 \x01(\x03R\bmethodId\x12\x18\n" + + "\aenabled\x18\x04 \x01(\bR\aenabled\x12(\n" + + "\x10operator_user_id\x18\x05 \x01(\x03R\x0eoperatorUserId\"c\n" + + "\x1fThirdPartyPaymentMethodResponse\x12@\n" + + "\x06method\x18\x01 \x01(\v2(.hyapp.wallet.v1.ThirdPartyPaymentMethodR\x06method\"\xd6\x01\n" + + "\"UpdateThirdPartyPaymentRateRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1b\n" + + "\tmethod_id\x18\x03 \x01(\x03R\bmethodId\x12/\n" + + "\x14usd_to_currency_rate\x18\x04 \x01(\tR\x11usdToCurrencyRate\x12(\n" + + "\x10operator_user_id\x18\x05 \x01(\x03R\x0eoperatorUserId\"\x98\x01\n" + + " ThirdPartyPaymentMethodSyncIssue\x12!\n" + + "\fcountry_code\x18\x01 \x01(\tR\vcountryCode\x12#\n" + + "\rcurrency_code\x18\x02 \x01(\tR\fcurrencyCode\x12\x12\n" + + "\x04code\x18\x03 \x01(\tR\x04code\x12\x18\n" + + "\amessage\x18\x04 \x01(\tR\amessage\"\xae\x01\n" + + "#SyncThirdPartyPaymentMethodsRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12#\n" + + "\rprovider_code\x18\x03 \x01(\tR\fproviderCode\x12(\n" + + "\x10operator_user_id\x18\x04 \x01(\x03R\x0eoperatorUserId\"\xed\x02\n" + + "$SyncThirdPartyPaymentMethodsResponse\x12#\n" + + "\rprovider_code\x18\x01 \x01(\tR\fproviderCode\x122\n" + + "\x15scanned_country_count\x18\x02 \x01(\x05R\x13scannedCountryCount\x122\n" + + "\x15fetched_country_count\x18\x03 \x01(\x05R\x13fetchedCountryCount\x12#\n" + + "\rcreated_count\x18\x04 \x01(\x05R\fcreatedCount\x12#\n" + + "\rupdated_count\x18\x05 \x01(\x05R\fupdatedCount\x12#\n" + + "\rskipped_count\x18\x06 \x01(\x05R\fskippedCount\x12I\n" + + "\x06issues\x18\a \x03(\v21.hyapp.wallet.v1.ThirdPartyPaymentMethodSyncIssueR\x06issues\"\xf9\x01\n" + + "\x18H5RechargeOptionsRequest\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(\n" + + "\x10target_region_id\x18\x04 \x01(\x03R\x0etargetRegionId\x12.\n" + + "\x13target_country_code\x18\x05 \x01(\tR\x11targetCountryCode\x12#\n" + + "\raudience_type\x18\x06 \x01(\tR\faudienceType\"\x88\x02\n" + + "\x19H5RechargeOptionsResponse\x12<\n" + + "\bproducts\x18\x01 \x03(\v2 .hyapp.wallet.v1.RechargeProductR\bproducts\x12Q\n" + + "\x0fpayment_methods\x18\x02 \x03(\v2(.hyapp.wallet.v1.ThirdPartyPaymentMethodR\x0epaymentMethods\x12,\n" + + "\x12usdt_trc20_enabled\x18\x03 \x01(\bR\x10usdtTrc20Enabled\x12,\n" + + "\x12usdt_trc20_address\x18\x04 \x01(\tR\x10usdtTrc20Address\"\x8e\b\n" + + "\x15ExternalRechargeOrder\x12\x19\n" + + "\border_id\x18\x01 \x01(\tR\aorderId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12$\n" + + "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x12(\n" + + "\x10target_region_id\x18\x04 \x01(\x03R\x0etargetRegionId\x12.\n" + + "\x13target_country_code\x18\x05 \x01(\tR\x11targetCountryCode\x12#\n" + + "\raudience_type\x18\x06 \x01(\tR\faudienceType\x12\x1d\n" + + "\n" + + "product_id\x18\a \x01(\x03R\tproductId\x12!\n" + + "\fproduct_name\x18\b \x01(\tR\vproductName\x12\x1f\n" + + "\vcoin_amount\x18\t \x01(\x03R\n" + + "coinAmount\x12(\n" + + "\x10usd_minor_amount\x18\n" + + " \x01(\x03R\x0eusdMinorAmount\x12#\n" + + "\rprovider_code\x18\v \x01(\tR\fproviderCode\x12*\n" + + "\x11payment_method_id\x18\f \x01(\x03R\x0fpaymentMethodId\x12!\n" + + "\fcountry_code\x18\r \x01(\tR\vcountryCode\x12#\n" + + "\rcurrency_code\x18\x0e \x01(\tR\fcurrencyCode\x122\n" + + "\x15provider_amount_minor\x18\x0f \x01(\x03R\x13providerAmountMinor\x12\x17\n" + + "\apay_way\x18\x10 \x01(\tR\x06payWay\x12\x19\n" + + "\bpay_type\x18\x11 \x01(\tR\apayType\x12\x17\n" + + "\apay_url\x18\x12 \x01(\tR\x06payUrl\x12*\n" + + "\x11provider_order_id\x18\x13 \x01(\tR\x0fproviderOrderId\x12\x17\n" + + "\atx_hash\x18\x14 \x01(\tR\x06txHash\x12'\n" + + "\x0freceive_address\x18\x15 \x01(\tR\x0ereceiveAddress\x12\x16\n" + + "\x06status\x18\x16 \x01(\tR\x06status\x12%\n" + + "\x0efailure_reason\x18\x17 \x01(\tR\rfailureReason\x12%\n" + + "\x0etransaction_id\x18\x18 \x01(\tR\rtransactionId\x12\"\n" + + "\rcreated_at_ms\x18\x19 \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x1a \x01(\x03R\vupdatedAtMs\x12+\n" + + "\x11idempotent_replay\x18\x1b \x01(\bR\x10idempotentReplay\x12*\n" + + "\x11target_country_id\x18\x1c \x01(\x03R\x0ftargetCountryId\"\x94\x05\n" + + "\x1cCreateH5RechargeOrderRequest\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" + + "\x0etarget_user_id\x18\x04 \x01(\x03R\ftargetUserId\x12(\n" + + "\x10target_region_id\x18\x05 \x01(\x03R\x0etargetRegionId\x12.\n" + + "\x13target_country_code\x18\x06 \x01(\tR\x11targetCountryCode\x12#\n" + + "\raudience_type\x18\a \x01(\tR\faudienceType\x12\x1d\n" + + "\n" + + "product_id\x18\b \x01(\x03R\tproductId\x12#\n" + + "\rprovider_code\x18\t \x01(\tR\fproviderCode\x12*\n" + + "\x11payment_method_id\x18\n" + + " \x01(\x03R\x0fpaymentMethodId\x12\x1d\n" + + "\n" + + "return_url\x18\v \x01(\tR\treturnUrl\x12\x1d\n" + + "\n" + + "notify_url\x18\f \x01(\tR\tnotifyUrl\x12\x1b\n" + + "\tclient_ip\x18\r \x01(\tR\bclientIp\x12\x1a\n" + + "\blanguage\x18\x0e \x01(\tR\blanguage\x12\x1d\n" + + "\n" + + "payer_name\x18\x0f \x01(\tR\tpayerName\x12#\n" + + "\rpayer_account\x18\x10 \x01(\tR\fpayerAccount\x12\x1f\n" + + "\vpayer_email\x18\x11 \x01(\tR\n" + + "payerEmail\x12*\n" + + "\x11target_country_id\x18\x12 \x01(\x03R\x0ftargetCountryId\"\xf6\x03\n" + + "#CreateTemporaryRechargeOrderRequest\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\x1f\n" + + "\vcoin_amount\x18\x04 \x01(\x03R\n" + + "coinAmount\x12(\n" + + "\x10usd_minor_amount\x18\x05 \x01(\x03R\x0eusdMinorAmount\x12#\n" + + "\rprovider_code\x18\x06 \x01(\tR\fproviderCode\x12*\n" + + "\x11payment_method_id\x18\a \x01(\x03R\x0fpaymentMethodId\x12\x1d\n" + + "\n" + + "return_url\x18\b \x01(\tR\treturnUrl\x12\x1d\n" + + "\n" + + "notify_url\x18\t \x01(\tR\tnotifyUrl\x12\x1b\n" + + "\tclient_ip\x18\n" + + " \x01(\tR\bclientIp\x12\x1a\n" + + "\blanguage\x18\v \x01(\tR\blanguage\x12\x1d\n" + + "\n" + + "payer_name\x18\f \x01(\tR\tpayerName\x12#\n" + + "\rpayer_account\x18\r \x01(\tR\fpayerAccount\x12\x1f\n" + + "\vpayer_email\x18\x0e \x01(\tR\n" + + "payerEmail\"w\n" + + " GetTemporaryRechargeOrderRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x19\n" + + "\border_id\x18\x03 \x01(\tR\aorderId\"\xe6\x01\n" + + "\"ListTemporaryRechargeOrdersRequest\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#\n" + + "\rprovider_code\x18\x04 \x01(\tR\fproviderCode\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\"{\n" + + "#ListTemporaryRechargeOrdersResponse\x12>\n" + + "\x06orders\x18\x01 \x03(\v2&.hyapp.wallet.v1.ExternalRechargeOrderR\x06orders\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\xaf\x01\n" + + "\x19SubmitH5RechargeTxRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x19\n" + + "\border_id\x18\x03 \x01(\tR\aorderId\x12$\n" + + "\x0etarget_user_id\x18\x04 \x01(\x03R\ftargetUserId\x12\x17\n" + + "\atx_hash\x18\x05 \x01(\tR\x06txHash\"\x96\x01\n" + + "\x19GetH5RechargeOrderRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x19\n" + + "\border_id\x18\x03 \x01(\tR\aorderId\x12$\n" + + "\x0etarget_user_id\x18\x04 \x01(\x03R\ftargetUserId\"W\n" + + "\x17H5RechargeOrderResponse\x12<\n" + + "\x05order\x18\x01 \x01(\v2&.hyapp.wallet.v1.ExternalRechargeOrderR\x05order\"\x8a\x04\n" + + "&VerifyCoinSellerRechargeReceiptRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12#\n" + + "\rprovider_code\x18\x03 \x01(\tR\fproviderCode\x12*\n" + + "\x11external_order_no\x18\x04 \x01(\tR\x0fexternalOrderNo\x12\x14\n" + + "\x05chain\x18\x05 \x01(\tR\x05chain\x12(\n" + + "\x10usd_minor_amount\x18\x06 \x01(\x03R\x0eusdMinorAmount\x12\"\n" + + "\rorder_date_ms\x18\a \x01(\x03R\vorderDateMs\x122\n" + + "\x15provider_country_code\x18\b \x01(\tR\x13providerCountryCode\x124\n" + + "\x16provider_currency_code\x18\t \x01(\tR\x14providerCurrencyCode\x12*\n" + + "\x11provider_pay_type\x18\n" + + " \x01(\tR\x0fproviderPayType\x122\n" + + "\x15provider_amount_minor\x18\v \x01(\x03R\x13providerAmountMinor\x12'\n" + + "\x0freceive_address\x18\f \x01(\tR\x0ereceiveAddress\"\xda\x03\n" + + "'VerifyCoinSellerRechargeReceiptResponse\x12\x1a\n" + + "\bverified\x18\x01 \x01(\bR\bverified\x12#\n" + + "\rprovider_code\x18\x02 \x01(\tR\fproviderCode\x12*\n" + + "\x11external_order_no\x18\x03 \x01(\tR\x0fexternalOrderNo\x12*\n" + + "\x11provider_order_id\x18\x04 \x01(\tR\x0fproviderOrderId\x12\x16\n" + + "\x06status\x18\x05 \x01(\tR\x06status\x12#\n" + + "\rcurrency_code\x18\x06 \x01(\tR\fcurrencyCode\x122\n" + + "\x15provider_amount_minor\x18\a \x01(\x03R\x13providerAmountMinor\x12\x19\n" + + "\braw_json\x18\b \x01(\tR\arawJson\x12\x14\n" + + "\x05chain\x18\t \x01(\tR\x05chain\x12'\n" + + "\x0freceive_address\x18\n" + + " \x01(\tR\x0ereceiveAddress\x12$\n" + + "\x0everified_at_ms\x18\v \x01(\x03R\fverifiedAtMs\x12%\n" + + "\x0efailure_reason\x18\f \x01(\tR\rfailureReason\"\x9f\x01\n" + + "\x1aHandleMifapayNotifyRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1f\n" + + "\vmer_account\x18\x03 \x01(\tR\n" + + "merAccount\x12\x12\n" + + "\x04data\x18\x04 \x01(\tR\x04data\x12\x12\n" + + "\x04sign\x18\x05 \x01(\tR\x04sign\"y\n" + + "\x1bHandleMifapayNotifyResponse\x12\x1a\n" + + "\baccepted\x18\x01 \x01(\bR\baccepted\x12#\n" + + "\rresponse_text\x18\x02 \x01(\tR\fresponseText\x12\x19\n" + + "\border_id\x18\x03 \x01(\tR\aorderId\"\xf9\x01\n" + + "\x18HandleV5PayNotifyRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x19\n" + + "\braw_json\x18\x03 \x01(\tR\arawJson\x12M\n" + + "\x06fields\x18\x04 \x03(\v25.hyapp.wallet.v1.HandleV5PayNotifyRequest.FieldsEntryR\x06fields\x1a9\n" + + "\vFieldsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"w\n" + + "\x19HandleV5PayNotifyResponse\x12\x1a\n" + + "\baccepted\x18\x01 \x01(\bR\baccepted\x12#\n" + + "\rresponse_text\x18\x02 \x01(\tR\fresponseText\x12\x19\n" + + "\border_id\x18\x03 \x01(\tR\aorderId\"\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\"\xfa\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\x12,\n" + + "\x12transfer_usd_minor\x18\f \x01(\x03R\x10transferUsdMinor\x124\n" + + "\x16transfer_currency_code\x18\r \x01(\tR\x14transferCurrencyCode\"\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\"\xdb\x04\n" + + "\x10VipProgramConfig\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12!\n" + + "\fprogram_type\x18\x02 \x01(\tR\vprogramType\x12\x1f\n" + + "\vlevel_count\x18\x03 \x01(\x05R\n" + + "levelCount\x127\n" + + "\x18same_level_expiry_policy\x18\x04 \x01(\tR\x15sameLevelExpiryPolicy\x122\n" + + "\x15upgrade_expiry_policy\x18\x05 \x01(\tR\x13upgradeExpiryPolicy\x12:\n" + + "\x19downgrade_purchase_policy\x18\x06 \x01(\tR\x17downgradePurchasePolicy\x12<\n" + + "\x1abenefit_inheritance_policy\x18\a \x01(\tR\x18benefitInheritancePolicy\x12\x1d\n" + + "\n" + + "grant_mode\x18\b \x01(\tR\tgrantMode\x12,\n" + + "\x12trial_card_enabled\x18\t \x01(\bR\x10trialCardEnabled\x12\x16\n" + + "\x06status\x18\n" + + " \x01(\tR\x06status\x12%\n" + + "\x0econfig_version\x18\v \x01(\x03R\rconfigVersion\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\"\xad\x04\n" + + "\n" + + "VipBenefit\x12!\n" + + "\fbenefit_code\x18\x01 \x01(\tR\vbenefitCode\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12!\n" + + "\fbenefit_type\x18\x03 \x01(\tR\vbenefitType\x12!\n" + + "\funlock_level\x18\x04 \x01(\x05R\vunlockLevel\x12\x16\n" + + "\x06status\x18\x05 \x01(\tR\x06status\x12#\n" + + "\rtrial_enabled\x18\x06 \x01(\bR\ftrialEnabled\x12\x1f\n" + + "\vresource_id\x18\a \x01(\x03R\n" + + "resourceId\x12#\n" + + "\rresource_type\x18\b \x01(\tR\fresourceType\x12'\n" + + "\x0fexecution_scope\x18\t \x01(\tR\x0eexecutionScope\x12\x1d\n" + + "\n" + + "auto_equip\x18\n" + + " \x01(\bR\tautoEquip\x12\x1d\n" + + "\n" + + "sort_order\x18\v \x01(\x05R\tsortOrder\x12#\n" + + "\rmetadata_json\x18\f \x01(\tR\fmetadataJson\x12\"\n" + + "\rcreated_at_ms\x18\r \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x0e \x01(\x03R\vupdatedAtMs\x12K\n" + + "\fpresentation\x18\x0f \x01(\v2'.hyapp.wallet.v1.VipBenefitPresentationR\fpresentation\"\xdc\x05\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\x127\n" + + "\bbenefits\x18\x10 \x03(\v2\x1b.hyapp.wallet.v1.VipBenefitR\bbenefits\x12%\n" + + "\x0econfig_version\x18\x11 \x01(\x03R\rconfigVersion\"\x9a\x02\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\x12!\n" + + "\fprogram_type\x18\b \x01(\tR\vprogramType\x12%\n" + + "\x0econfig_version\x18\t \x01(\x03R\rconfigVersion\"\xa5\x04\n" + + "\fVipTrialCard\x12\"\n" + + "\rtrial_card_id\x18\x01 \x01(\tR\vtrialCardId\x12%\n" + + "\x0eentitlement_id\x18\x02 \x01(\tR\rentitlementId\x12\x1f\n" + + "\vresource_id\x18\x03 \x01(\x03R\n" + + "resourceId\x12\x17\n" + + "\auser_id\x18\x04 \x01(\x03R\x06userId\x12\x14\n" + + "\x05level\x18\x05 \x01(\x05R\x05level\x12\x12\n" + + "\x04name\x18\x06 \x01(\tR\x04name\x12\x16\n" + + "\x06status\x18\a \x01(\tR\x06status\x12\x1a\n" + + "\bequipped\x18\b \x01(\bR\bequipped\x12\x1f\n" + + "\vduration_ms\x18\t \x01(\x03R\n" + + "durationMs\x12&\n" + + "\x0feffective_at_ms\x18\n" + + " \x01(\x03R\reffectiveAtMs\x12\"\n" + + "\rexpires_at_ms\x18\v \x01(\x03R\vexpiresAtMs\x122\n" + + "\x15remaining_duration_ms\x18\f \x01(\x03R\x13remainingDurationMs\x12!\n" + + "\fgrant_source\x18\r \x01(\tR\vgrantSource\x12&\n" + + "\x0fsource_grant_id\x18\x0e \x01(\tR\rsourceGrantId\x12\"\n" + + "\rcreated_at_ms\x18\x0f \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x10 \x01(\x03R\vupdatedAtMs\"\xab\x03\n" + + "\x0fVipUserSettings\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x129\n" + + "\x19room_entry_notice_enabled\x18\x03 \x01(\bR\x16roomEntryNoticeEnabled\x12?\n" + + "\x1conline_global_notice_enabled\x18\x04 \x01(\bR\x19onlineGlobalNoticeEnabled\x12\"\n" + + "\rupdated_at_ms\x18\x05 \x01(\x03R\vupdatedAtMs\x129\n" + + "\x19hide_profile_data_enabled\x18\x06 \x01(\bR\x16hideProfileDataEnabled\x12E\n" + + "\x1fanonymous_profile_visit_enabled\x18\a \x01(\bR\x1canonymousProfileVisitEnabled\x12B\n" + + "\x1dleaderboard_invisible_enabled\x18\b \x01(\bR\x1bleaderboardInvisibleEnabled\"\xfd\x03\n" + + "\bVipState\x123\n" + + "\bpaid_vip\x18\x01 \x01(\v2\x18.hyapp.wallet.v1.UserVipR\apaidVip\x12M\n" + + "\x13equipped_trial_card\x18\x02 \x01(\v2\x1d.hyapp.wallet.v1.VipTrialCardR\x11equippedTrialCard\x12=\n" + + "\reffective_vip\x18\x03 \x01(\v2\x18.hyapp.wallet.v1.UserVipR\feffectiveVip\x12)\n" + + "\x10effective_source\x18\x04 \x01(\tR\x0feffectiveSource\x12J\n" + + "\x12effective_benefits\x18\x05 \x03(\v2\x1b.hyapp.wallet.v1.VipBenefitR\x11effectiveBenefits\x12&\n" + + "\x0fevaluated_at_ms\x18\x06 \x01(\x03R\revaluatedAtMs\x12H\n" + + "\x0eprogram_config\x18\a \x01(\v2!.hyapp.wallet.v1.VipProgramConfigR\rprogramConfig\x12E\n" + + "\ruser_settings\x18\b \x01(\v2 .hyapp.wallet.v1.VipUserSettingsR\fuserSettings\"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\"\x86\x02\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\x12/\n" + + "\x05state\x18\x03 \x01(\v2\x19.hyapp.wallet.v1.VipStateR\x05state\x12H\n" + + "\x0eprogram_config\x18\x04 \x01(\v2!.hyapp.wallet.v1.VipProgramConfigR\rprogramConfig\"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\"o\n" + + "\x10GetMyVipResponse\x12*\n" + + "\x03vip\x18\x01 \x01(\v2\x18.hyapp.wallet.v1.UserVipR\x03vip\x12/\n" + + "\x05state\x18\x02 \x01(\v2\x19.hyapp.wallet.v1.VipStateR\x05state\"}\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\"\x86\x03\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\x12/\n" + + "\x05state\x18\a \x01(\v2\x19.hyapp.wallet.v1.VipStateR\x05state\x12@\n" + + "\fcoin_balance\x18\b \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\vcoinBalance\"\xd3\x01\n" + + "\x18DebitCPBreakupFeeRequest\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" + + "\x0frelationship_id\x18\x04 \x01(\tR\x0erelationshipId\x12#\n" + + "\rrelation_type\x18\x05 \x01(\tR\frelationType\x12\x16\n" + + "\x06amount\x18\x06 \x01(\x03R\x06amount\"\xc8\x01\n" + + "\x19DebitCPBreakupFeeResponse\x12%\n" + + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x12\x1d\n" + + "\n" + + "coin_spent\x18\x02 \x01(\x03R\tcoinSpent\x12,\n" + + "\x12coin_balance_after\x18\x03 \x01(\x03R\x10coinBalanceAfter\x127\n" + + "\abalance\x18\x04 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\"\xbc\x01\n" + + "\x15DebitWheelDrawRequest\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\x19\n" + + "\bwheel_id\x18\x04 \x01(\tR\awheelId\x12\x1d\n" + + "\n" + + "draw_count\x18\x05 \x01(\x05R\tdrawCount\x12\x16\n" + + "\x06amount\x18\x06 \x01(\x03R\x06amount\"\xc5\x01\n" + + "\x16DebitWheelDrawResponse\x12%\n" + + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x12\x1d\n" + + "\n" + + "coin_spent\x18\x02 \x01(\x03R\tcoinSpent\x12,\n" + + "\x12coin_balance_after\x18\x03 \x01(\x03R\x10coinBalanceAfter\x127\n" + + "\abalance\x18\x04 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\"\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\"\xff\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\x12/\n" + + "\x05state\x18\x05 \x01(\v2\x19.hyapp.wallet.v1.VipStateR\x05state\"V\n" + + "\x1aGetVipProgramConfigRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\"\xb7\x01\n" + + "\x1bGetVipProgramConfigResponse\x129\n" + + "\x06config\x18\x01 \x01(\v2!.hyapp.wallet.v1.VipProgramConfigR\x06config\x127\n" + + "\bbenefits\x18\x02 \x03(\v2\x1b.hyapp.wallet.v1.VipBenefitR\bbenefits\x12$\n" + + "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\xc3\x01\n" + + "\"UpdateAdminVipProgramConfigRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x129\n" + + "\x06config\x18\x03 \x01(\v2!.hyapp.wallet.v1.VipProgramConfigR\x06config\x12(\n" + + "\x10operator_user_id\x18\x04 \x01(\x03R\x0eoperatorUserId\"\x86\x01\n" + + "#UpdateAdminVipProgramConfigResponse\x129\n" + + "\x06config\x18\x01 \x01(\v2!.hyapp.wallet.v1.VipProgramConfigR\x06config\x12$\n" + + "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xed\x04\n" + + "\x1aUpdateMyVipSettingsRequest\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" + + "\x19room_entry_notice_enabled\x18\x04 \x01(\bH\x00R\x16roomEntryNoticeEnabled\x88\x01\x01\x12D\n" + + "\x1conline_global_notice_enabled\x18\x05 \x01(\bH\x01R\x19onlineGlobalNoticeEnabled\x88\x01\x01\x12>\n" + + "\x19hide_profile_data_enabled\x18\x06 \x01(\bH\x02R\x16hideProfileDataEnabled\x88\x01\x01\x12J\n" + + "\x1fanonymous_profile_visit_enabled\x18\a \x01(\bH\x03R\x1canonymousProfileVisitEnabled\x88\x01\x01\x12G\n" + + "\x1dleaderboard_invisible_enabled\x18\b \x01(\bH\x04R\x1bleaderboardInvisibleEnabled\x88\x01\x01B\x1c\n" + + "\x1a_room_entry_notice_enabledB\x1f\n" + + "\x1d_online_global_notice_enabledB\x1c\n" + + "\x1a_hide_profile_data_enabledB\"\n" + + " _anonymous_profile_visit_enabledB \n" + + "\x1e_leaderboard_invisible_enabled\"\x81\x01\n" + + "\x1bUpdateMyVipSettingsResponse\x12<\n" + + "\bsettings\x18\x01 \x01(\v2 .hyapp.wallet.v1.VipUserSettingsR\bsettings\x12$\n" + + "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xd2\x03\n" + + "\x15VipDailyCoinRebateRun\x12\x15\n" + + "\x06run_id\x18\x01 \x01(\tR\x05runId\x12\x19\n" + + "\btask_day\x18\x02 \x01(\tR\ataskDay\x12 \n" + + "\fday_start_ms\x18\x03 \x01(\x03R\n" + + "dayStartMs\x12\x1c\n" + + "\n" + + "day_end_ms\x18\x04 \x01(\x03R\bdayEndMs\x12%\n" + + "\x0econfig_version\x18\x05 \x01(\x03R\rconfigVersion\x12,\n" + + "\x12level_amounts_json\x18\x06 \x01(\tR\x10levelAmountsJson\x12\x16\n" + + "\x06status\x18\a \x01(\tR\x06status\x12 \n" + + "\flast_user_id\x18\b \x01(\x03R\n" + + "lastUserId\x12#\n" + + "\rscanned_count\x18\t \x01(\x03R\fscannedCount\x12#\n" + + "\rcreated_count\x18\n" + + " \x01(\x03R\fcreatedCount\x12\"\n" + + "\rcreated_at_ms\x18\v \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\f \x01(\x03R\vupdatedAtMs\x12&\n" + + "\x0fcompleted_at_ms\x18\r \x01(\x03R\rcompletedAtMs\"\xe9\x03\n" + + "\x12VipDailyCoinRebate\x12\x1b\n" + + "\trebate_id\x18\x01 \x01(\tR\brebateId\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x19\n" + + "\btask_day\x18\x03 \x01(\tR\ataskDay\x12\x1b\n" + + "\tvip_level\x18\x04 \x01(\x05R\bvipLevel\x12\x19\n" + + "\bvip_name\x18\x05 \x01(\tR\avipName\x12\x1f\n" + + "\vcoin_amount\x18\x06 \x01(\x03R\n" + + "coinAmount\x12\x16\n" + + "\x06status\x18\a \x01(\tR\x06status\x12&\n" + + "\x0favailable_at_ms\x18\b \x01(\x03R\ravailableAtMs\x12\"\n" + + "\rexpires_at_ms\x18\t \x01(\x03R\vexpiresAtMs\x12%\n" + + "\x0econfig_version\x18\n" + + " \x01(\x03R\rconfigVersion\x12\"\n" + + "\rclaimed_at_ms\x18\v \x01(\x03R\vclaimedAtMs\x122\n" + + "\x15wallet_transaction_id\x18\f \x01(\tR\x13walletTransactionId\x12\"\n" + + "\rcreated_at_ms\x18\r \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x0e \x01(\x03R\vupdatedAtMs\"\x9b\x01\n" + + "%ProcessVipDailyCoinRebateBatchRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x19\n" + + "\btask_day\x18\x03 \x01(\tR\ataskDay\x12\x1d\n" + + "\n" + + "batch_size\x18\x04 \x01(\x05R\tbatchSize\"\xed\x01\n" + + "&ProcessVipDailyCoinRebateBatchResponse\x128\n" + + "\x03run\x18\x01 \x01(\v2&.hyapp.wallet.v1.VipDailyCoinRebateRunR\x03run\x12#\n" + + "\rscanned_count\x18\x02 \x01(\x05R\fscannedCount\x12#\n" + + "\rcreated_count\x18\x03 \x01(\x05R\fcreatedCount\x12\x19\n" + + "\bhas_more\x18\x04 \x01(\bR\ahasMore\x12$\n" + + "\x0eserver_time_ms\x18\x05 \x01(\x03R\fserverTimeMs\"z\n" + + "%GetMyCurrentVipDailyCoinRebateRequest\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\"\xa1\x01\n" + + "&GetMyCurrentVipDailyCoinRebateResponse\x12\x14\n" + + "\x05found\x18\x01 \x01(\bR\x05found\x12;\n" + + "\x06rebate\x18\x02 \x01(\v2#.hyapp.wallet.v1.VipDailyCoinRebateR\x06rebate\x12$\n" + + "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\xcc\x01\n" + + "'ListMyVipDailyCoinRebateStatusesRequest\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\x12\n" + + "\x04page\x18\x04 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\x05 \x01(\x05R\bpageSize\x12\x1d\n" + + "\n" + + "rebate_ids\x18\x06 \x03(\tR\trebateIds\"\xa5\x01\n" + + "(ListMyVipDailyCoinRebateStatusesResponse\x12=\n" + + "\arebates\x18\x01 \x03(\v2#.hyapp.wallet.v1.VipDailyCoinRebateR\arebates\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\x12$\n" + + "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\x90\x01\n" + + "\x1eClaimVipDailyCoinRebateRequest\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\x1b\n" + + "\trebate_id\x18\x04 \x01(\tR\brebateId\"\xed\x01\n" + + "\x1fClaimVipDailyCoinRebateResponse\x12;\n" + + "\x06rebate\x18\x01 \x01(\v2#.hyapp.wallet.v1.VipDailyCoinRebateR\x06rebate\x12%\n" + + "\x0etransaction_id\x18\x02 \x01(\tR\rtransactionId\x12@\n" + + "\fcoin_balance\x18\x03 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\vcoinBalance\x12$\n" + + "\x0eserver_time_ms\x18\x04 \x01(\x03R\fserverTimeMs\"\xcc\x02\n" + + "\x18GrantVipTrialCardRequest\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\x1f\n" + + "\vduration_ms\x18\x05 \x01(\x03R\n" + + "durationMs\x12$\n" + + "\vresource_id\x18\x06 \x01(\x03H\x00R\n" + + "resourceId\x88\x01\x01\x12!\n" + + "\fgrant_source\x18\a \x01(\tR\vgrantSource\x12(\n" + + "\x10operator_user_id\x18\b \x01(\x03R\x0eoperatorUserId\x12\x16\n" + + "\x06reason\x18\t \x01(\tR\x06reasonB\x0e\n" + + "\f_resource_id\"\xb0\x01\n" + + "\x19GrantVipTrialCardResponse\x12<\n" + + "\n" + + "trial_card\x18\x01 \x01(\v2\x1d.hyapp.wallet.v1.VipTrialCardR\ttrialCard\x12/\n" + + "\x05state\x18\x02 \x01(\v2\x19.hyapp.wallet.v1.VipStateR\x05state\x12$\n" + + "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\x94\x01\n" + + "\x18EquipVipTrialCardRequest\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" + + "\x0eentitlement_id\x18\x04 \x01(\tR\rentitlementId\"\xb0\x01\n" + + "\x19EquipVipTrialCardResponse\x12<\n" + + "\n" + + "trial_card\x18\x01 \x01(\v2\x1d.hyapp.wallet.v1.VipTrialCardR\ttrialCard\x12/\n" + + "\x05state\x18\x02 \x01(\v2\x19.hyapp.wallet.v1.VipStateR\x05state\x12$\n" + + "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"o\n" + + "\x1aUnequipVipTrialCardRequest\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\"\x94\x01\n" + + "\x1bUnequipVipTrialCardResponse\x12\x1e\n" + + "\n" + + "unequipped\x18\x01 \x01(\bR\n" + + "unequipped\x12/\n" + + "\x05state\x18\x02 \x01(\v2\x19.hyapp.wallet.v1.VipStateR\x05state\x12$\n" + + "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\x8e\x01\n" + + "\x16CheckVipBenefitRequest\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" + + "\fbenefit_code\x18\x04 \x01(\tR\vbenefitCode\"\xe8\x01\n" + + "\x17CheckVipBenefitResponse\x12\x18\n" + + "\aallowed\x18\x01 \x01(\bR\aallowed\x125\n" + + "\abenefit\x18\x02 \x01(\v2\x1b.hyapp.wallet.v1.VipBenefitR\abenefit\x12/\n" + + "\x05state\x18\x03 \x01(\v2\x19.hyapp.wallet.v1.VipStateR\x05state\x12#\n" + + "\rdenial_reason\x18\x04 \x01(\tR\fdenialReason\x12&\n" + + "\x0fevaluated_at_ms\x18\x05 \x01(\x03R\revaluatedAtMs\"\xea\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\x127\n" + + "\bbenefits\x18\t \x03(\v2\x1b.hyapp.wallet.v1.VipBenefitR\bbenefits\"U\n" + + "\x19ListAdminVipLevelsRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\"\xbf\x01\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\x12H\n" + + "\x0eprogram_config\x18\x03 \x01(\v2!.hyapp.wallet.v1.VipProgramConfigR\rprogramConfig\"\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\"\xc1\x01\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\x12H\n" + + "\x0eprogram_config\x18\x03 \x01(\v2!.hyapp.wallet.v1.VipProgramConfigR\rprogramConfig\"\xa8\x02\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\x12*\n" + + "\x11reward_asset_type\x18\t \x01(\tR\x0frewardAssetType\"\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\"\xdd\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\x12\x1d\n" + + "\n" + + "country_id\x18\v \x01(\x03R\tcountryId\"\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\"\xb4\x02\n" + + "\x18CreditWheelRewardRequest\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\x19\n" + + "\bwheel_id\x18\x06 \x01(\tR\awheelId\x12(\n" + + "\x10selected_tier_id\x18\a \x01(\tR\x0eselectedTierId\x12\x16\n" + + "\x06reason\x18\b \x01(\tR\x06reason\x12*\n" + + "\x11visible_region_id\x18\t \x01(\x03R\x0fvisibleRegionId\"\xb7\x01\n" + + "\x19CreditWheelRewardResponse\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\"\xe7\x02\n" + + "!CreditInviteActivityRewardRequest\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\x19\n" + + "\bclaim_id\x18\x05 \x01(\tR\aclaimId\x12\x1f\n" + + "\vreward_type\x18\x06 \x01(\tR\n" + + "rewardType\x12\x17\n" + + "\atier_id\x18\a \x01(\x03R\x06tierId\x12\x1b\n" + + "\ttier_code\x18\b \x01(\tR\btierCode\x12\x1b\n" + + "\tcycle_key\x18\t \x01(\tR\bcycleKey\x12#\n" + + "\rreached_value\x18\n" + + " \x01(\x03R\freachedValue\x12\x16\n" + + "\x06reason\x18\v \x01(\tR\x06reason\"\xc0\x01\n" + + "\"CreditInviteActivityRewardResponse\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\"\xcb\x02\n" + + " CreditAgencyOpeningRewardRequest\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" + + "\x0eapplication_id\x18\x05 \x01(\tR\rapplicationId\x12\x19\n" + + "\bcycle_id\x18\x06 \x01(\tR\acycleId\x12\x1b\n" + + "\tagency_id\x18\a \x01(\x03R\bagencyId\x12\x17\n" + + "\arank_no\x18\b \x01(\x05R\x06rankNo\x12\x1f\n" + + "\vscore_coins\x18\t \x01(\x03R\n" + + "scoreCoins\x12\x16\n" + + "\x06reason\x18\n" + + " \x01(\tR\x06reason\"\xbf\x01\n" + + "!CreditAgencyOpeningRewardResponse\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\"\xc3\x02\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\x12!\n" + + "\ftrigger_mode\x18\a \x01(\tR\vtriggerMode\x12\x1b\n" + + "\tcycle_key\x18\b \x01(\tR\bcycleKey\x12\x19\n" + + "\buser_ids\x18\t \x03(\x03R\auserIds\x12'\n" + + "\x0fsettlement_role\x18\n" + + " \x01(\tR\x0esettlementRole\"\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\ahasMore\"\xae\x04\n" + + "\x19ResourceShopPurchaseOrder\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x19\n" + + "\border_id\x18\x02 \x01(\tR\aorderId\x12\x1d\n" + + "\n" + + "command_id\x18\x03 \x01(\tR\tcommandId\x12\x17\n" + + "\auser_id\x18\x04 \x01(\x03R\x06userId\x12 \n" + + "\fshop_item_id\x18\x05 \x01(\x03R\n" + + "shopItemId\x12\x1f\n" + + "\vresource_id\x18\x06 \x01(\x03R\n" + + "resourceId\x125\n" + + "\bresource\x18\a \x01(\v2\x19.hyapp.wallet.v1.ResourceR\bresource\x12#\n" + + "\rduration_days\x18\b \x01(\x05R\fdurationDays\x12\x1d\n" + + "\n" + + "price_coin\x18\t \x01(\x03R\tpriceCoin\x12\x16\n" + + "\x06status\x18\n" + + " \x01(\tR\x06status\x122\n" + + "\x15wallet_transaction_id\x18\v \x01(\tR\x13walletTransactionId\x12*\n" + + "\x11resource_grant_id\x18\f \x01(\tR\x0fresourceGrantId\x12%\n" + + "\x0eentitlement_id\x18\r \x01(\tR\rentitlementId\x12\"\n" + + "\rcreated_at_ms\x18\x0e \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x0f \x01(\x03R\vupdatedAtMs\"\x82\x02\n" + + "%ListResourceShopPurchaseOrdersRequest\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\x16\n" + + "\x06status\x18\x05 \x01(\tR\x06status\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\"\x82\x01\n" + + "&ListResourceShopPurchaseOrdersResponse\x12B\n" + + "\x06orders\x18\x01 \x03(\v2*.hyapp.wallet.v1.ResourceShopPurchaseOrderR\x06orders\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"X\n" + + "\x1cGetGiftCatalogVersionRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\"9\n" + + "\x1dGetGiftCatalogVersionResponse\x12\x18\n" + + "\aversion\x18\x01 \x01(\x03R\aversion\"\x8d\x01\n" + + "\x10HostRevenueStats\x12)\n" + + "\x10diamond_earnings\x18\x01 \x01(\x03R\x0fdiamondEarnings\x12+\n" + + "\x11diamond_exchanged\x18\x02 \x01(\x03R\x10diamondExchanged\x12!\n" + + "\fgift_senders\x18\x03 \x01(\x03R\vgiftSenders\"\xb4\x01\n" + + "\x1aGetHostRevenueStatsRequest\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\x1e\n" + + "\vstart_at_ms\x18\x04 \x01(\x03R\tstartAtMs\x12\x1a\n" + + "\tend_at_ms\x18\x05 \x01(\x03R\aendAtMs\"V\n" + + "\x1bGetHostRevenueStatsResponse\x127\n" + + "\x05stats\x18\x01 \x01(\v2!.hyapp.wallet.v1.HostRevenueStatsR\x05stats\"f\n" + + "\x15AgencyPointShareStats\x12!\n" + + "\fshare_income\x18\x01 \x01(\x03R\vshareIncome\x12*\n" + + "\x11gifted_host_count\x18\x02 \x01(\x03R\x0fgiftedHostCount\"\xc8\x01\n" + + "\x1fGetAgencyPointShareStatsRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12/\n" + + "\x14agency_owner_user_id\x18\x03 \x01(\x03R\x11agencyOwnerUserId\x12\x1e\n" + + "\vstart_at_ms\x18\x04 \x01(\x03R\tstartAtMs\x12\x1a\n" + + "\tend_at_ms\x18\x05 \x01(\x03R\aendAtMs\"`\n" + + " GetAgencyPointShareStatsResponse\x12<\n" + + "\x05stats\x18\x01 \x01(\v2&.hyapp.wallet.v1.AgencyPointShareStatsR\x05stats\"b\n" + + "\x13AgencyHostGiftStats\x12\x1f\n" + + "\vgift_income\x18\x01 \x01(\x03R\n" + + "giftIncome\x12*\n" + + "\x11gifted_host_count\x18\x02 \x01(\x03R\x0fgiftedHostCount\"\xb9\x01\n" + + "\x1dGetAgencyHostGiftStatsRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\"\n" + + "\rhost_user_ids\x18\x03 \x03(\x03R\vhostUserIds\x12\x1e\n" + + "\vstart_at_ms\x18\x04 \x01(\x03R\tstartAtMs\x12\x1a\n" + + "\tend_at_ms\x18\x05 \x01(\x03R\aendAtMs\"\\\n" + + "\x1eGetAgencyHostGiftStatsResponse\x12:\n" + + "\x05stats\x18\x01 \x01(\v2$.hyapp.wallet.v1.AgencyHostGiftStatsR\x05stats\"\xe6\x02\n" + + "\x1fPointWithdrawalCoinSellerConfig\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12$\n" + + "\x0eseller_user_id\x18\x02 \x01(\x03R\fsellerUserId\x12\x1d\n" + + "\n" + + "sort_order\x18\x03 \x01(\x05R\tsortOrder\x12!\n" + + "\fpoint_amount\x18\x04 \x01(\x03R\vpointAmount\x12,\n" + + "\x12seller_coin_amount\x18\x05 \x01(\x03R\x10sellerCoinAmount\x122\n" + + "\x15service_country_codes\x18\x06 \x03(\tR\x13serviceCountryCodes\x12\x16\n" + + "\x06status\x18\a \x01(\tR\x06status\x12\"\n" + + "\rcreated_at_ms\x18\b \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\t \x01(\x03R\vupdatedAtMs\"\xaf\x01\n" + + "%ListPointWithdrawalCoinSellersRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12!\n" + + "\fcountry_code\x18\x03 \x01(\tR\vcountryCode\x12)\n" + + "\x10include_disabled\x18\x04 \x01(\bR\x0fincludeDisabled\"t\n" + + "&ListPointWithdrawalCoinSellersResponse\x12J\n" + + "\asellers\x18\x01 \x03(\v20.hyapp.wallet.v1.PointWithdrawalCoinSellerConfigR\asellers\"\x93\x02\n" + + " TransferPointToCoinSellerRequest\x12\x1d\n" + + "\n" + + "command_id\x18\x01 \x01(\tR\tcommandId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12$\n" + + "\x0esource_user_id\x18\x03 \x01(\x03R\fsourceUserId\x12$\n" + + "\x0eseller_user_id\x18\x04 \x01(\x03R\fsellerUserId\x12!\n" + + "\fpoint_amount\x18\x05 \x01(\x03R\vpointAmount\x12.\n" + + "\x13source_country_code\x18\x06 \x01(\tR\x11sourceCountryCode\x12\x16\n" + + "\x06reason\x18\a \x01(\tR\x06reason\"\xf1\x02\n" + + "!TransferPointToCoinSellerResponse\x12%\n" + + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x12;\n" + + "\x1asource_point_balance_after\x18\x02 \x01(\x03R\x17sourcePointBalanceAfter\x120\n" + + "\x14seller_balance_after\x18\x03 \x01(\x03R\x12sellerBalanceAfter\x12!\n" + + "\fpoint_amount\x18\x04 \x01(\x03R\vpointAmount\x12,\n" + + "\x12seller_coin_amount\x18\x05 \x01(\x03R\x10sellerCoinAmount\x12,\n" + + "\x12ratio_point_amount\x18\x06 \x01(\x03R\x10ratioPointAmount\x127\n" + + "\x18ratio_seller_coin_amount\x18\a \x01(\x03R\x15ratioSellerCoinAmount\"\x8f\x01\n" + + "\x1fGetPointWithdrawalConfigRequest\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\x15\n" + + "\x06now_ms\x18\x04 \x01(\x03R\x05nowMs\"\xd0\x01\n" + + " GetPointWithdrawalConfigResponse\x12\x14\n" + + "\x05found\x18\x01 \x01(\bR\x05found\x12$\n" + + "\x0epoints_per_usd\x18\x02 \x01(\x03R\fpointsPerUsd\x12\x17\n" + + "\afee_bps\x18\x03 \x01(\x05R\x06feeBps\x12%\n" + + "\x0eminimum_points\x18\x04 \x01(\x03R\rminimumPoints\x120\n" + + "\x14policy_instance_code\x18\x05 \x01(\tR\x12policyInstanceCode\"\x98\x02\n" + + "\x15VipBenefitPreviewItem\x12\x1d\n" + + "\n" + + "preview_id\x18\x01 \x01(\tR\tpreviewId\x12\x14\n" + + "\x05title\x18\x02 \x01(\tR\x05title\x12\x1d\n" + + "\n" + + "media_type\x18\x03 \x01(\tR\tmediaType\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" + + "\x10composition_type\x18\a \x01(\tR\x0fcompositionType\x12\x1d\n" + + "\n" + + "sort_order\x18\b \x01(\x05R\tsortOrder\"q\n" + + "\x17VipBenefitNumericReward\x12\x14\n" + + "\x05label\x18\x01 \x01(\tR\x05label\x12\x14\n" + + "\x05value\x18\x02 \x01(\x03R\x05value\x12\x12\n" + + "\x04unit\x18\x03 \x01(\tR\x04unit\x12\x16\n" + + "\x06period\x18\x04 \x01(\tR\x06period\"\xd8\x01\n" + + "\x16VipBenefitPresentation\x12 \n" + + "\vdescription\x18\x01 \x01(\tR\vdescription\x12K\n" + + "\rpreview_items\x18\x02 \x03(\v2&.hyapp.wallet.v1.VipBenefitPreviewItemR\fpreviewItems\x12O\n" + + "\x0enumeric_reward\x18\x03 \x01(\v2(.hyapp.wallet.v1.VipBenefitNumericRewardR\rnumericReward\"\xd7\x01\n" + + "\x19RevokeUserResourceRequest\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" + + "\x0eentitlement_id\x18\x04 \x01(\tR\rentitlementId\x12\x16\n" + + "\x06reason\x18\x05 \x01(\tR\x06reason\x12(\n" + + "\x10operator_user_id\x18\x06 \x01(\x03R\x0eoperatorUserId\"b\n" + + "\x1aRevokeUserResourceResponse\x12D\n" + + "\bresource\x18\x01 \x01(\v2(.hyapp.wallet.v1.UserResourceEntitlementR\bresource2\xf4\x03\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.CronBatchResponse\x12\x91\x01\n" + + "\x1eProcessVipDailyCoinRebateBatch\x126.hyapp.wallet.v1.ProcessVipDailyCoinRebateBatchRequest\x1a7.hyapp.wallet.v1.ProcessVipDailyCoinRebateBatchResponse2\xcfs\n" + + "\rWalletService\x12R\n" + + "\tDebitGift\x12!.hyapp.wallet.v1.DebitGiftRequest\x1a\".hyapp.wallet.v1.DebitGiftResponse\x12^\n" + + "\x0fDebitDirectGift\x12'.hyapp.wallet.v1.DebitDirectGiftRequest\x1a\".hyapp.wallet.v1.DebitGiftResponse\x12a\n" + + "\x0eBatchDebitGift\x12&.hyapp.wallet.v1.BatchDebitGiftRequest\x1a'.hyapp.wallet.v1.BatchDebitGiftResponse\x12\\\n" + + "\x0eDebitRobotGift\x12&.hyapp.wallet.v1.DebitRobotGiftRequest\x1a\".hyapp.wallet.v1.DebitGiftResponse\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\x12p\n" + + "\x13GetHostRevenueStats\x12+.hyapp.wallet.v1.GetHostRevenueStatsRequest\x1a,.hyapp.wallet.v1.GetHostRevenueStatsResponse\x12\x7f\n" + + "\x18GetAgencyPointShareStats\x120.hyapp.wallet.v1.GetAgencyPointShareStatsRequest\x1a1.hyapp.wallet.v1.GetAgencyPointShareStatsResponse\x12y\n" + + "\x16GetAgencyHostGiftStats\x12..hyapp.wallet.v1.GetAgencyHostGiftStatsRequest\x1a/.hyapp.wallet.v1.GetAgencyHostGiftStatsResponse\x12y\n" + + "\x16GetTeamHostSalaryStats\x12..hyapp.wallet.v1.GetTeamHostSalaryStatsRequest\x1a/.hyapp.wallet.v1.GetTeamHostSalaryStatsResponse\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\x91\x01\n" + + "\x1eTransferCoinSellerStockToChild\x126.hyapp.wallet.v1.TransferCoinSellerStockToChildRequest\x1a7.hyapp.wallet.v1.TransferCoinSellerStockToChildResponse\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\x91\x01\n" + + "\x1eListPointWithdrawalCoinSellers\x126.hyapp.wallet.v1.ListPointWithdrawalCoinSellersRequest\x1a7.hyapp.wallet.v1.ListPointWithdrawalCoinSellersResponse\x12\x82\x01\n" + + "\x19TransferPointToCoinSeller\x121.hyapp.wallet.v1.TransferPointToCoinSellerRequest\x1a2.hyapp.wallet.v1.TransferPointToCoinSellerResponse\x12\x7f\n" + + "\x18GetPointWithdrawalConfig\x120.hyapp.wallet.v1.GetPointWithdrawalConfigRequest\x1a1.hyapp.wallet.v1.GetPointWithdrawalConfigResponse\x12y\n" + + "\x16FreezeSalaryWithdrawal\x12..hyapp.wallet.v1.FreezeSalaryWithdrawalRequest\x1a/.hyapp.wallet.v1.FreezeSalaryWithdrawalResponse\x12y\n" + + "\x16SettleSalaryWithdrawal\x12..hyapp.wallet.v1.SettleSalaryWithdrawalRequest\x1a/.hyapp.wallet.v1.SettleSalaryWithdrawalResponse\x12|\n" + + "\x17ReleaseSalaryWithdrawal\x12/.hyapp.wallet.v1.ReleaseSalaryWithdrawalRequest\x1a0.hyapp.wallet.v1.ReleaseSalaryWithdrawalResponse\x12v\n" + + "\x15FreezePointWithdrawal\x12-.hyapp.wallet.v1.FreezePointWithdrawalRequest\x1a..hyapp.wallet.v1.FreezePointWithdrawalResponse\x12v\n" + + "\x15SettlePointWithdrawal\x12-.hyapp.wallet.v1.SettlePointWithdrawalRequest\x1a..hyapp.wallet.v1.SettlePointWithdrawalResponse\x12y\n" + + "\x16ReleasePointWithdrawal\x12..hyapp.wallet.v1.ReleasePointWithdrawalRequest\x1a/.hyapp.wallet.v1.ReleasePointWithdrawalResponse\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\x12[\n" + + "\x0eDeleteResource\x12&.hyapp.wallet.v1.DeleteResourceRequest\x1a!.hyapp.wallet.v1.ResourceResponse\x12s\n" + + "\x14BatchDeleteResources\x12,.hyapp.wallet.v1.BatchDeleteResourcesRequest\x1a-.hyapp.wallet.v1.BatchDeleteResourcesResponse\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\x12\x7f\n" + + "\x18PinResourceGroupSnapshot\x120.hyapp.wallet.v1.PinResourceGroupSnapshotRequest\x1a1.hyapp.wallet.v1.PinResourceGroupSnapshotResponse\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\x12v\n" + + "\x15GetGiftCatalogVersion\x12-.hyapp.wallet.v1.GetGiftCatalogVersionRequest\x1a..hyapp.wallet.v1.GetGiftCatalogVersionResponse\x12a\n" + + "\x10CreateGiftConfig\x12(.hyapp.wallet.v1.CreateGiftConfigRequest\x1a#.hyapp.wallet.v1.GiftConfigResponse\x12y\n" + + "\x16BatchCreateGiftConfigs\x12..hyapp.wallet.v1.BatchCreateGiftConfigsRequest\x1a/.hyapp.wallet.v1.BatchCreateGiftConfigsResponse\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\x12a\n" + + "\x10DeleteGiftConfig\x12(.hyapp.wallet.v1.DeleteGiftConfigRequest\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\x12t\n" + + "\x18GrantPinnedResourceGroup\x120.hyapp.wallet.v1.GrantPinnedResourceGroupRequest\x1a&.hyapp.wallet.v1.ResourceGrantResponse\x12j\n" + + "\x13RevokeResourceGrant\x12+.hyapp.wallet.v1.RevokeResourceGrantRequest\x1a&.hyapp.wallet.v1.ResourceGrantResponse\x12m\n" + + "\x12RevokeUserResource\x12*.hyapp.wallet.v1.RevokeUserResourceRequest\x1a+.hyapp.wallet.v1.RevokeUserResourceResponse\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\x91\x01\n" + + "\x1eListResourceShopPurchaseOrders\x126.hyapp.wallet.v1.ListResourceShopPurchaseOrdersRequest\x1a7.hyapp.wallet.v1.ListResourceShopPurchaseOrdersResponse\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\x12y\n" + + "\x16GetRechargeBillSummary\x12..hyapp.wallet.v1.GetRechargeBillSummaryRequest\x1a/.hyapp.wallet.v1.GetRechargeBillSummaryResponse\x12\x82\x01\n" + + "\x19BatchGetUserRechargeStats\x121.hyapp.wallet.v1.BatchGetUserRechargeStatsRequest\x1a2.hyapp.wallet.v1.BatchGetUserRechargeStatsResponse\x12|\n" + + "\x17GetRechargeBillOverview\x12/.hyapp.wallet.v1.GetRechargeBillOverviewRequest\x1a0.hyapp.wallet.v1.GetRechargeBillOverviewResponse\x12\x85\x01\n" + + "\x1aRefreshGooglePaymentPrices\x122.hyapp.wallet.v1.RefreshGooglePaymentPricesRequest\x1a3.hyapp.wallet.v1.RefreshGooglePaymentPricesResponse\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\x8e\x01\n" + + "\x1dListThirdPartyPaymentChannels\x125.hyapp.wallet.v1.ListThirdPartyPaymentChannelsRequest\x1a6.hyapp.wallet.v1.ListThirdPartyPaymentChannelsResponse\x12\x8e\x01\n" + + " SetThirdPartyPaymentMethodStatus\x128.hyapp.wallet.v1.SetThirdPartyPaymentMethodStatusRequest\x1a0.hyapp.wallet.v1.ThirdPartyPaymentMethodResponse\x12\x84\x01\n" + + "\x1bUpdateThirdPartyPaymentRate\x123.hyapp.wallet.v1.UpdateThirdPartyPaymentRateRequest\x1a0.hyapp.wallet.v1.ThirdPartyPaymentMethodResponse\x12\x8b\x01\n" + + "\x1cSyncThirdPartyPaymentMethods\x124.hyapp.wallet.v1.SyncThirdPartyPaymentMethodsRequest\x1a5.hyapp.wallet.v1.SyncThirdPartyPaymentMethodsResponse\x12n\n" + + "\x15ListH5RechargeOptions\x12).hyapp.wallet.v1.H5RechargeOptionsRequest\x1a*.hyapp.wallet.v1.H5RechargeOptionsResponse\x12p\n" + + "\x15CreateH5RechargeOrder\x12-.hyapp.wallet.v1.CreateH5RechargeOrderRequest\x1a(.hyapp.wallet.v1.H5RechargeOrderResponse\x12~\n" + + "\x1cCreateTemporaryRechargeOrder\x124.hyapp.wallet.v1.CreateTemporaryRechargeOrderRequest\x1a(.hyapp.wallet.v1.H5RechargeOrderResponse\x12x\n" + + "\x19GetTemporaryRechargeOrder\x121.hyapp.wallet.v1.GetTemporaryRechargeOrderRequest\x1a(.hyapp.wallet.v1.H5RechargeOrderResponse\x12\x88\x01\n" + + "\x1bListTemporaryRechargeOrders\x123.hyapp.wallet.v1.ListTemporaryRechargeOrdersRequest\x1a4.hyapp.wallet.v1.ListTemporaryRechargeOrdersResponse\x12j\n" + + "\x12SubmitH5RechargeTx\x12*.hyapp.wallet.v1.SubmitH5RechargeTxRequest\x1a(.hyapp.wallet.v1.H5RechargeOrderResponse\x12j\n" + + "\x12GetH5RechargeOrder\x12*.hyapp.wallet.v1.GetH5RechargeOrderRequest\x1a(.hyapp.wallet.v1.H5RechargeOrderResponse\x12\x94\x01\n" + + "\x1fVerifyCoinSellerRechargeReceipt\x127.hyapp.wallet.v1.VerifyCoinSellerRechargeReceiptRequest\x1a8.hyapp.wallet.v1.VerifyCoinSellerRechargeReceiptResponse\x12p\n" + + "\x13HandleMifapayNotify\x12+.hyapp.wallet.v1.HandleMifapayNotifyRequest\x1a,.hyapp.wallet.v1.HandleMifapayNotifyResponse\x12j\n" + + "\x11HandleV5PayNotify\x12).hyapp.wallet.v1.HandleV5PayNotifyRequest\x1a*.hyapp.wallet.v1.HandleV5PayNotifyResponse\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\x12p\n" + + "\x13GetVipProgramConfig\x12+.hyapp.wallet.v1.GetVipProgramConfigRequest\x1a,.hyapp.wallet.v1.GetVipProgramConfigResponse\x12O\n" + + "\bGetMyVip\x12 .hyapp.wallet.v1.GetMyVipRequest\x1a!.hyapp.wallet.v1.GetMyVipResponse\x12d\n" + + "\x0fCheckVipBenefit\x12'.hyapp.wallet.v1.CheckVipBenefitRequest\x1a(.hyapp.wallet.v1.CheckVipBenefitResponse\x12X\n" + + "\vPurchaseVip\x12#.hyapp.wallet.v1.PurchaseVipRequest\x1a$.hyapp.wallet.v1.PurchaseVipResponse\x12j\n" + + "\x11DebitCPBreakupFee\x12).hyapp.wallet.v1.DebitCPBreakupFeeRequest\x1a*.hyapp.wallet.v1.DebitCPBreakupFeeResponse\x12a\n" + + "\x0eDebitWheelDraw\x12&.hyapp.wallet.v1.DebitWheelDrawRequest\x1a'.hyapp.wallet.v1.DebitWheelDrawResponse\x12O\n" + + "\bGrantVip\x12 .hyapp.wallet.v1.GrantVipRequest\x1a!.hyapp.wallet.v1.GrantVipResponse\x12j\n" + + "\x11GrantVipTrialCard\x12).hyapp.wallet.v1.GrantVipTrialCardRequest\x1a*.hyapp.wallet.v1.GrantVipTrialCardResponse\x12j\n" + + "\x11EquipVipTrialCard\x12).hyapp.wallet.v1.EquipVipTrialCardRequest\x1a*.hyapp.wallet.v1.EquipVipTrialCardResponse\x12p\n" + + "\x13UnequipVipTrialCard\x12+.hyapp.wallet.v1.UnequipVipTrialCardRequest\x1a,.hyapp.wallet.v1.UnequipVipTrialCardResponse\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\x12\x88\x01\n" + + "\x1bUpdateAdminVipProgramConfig\x123.hyapp.wallet.v1.UpdateAdminVipProgramConfigRequest\x1a4.hyapp.wallet.v1.UpdateAdminVipProgramConfigResponse\x12p\n" + + "\x13UpdateMyVipSettings\x12+.hyapp.wallet.v1.UpdateMyVipSettingsRequest\x1a,.hyapp.wallet.v1.UpdateMyVipSettingsResponse\x12\x91\x01\n" + + "\x1eGetMyCurrentVipDailyCoinRebate\x126.hyapp.wallet.v1.GetMyCurrentVipDailyCoinRebateRequest\x1a7.hyapp.wallet.v1.GetMyCurrentVipDailyCoinRebateResponse\x12\x97\x01\n" + + " ListMyVipDailyCoinRebateStatuses\x128.hyapp.wallet.v1.ListMyVipDailyCoinRebateStatusesRequest\x1a9.hyapp.wallet.v1.ListMyVipDailyCoinRebateStatusesResponse\x12|\n" + + "\x17ClaimVipDailyCoinRebate\x12/.hyapp.wallet.v1.ClaimVipDailyCoinRebateRequest\x1a0.hyapp.wallet.v1.ClaimVipDailyCoinRebateResponse\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\x12j\n" + + "\x11CreditWheelReward\x12).hyapp.wallet.v1.CreditWheelRewardRequest\x1a*.hyapp.wallet.v1.CreditWheelRewardResponse\x12\x7f\n" + + "\x18CreditRoomTurnoverReward\x120.hyapp.wallet.v1.CreditRoomTurnoverRewardRequest\x1a1.hyapp.wallet.v1.CreditRoomTurnoverRewardResponse\x12\x85\x01\n" + + "\x1aCreditInviteActivityReward\x122.hyapp.wallet.v1.CreditInviteActivityRewardRequest\x1a3.hyapp.wallet.v1.CreditInviteActivityRewardResponse\x12\x82\x01\n" + + "\x19CreditAgencyOpeningReward\x121.hyapp.wallet.v1.CreditAgencyOpeningRewardRequest\x1a2.hyapp.wallet.v1.CreditAgencyOpeningRewardResponse\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_rawDescOnce sync.Once - file_proto_wallet_v1_wallet_proto_rawDescData = file_proto_wallet_v1_wallet_proto_rawDesc + file_proto_wallet_v1_wallet_proto_rawDescData []byte ) 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(file_proto_wallet_v1_wallet_proto_rawDescData) + 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))) }) return file_proto_wallet_v1_wallet_proto_rawDescData } -var file_proto_wallet_v1_wallet_proto_msgTypes = make([]protoimpl.MessageInfo, 296) +var file_proto_wallet_v1_wallet_proto_msgTypes = make([]protoimpl.MessageInfo, 301) var file_proto_wallet_v1_wallet_proto_goTypes = []any{ (*DebitGiftRequest)(nil), // 0: hyapp.wallet.v1.DebitGiftRequest (*DebitDirectGiftRequest)(nil), // 1: hyapp.wallet.v1.DebitDirectGiftRequest @@ -32237,7 +29340,12 @@ var file_proto_wallet_v1_wallet_proto_goTypes = []any{ (*TransferPointToCoinSellerResponse)(nil), // 292: hyapp.wallet.v1.TransferPointToCoinSellerResponse (*GetPointWithdrawalConfigRequest)(nil), // 293: hyapp.wallet.v1.GetPointWithdrawalConfigRequest (*GetPointWithdrawalConfigResponse)(nil), // 294: hyapp.wallet.v1.GetPointWithdrawalConfigResponse - nil, // 295: hyapp.wallet.v1.HandleV5PayNotifyRequest.FieldsEntry + (*VipBenefitPreviewItem)(nil), // 295: hyapp.wallet.v1.VipBenefitPreviewItem + (*VipBenefitNumericReward)(nil), // 296: hyapp.wallet.v1.VipBenefitNumericReward + (*VipBenefitPresentation)(nil), // 297: hyapp.wallet.v1.VipBenefitPresentation + (*RevokeUserResourceRequest)(nil), // 298: hyapp.wallet.v1.RevokeUserResourceRequest + (*RevokeUserResourceResponse)(nil), // 299: hyapp.wallet.v1.RevokeUserResourceResponse + nil, // 300: hyapp.wallet.v1.HandleV5PayNotifyRequest.FieldsEntry } var file_proto_wallet_v1_wallet_proto_depIdxs = []int32{ 3, // 0: hyapp.wallet.v1.BatchDebitGiftRequest.targets:type_name -> hyapp.wallet.v1.DebitGiftTarget @@ -32322,340 +29430,347 @@ var file_proto_wallet_v1_wallet_proto_depIdxs = []int32{ 157, // 79: hyapp.wallet.v1.H5RechargeOptionsResponse.payment_methods:type_name -> hyapp.wallet.v1.ThirdPartyPaymentMethod 169, // 80: hyapp.wallet.v1.ListTemporaryRechargeOrdersResponse.orders:type_name -> hyapp.wallet.v1.ExternalRechargeOrder 169, // 81: hyapp.wallet.v1.H5RechargeOrderResponse.order:type_name -> hyapp.wallet.v1.ExternalRechargeOrder - 295, // 82: hyapp.wallet.v1.HandleV5PayNotifyRequest.fields:type_name -> hyapp.wallet.v1.HandleV5PayNotifyRequest.FieldsEntry + 300, // 82: hyapp.wallet.v1.HandleV5PayNotifyRequest.fields:type_name -> hyapp.wallet.v1.HandleV5PayNotifyRequest.FieldsEntry 184, // 83: hyapp.wallet.v1.GetDiamondExchangeConfigResponse.rules:type_name -> hyapp.wallet.v1.DiamondExchangeRule 187, // 84: hyapp.wallet.v1.ListWalletTransactionsResponse.transactions:type_name -> hyapp.wallet.v1.WalletTransaction - 190, // 85: hyapp.wallet.v1.VipLevel.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 192, // 86: hyapp.wallet.v1.VipLevel.benefits:type_name -> hyapp.wallet.v1.VipBenefit - 194, // 87: hyapp.wallet.v1.VipState.paid_vip:type_name -> hyapp.wallet.v1.UserVip - 195, // 88: hyapp.wallet.v1.VipState.equipped_trial_card:type_name -> hyapp.wallet.v1.VipTrialCard - 194, // 89: hyapp.wallet.v1.VipState.effective_vip:type_name -> hyapp.wallet.v1.UserVip - 192, // 90: hyapp.wallet.v1.VipState.effective_benefits:type_name -> hyapp.wallet.v1.VipBenefit - 191, // 91: hyapp.wallet.v1.VipState.program_config:type_name -> hyapp.wallet.v1.VipProgramConfig - 196, // 92: hyapp.wallet.v1.VipState.user_settings:type_name -> hyapp.wallet.v1.VipUserSettings - 194, // 93: hyapp.wallet.v1.ListVipPackagesResponse.current_vip:type_name -> hyapp.wallet.v1.UserVip - 193, // 94: hyapp.wallet.v1.ListVipPackagesResponse.packages:type_name -> hyapp.wallet.v1.VipLevel - 197, // 95: hyapp.wallet.v1.ListVipPackagesResponse.state:type_name -> hyapp.wallet.v1.VipState - 191, // 96: hyapp.wallet.v1.ListVipPackagesResponse.program_config:type_name -> hyapp.wallet.v1.VipProgramConfig - 194, // 97: hyapp.wallet.v1.GetMyVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 197, // 98: hyapp.wallet.v1.GetMyVipResponse.state:type_name -> hyapp.wallet.v1.VipState - 194, // 99: hyapp.wallet.v1.PurchaseVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 190, // 100: hyapp.wallet.v1.PurchaseVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 197, // 101: hyapp.wallet.v1.PurchaseVipResponse.state:type_name -> hyapp.wallet.v1.VipState - 8, // 102: hyapp.wallet.v1.DebitCPBreakupFeeResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 8, // 103: hyapp.wallet.v1.DebitWheelDrawResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 194, // 104: hyapp.wallet.v1.GrantVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 190, // 105: hyapp.wallet.v1.GrantVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 197, // 106: hyapp.wallet.v1.GrantVipResponse.state:type_name -> hyapp.wallet.v1.VipState - 191, // 107: hyapp.wallet.v1.GetVipProgramConfigResponse.config:type_name -> hyapp.wallet.v1.VipProgramConfig - 192, // 108: hyapp.wallet.v1.GetVipProgramConfigResponse.benefits:type_name -> hyapp.wallet.v1.VipBenefit - 191, // 109: hyapp.wallet.v1.UpdateAdminVipProgramConfigRequest.config:type_name -> hyapp.wallet.v1.VipProgramConfig - 191, // 110: hyapp.wallet.v1.UpdateAdminVipProgramConfigResponse.config:type_name -> hyapp.wallet.v1.VipProgramConfig - 196, // 111: hyapp.wallet.v1.UpdateMyVipSettingsResponse.settings:type_name -> hyapp.wallet.v1.VipUserSettings - 216, // 112: hyapp.wallet.v1.ProcessVipDailyCoinRebateBatchResponse.run:type_name -> hyapp.wallet.v1.VipDailyCoinRebateRun - 217, // 113: hyapp.wallet.v1.GetMyCurrentVipDailyCoinRebateResponse.rebate:type_name -> hyapp.wallet.v1.VipDailyCoinRebate - 217, // 114: hyapp.wallet.v1.ListMyVipDailyCoinRebateStatusesResponse.rebates:type_name -> hyapp.wallet.v1.VipDailyCoinRebate - 217, // 115: hyapp.wallet.v1.ClaimVipDailyCoinRebateResponse.rebate:type_name -> hyapp.wallet.v1.VipDailyCoinRebate - 8, // 116: hyapp.wallet.v1.ClaimVipDailyCoinRebateResponse.coin_balance:type_name -> hyapp.wallet.v1.AssetBalance - 195, // 117: hyapp.wallet.v1.GrantVipTrialCardResponse.trial_card:type_name -> hyapp.wallet.v1.VipTrialCard - 197, // 118: hyapp.wallet.v1.GrantVipTrialCardResponse.state:type_name -> hyapp.wallet.v1.VipState - 195, // 119: hyapp.wallet.v1.EquipVipTrialCardResponse.trial_card:type_name -> hyapp.wallet.v1.VipTrialCard - 197, // 120: hyapp.wallet.v1.EquipVipTrialCardResponse.state:type_name -> hyapp.wallet.v1.VipState - 197, // 121: hyapp.wallet.v1.UnequipVipTrialCardResponse.state:type_name -> hyapp.wallet.v1.VipState - 192, // 122: hyapp.wallet.v1.CheckVipBenefitResponse.benefit:type_name -> hyapp.wallet.v1.VipBenefit - 197, // 123: hyapp.wallet.v1.CheckVipBenefitResponse.state:type_name -> hyapp.wallet.v1.VipState - 192, // 124: hyapp.wallet.v1.AdminVipLevelInput.benefits:type_name -> hyapp.wallet.v1.VipBenefit - 193, // 125: hyapp.wallet.v1.ListAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel - 191, // 126: hyapp.wallet.v1.ListAdminVipLevelsResponse.program_config:type_name -> hyapp.wallet.v1.VipProgramConfig - 234, // 127: hyapp.wallet.v1.UpdateAdminVipLevelsRequest.levels:type_name -> hyapp.wallet.v1.AdminVipLevelInput - 193, // 128: hyapp.wallet.v1.UpdateAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel - 191, // 129: hyapp.wallet.v1.UpdateAdminVipLevelsResponse.program_config:type_name -> hyapp.wallet.v1.VipProgramConfig - 8, // 130: hyapp.wallet.v1.CreditTaskRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 8, // 131: hyapp.wallet.v1.CreditLuckyGiftRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 8, // 132: hyapp.wallet.v1.CreditWheelRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 8, // 133: hyapp.wallet.v1.CreditRoomTurnoverRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 8, // 134: hyapp.wallet.v1.CreditInviteActivityRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 8, // 135: hyapp.wallet.v1.CreditAgencyOpeningRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 254, // 136: hyapp.wallet.v1.RedPacket.claims:type_name -> hyapp.wallet.v1.RedPacketClaim - 253, // 137: hyapp.wallet.v1.GetRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig - 253, // 138: hyapp.wallet.v1.UpdateRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig - 255, // 139: hyapp.wallet.v1.CreateRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 254, // 140: hyapp.wallet.v1.ClaimRedPacketResponse.claim:type_name -> hyapp.wallet.v1.RedPacketClaim - 255, // 141: hyapp.wallet.v1.ClaimRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 255, // 142: hyapp.wallet.v1.ListRedPacketsResponse.packets:type_name -> hyapp.wallet.v1.RedPacket - 255, // 143: hyapp.wallet.v1.GetRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 255, // 144: hyapp.wallet.v1.RetryRedPacketRefundResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 48, // 145: hyapp.wallet.v1.ResourceShopPurchaseOrder.resource:type_name -> hyapp.wallet.v1.Resource - 274, // 146: hyapp.wallet.v1.ListResourceShopPurchaseOrdersResponse.orders:type_name -> hyapp.wallet.v1.ResourceShopPurchaseOrder - 279, // 147: hyapp.wallet.v1.GetHostRevenueStatsResponse.stats:type_name -> hyapp.wallet.v1.HostRevenueStats - 282, // 148: hyapp.wallet.v1.GetAgencyPointShareStatsResponse.stats:type_name -> hyapp.wallet.v1.AgencyPointShareStats - 285, // 149: hyapp.wallet.v1.GetAgencyHostGiftStatsResponse.stats:type_name -> hyapp.wallet.v1.AgencyHostGiftStats - 288, // 150: hyapp.wallet.v1.ListPointWithdrawalCoinSellersResponse.sellers:type_name -> hyapp.wallet.v1.PointWithdrawalCoinSellerConfig - 272, // 151: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 272, // 152: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 272, // 153: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 218, // 154: hyapp.wallet.v1.WalletCronService.ProcessVipDailyCoinRebateBatch:input_type -> hyapp.wallet.v1.ProcessVipDailyCoinRebateBatchRequest - 0, // 155: hyapp.wallet.v1.WalletService.DebitGift:input_type -> hyapp.wallet.v1.DebitGiftRequest - 1, // 156: hyapp.wallet.v1.WalletService.DebitDirectGift:input_type -> hyapp.wallet.v1.DebitDirectGiftRequest - 4, // 157: hyapp.wallet.v1.WalletService.BatchDebitGift:input_type -> hyapp.wallet.v1.BatchDebitGiftRequest - 7, // 158: hyapp.wallet.v1.WalletService.DebitRobotGift:input_type -> hyapp.wallet.v1.DebitRobotGiftRequest - 9, // 159: hyapp.wallet.v1.WalletService.GetBalances:input_type -> hyapp.wallet.v1.GetBalancesRequest - 13, // 160: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:input_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyRequest - 16, // 161: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:input_type -> hyapp.wallet.v1.GetHostSalaryProgressRequest - 280, // 162: hyapp.wallet.v1.WalletService.GetHostRevenueStats:input_type -> hyapp.wallet.v1.GetHostRevenueStatsRequest - 283, // 163: hyapp.wallet.v1.WalletService.GetAgencyPointShareStats:input_type -> hyapp.wallet.v1.GetAgencyPointShareStatsRequest - 286, // 164: hyapp.wallet.v1.WalletService.GetAgencyHostGiftStats:input_type -> hyapp.wallet.v1.GetAgencyHostGiftStatsRequest - 19, // 165: hyapp.wallet.v1.WalletService.GetTeamHostSalaryStats:input_type -> hyapp.wallet.v1.GetTeamHostSalaryStatsRequest - 21, // 166: hyapp.wallet.v1.WalletService.AdminCreditAsset:input_type -> hyapp.wallet.v1.AdminCreditAssetRequest - 23, // 167: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:input_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockRequest - 25, // 168: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:input_type -> hyapp.wallet.v1.TransferCoinFromSellerRequest - 27, // 169: hyapp.wallet.v1.WalletService.TransferCoinSellerStockToChild:input_type -> hyapp.wallet.v1.TransferCoinSellerStockToChildRequest - 30, // 170: hyapp.wallet.v1.WalletService.ListCoinSellerSalaryExchangeRateTiers:input_type -> hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersRequest - 32, // 171: hyapp.wallet.v1.WalletService.ExchangeSalaryToCoin:input_type -> hyapp.wallet.v1.ExchangeSalaryToCoinRequest - 34, // 172: hyapp.wallet.v1.WalletService.TransferSalaryToCoinSeller:input_type -> hyapp.wallet.v1.TransferSalaryToCoinSellerRequest - 289, // 173: hyapp.wallet.v1.WalletService.ListPointWithdrawalCoinSellers:input_type -> hyapp.wallet.v1.ListPointWithdrawalCoinSellersRequest - 291, // 174: hyapp.wallet.v1.WalletService.TransferPointToCoinSeller:input_type -> hyapp.wallet.v1.TransferPointToCoinSellerRequest - 293, // 175: hyapp.wallet.v1.WalletService.GetPointWithdrawalConfig:input_type -> hyapp.wallet.v1.GetPointWithdrawalConfigRequest - 36, // 176: hyapp.wallet.v1.WalletService.FreezeSalaryWithdrawal:input_type -> hyapp.wallet.v1.FreezeSalaryWithdrawalRequest - 38, // 177: hyapp.wallet.v1.WalletService.SettleSalaryWithdrawal:input_type -> hyapp.wallet.v1.SettleSalaryWithdrawalRequest - 40, // 178: hyapp.wallet.v1.WalletService.ReleaseSalaryWithdrawal:input_type -> hyapp.wallet.v1.ReleaseSalaryWithdrawalRequest - 42, // 179: hyapp.wallet.v1.WalletService.FreezePointWithdrawal:input_type -> hyapp.wallet.v1.FreezePointWithdrawalRequest - 44, // 180: hyapp.wallet.v1.WalletService.SettlePointWithdrawal:input_type -> hyapp.wallet.v1.SettlePointWithdrawalRequest - 46, // 181: hyapp.wallet.v1.WalletService.ReleasePointWithdrawal:input_type -> hyapp.wallet.v1.ReleasePointWithdrawalRequest - 61, // 182: hyapp.wallet.v1.WalletService.ListResources:input_type -> hyapp.wallet.v1.ListResourcesRequest - 63, // 183: hyapp.wallet.v1.WalletService.GetResource:input_type -> hyapp.wallet.v1.GetResourceRequest - 65, // 184: hyapp.wallet.v1.WalletService.CreateResource:input_type -> hyapp.wallet.v1.CreateResourceRequest - 66, // 185: hyapp.wallet.v1.WalletService.UpdateResource:input_type -> hyapp.wallet.v1.UpdateResourceRequest - 67, // 186: hyapp.wallet.v1.WalletService.SetResourceStatus:input_type -> hyapp.wallet.v1.SetResourceStatusRequest - 68, // 187: hyapp.wallet.v1.WalletService.DeleteResource:input_type -> hyapp.wallet.v1.DeleteResourceRequest - 69, // 188: hyapp.wallet.v1.WalletService.BatchDeleteResources:input_type -> hyapp.wallet.v1.BatchDeleteResourcesRequest - 72, // 189: hyapp.wallet.v1.WalletService.ListResourceGroups:input_type -> hyapp.wallet.v1.ListResourceGroupsRequest - 74, // 190: hyapp.wallet.v1.WalletService.GetResourceGroup:input_type -> hyapp.wallet.v1.GetResourceGroupRequest - 76, // 191: hyapp.wallet.v1.WalletService.CreateResourceGroup:input_type -> hyapp.wallet.v1.CreateResourceGroupRequest - 77, // 192: hyapp.wallet.v1.WalletService.UpdateResourceGroup:input_type -> hyapp.wallet.v1.UpdateResourceGroupRequest - 78, // 193: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:input_type -> hyapp.wallet.v1.SetResourceGroupStatusRequest - 52, // 194: hyapp.wallet.v1.WalletService.PinResourceGroupSnapshot:input_type -> hyapp.wallet.v1.PinResourceGroupSnapshotRequest - 80, // 195: hyapp.wallet.v1.WalletService.ListGiftConfigs:input_type -> hyapp.wallet.v1.ListGiftConfigsRequest - 82, // 196: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:input_type -> hyapp.wallet.v1.ListGiftTypeConfigsRequest - 277, // 197: hyapp.wallet.v1.WalletService.GetGiftCatalogVersion:input_type -> hyapp.wallet.v1.GetGiftCatalogVersionRequest - 86, // 198: hyapp.wallet.v1.WalletService.CreateGiftConfig:input_type -> hyapp.wallet.v1.CreateGiftConfigRequest - 87, // 199: hyapp.wallet.v1.WalletService.BatchCreateGiftConfigs:input_type -> hyapp.wallet.v1.BatchCreateGiftConfigsRequest - 89, // 200: hyapp.wallet.v1.WalletService.UpdateGiftConfig:input_type -> hyapp.wallet.v1.UpdateGiftConfigRequest - 90, // 201: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:input_type -> hyapp.wallet.v1.SetGiftConfigStatusRequest - 91, // 202: hyapp.wallet.v1.WalletService.DeleteGiftConfig:input_type -> hyapp.wallet.v1.DeleteGiftConfigRequest - 84, // 203: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:input_type -> hyapp.wallet.v1.UpsertGiftTypeConfigRequest - 93, // 204: hyapp.wallet.v1.WalletService.GrantResource:input_type -> hyapp.wallet.v1.GrantResourceRequest - 94, // 205: hyapp.wallet.v1.WalletService.GrantResourceGroup:input_type -> hyapp.wallet.v1.GrantResourceGroupRequest - 95, // 206: hyapp.wallet.v1.WalletService.GrantPinnedResourceGroup:input_type -> hyapp.wallet.v1.GrantPinnedResourceGroupRequest - 96, // 207: hyapp.wallet.v1.WalletService.RevokeResourceGrant:input_type -> hyapp.wallet.v1.RevokeResourceGrantRequest - 98, // 208: hyapp.wallet.v1.WalletService.ListUserResources:input_type -> hyapp.wallet.v1.ListUserResourcesRequest - 100, // 209: hyapp.wallet.v1.WalletService.EquipUserResource:input_type -> hyapp.wallet.v1.EquipUserResourceRequest - 102, // 210: hyapp.wallet.v1.WalletService.UnequipUserResource:input_type -> hyapp.wallet.v1.UnequipUserResourceRequest - 104, // 211: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:input_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest - 107, // 212: hyapp.wallet.v1.WalletService.ListResourceGrants:input_type -> hyapp.wallet.v1.ListResourceGrantsRequest - 110, // 213: hyapp.wallet.v1.WalletService.ListResourceShopItems:input_type -> hyapp.wallet.v1.ListResourceShopItemsRequest - 112, // 214: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:input_type -> hyapp.wallet.v1.UpsertResourceShopItemsRequest - 114, // 215: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:input_type -> hyapp.wallet.v1.SetResourceShopItemStatusRequest - 275, // 216: hyapp.wallet.v1.WalletService.ListResourceShopPurchaseOrders:input_type -> hyapp.wallet.v1.ListResourceShopPurchaseOrdersRequest - 116, // 217: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:input_type -> hyapp.wallet.v1.PurchaseResourceShopItemRequest - 119, // 218: hyapp.wallet.v1.WalletService.ListRechargeBills:input_type -> hyapp.wallet.v1.ListRechargeBillsRequest - 121, // 219: hyapp.wallet.v1.WalletService.GetRechargeBillSummary:input_type -> hyapp.wallet.v1.GetRechargeBillSummaryRequest - 125, // 220: hyapp.wallet.v1.WalletService.BatchGetUserRechargeStats:input_type -> hyapp.wallet.v1.BatchGetUserRechargeStatsRequest - 127, // 221: hyapp.wallet.v1.WalletService.GetRechargeBillOverview:input_type -> hyapp.wallet.v1.GetRechargeBillOverviewRequest - 133, // 222: hyapp.wallet.v1.WalletService.RefreshGooglePaymentPrices:input_type -> hyapp.wallet.v1.RefreshGooglePaymentPricesRequest - 137, // 223: hyapp.wallet.v1.WalletService.GetWalletOverview:input_type -> hyapp.wallet.v1.GetWalletOverviewRequest - 140, // 224: hyapp.wallet.v1.WalletService.GetWalletValueSummary:input_type -> hyapp.wallet.v1.GetWalletValueSummaryRequest - 143, // 225: hyapp.wallet.v1.WalletService.GetUserGiftWall:input_type -> hyapp.wallet.v1.GetUserGiftWallRequest - 146, // 226: hyapp.wallet.v1.WalletService.ListRechargeProducts:input_type -> hyapp.wallet.v1.ListRechargeProductsRequest - 148, // 227: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:input_type -> hyapp.wallet.v1.ConfirmGooglePaymentRequest - 150, // 228: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:input_type -> hyapp.wallet.v1.ListAdminRechargeProductsRequest - 152, // 229: hyapp.wallet.v1.WalletService.CreateRechargeProduct:input_type -> hyapp.wallet.v1.CreateRechargeProductRequest - 153, // 230: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:input_type -> hyapp.wallet.v1.UpdateRechargeProductRequest - 154, // 231: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:input_type -> hyapp.wallet.v1.DeleteRechargeProductRequest - 159, // 232: hyapp.wallet.v1.WalletService.ListThirdPartyPaymentChannels:input_type -> hyapp.wallet.v1.ListThirdPartyPaymentChannelsRequest - 161, // 233: hyapp.wallet.v1.WalletService.SetThirdPartyPaymentMethodStatus:input_type -> hyapp.wallet.v1.SetThirdPartyPaymentMethodStatusRequest - 163, // 234: hyapp.wallet.v1.WalletService.UpdateThirdPartyPaymentRate:input_type -> hyapp.wallet.v1.UpdateThirdPartyPaymentRateRequest - 165, // 235: hyapp.wallet.v1.WalletService.SyncThirdPartyPaymentMethods:input_type -> hyapp.wallet.v1.SyncThirdPartyPaymentMethodsRequest - 167, // 236: hyapp.wallet.v1.WalletService.ListH5RechargeOptions:input_type -> hyapp.wallet.v1.H5RechargeOptionsRequest - 170, // 237: hyapp.wallet.v1.WalletService.CreateH5RechargeOrder:input_type -> hyapp.wallet.v1.CreateH5RechargeOrderRequest - 171, // 238: hyapp.wallet.v1.WalletService.CreateTemporaryRechargeOrder:input_type -> hyapp.wallet.v1.CreateTemporaryRechargeOrderRequest - 172, // 239: hyapp.wallet.v1.WalletService.GetTemporaryRechargeOrder:input_type -> hyapp.wallet.v1.GetTemporaryRechargeOrderRequest - 173, // 240: hyapp.wallet.v1.WalletService.ListTemporaryRechargeOrders:input_type -> hyapp.wallet.v1.ListTemporaryRechargeOrdersRequest - 175, // 241: hyapp.wallet.v1.WalletService.SubmitH5RechargeTx:input_type -> hyapp.wallet.v1.SubmitH5RechargeTxRequest - 176, // 242: hyapp.wallet.v1.WalletService.GetH5RechargeOrder:input_type -> hyapp.wallet.v1.GetH5RechargeOrderRequest - 178, // 243: hyapp.wallet.v1.WalletService.VerifyCoinSellerRechargeReceipt:input_type -> hyapp.wallet.v1.VerifyCoinSellerRechargeReceiptRequest - 180, // 244: hyapp.wallet.v1.WalletService.HandleMifapayNotify:input_type -> hyapp.wallet.v1.HandleMifapayNotifyRequest - 182, // 245: hyapp.wallet.v1.WalletService.HandleV5PayNotify:input_type -> hyapp.wallet.v1.HandleV5PayNotifyRequest - 185, // 246: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:input_type -> hyapp.wallet.v1.GetDiamondExchangeConfigRequest - 188, // 247: hyapp.wallet.v1.WalletService.ListWalletTransactions:input_type -> hyapp.wallet.v1.ListWalletTransactionsRequest - 198, // 248: hyapp.wallet.v1.WalletService.ListVipPackages:input_type -> hyapp.wallet.v1.ListVipPackagesRequest - 210, // 249: hyapp.wallet.v1.WalletService.GetVipProgramConfig:input_type -> hyapp.wallet.v1.GetVipProgramConfigRequest - 200, // 250: hyapp.wallet.v1.WalletService.GetMyVip:input_type -> hyapp.wallet.v1.GetMyVipRequest - 232, // 251: hyapp.wallet.v1.WalletService.CheckVipBenefit:input_type -> hyapp.wallet.v1.CheckVipBenefitRequest - 202, // 252: hyapp.wallet.v1.WalletService.PurchaseVip:input_type -> hyapp.wallet.v1.PurchaseVipRequest - 204, // 253: hyapp.wallet.v1.WalletService.DebitCPBreakupFee:input_type -> hyapp.wallet.v1.DebitCPBreakupFeeRequest - 206, // 254: hyapp.wallet.v1.WalletService.DebitWheelDraw:input_type -> hyapp.wallet.v1.DebitWheelDrawRequest - 208, // 255: hyapp.wallet.v1.WalletService.GrantVip:input_type -> hyapp.wallet.v1.GrantVipRequest - 226, // 256: hyapp.wallet.v1.WalletService.GrantVipTrialCard:input_type -> hyapp.wallet.v1.GrantVipTrialCardRequest - 228, // 257: hyapp.wallet.v1.WalletService.EquipVipTrialCard:input_type -> hyapp.wallet.v1.EquipVipTrialCardRequest - 230, // 258: hyapp.wallet.v1.WalletService.UnequipVipTrialCard:input_type -> hyapp.wallet.v1.UnequipVipTrialCardRequest - 235, // 259: hyapp.wallet.v1.WalletService.ListAdminVipLevels:input_type -> hyapp.wallet.v1.ListAdminVipLevelsRequest - 237, // 260: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:input_type -> hyapp.wallet.v1.UpdateAdminVipLevelsRequest - 212, // 261: hyapp.wallet.v1.WalletService.UpdateAdminVipProgramConfig:input_type -> hyapp.wallet.v1.UpdateAdminVipProgramConfigRequest - 214, // 262: hyapp.wallet.v1.WalletService.UpdateMyVipSettings:input_type -> hyapp.wallet.v1.UpdateMyVipSettingsRequest - 220, // 263: hyapp.wallet.v1.WalletService.GetMyCurrentVipDailyCoinRebate:input_type -> hyapp.wallet.v1.GetMyCurrentVipDailyCoinRebateRequest - 222, // 264: hyapp.wallet.v1.WalletService.ListMyVipDailyCoinRebateStatuses:input_type -> hyapp.wallet.v1.ListMyVipDailyCoinRebateStatusesRequest - 224, // 265: hyapp.wallet.v1.WalletService.ClaimVipDailyCoinRebate:input_type -> hyapp.wallet.v1.ClaimVipDailyCoinRebateRequest - 239, // 266: hyapp.wallet.v1.WalletService.CreditTaskReward:input_type -> hyapp.wallet.v1.CreditTaskRewardRequest - 241, // 267: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:input_type -> hyapp.wallet.v1.CreditLuckyGiftRewardRequest - 243, // 268: hyapp.wallet.v1.WalletService.CreditWheelReward:input_type -> hyapp.wallet.v1.CreditWheelRewardRequest - 245, // 269: hyapp.wallet.v1.WalletService.CreditRoomTurnoverReward:input_type -> hyapp.wallet.v1.CreditRoomTurnoverRewardRequest - 247, // 270: hyapp.wallet.v1.WalletService.CreditInviteActivityReward:input_type -> hyapp.wallet.v1.CreditInviteActivityRewardRequest - 249, // 271: hyapp.wallet.v1.WalletService.CreditAgencyOpeningReward:input_type -> hyapp.wallet.v1.CreditAgencyOpeningRewardRequest - 251, // 272: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:input_type -> hyapp.wallet.v1.ApplyGameCoinChangeRequest - 256, // 273: hyapp.wallet.v1.WalletService.GetRedPacketConfig:input_type -> hyapp.wallet.v1.GetRedPacketConfigRequest - 258, // 274: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:input_type -> hyapp.wallet.v1.UpdateRedPacketConfigRequest - 260, // 275: hyapp.wallet.v1.WalletService.CreateRedPacket:input_type -> hyapp.wallet.v1.CreateRedPacketRequest - 262, // 276: hyapp.wallet.v1.WalletService.ClaimRedPacket:input_type -> hyapp.wallet.v1.ClaimRedPacketRequest - 264, // 277: hyapp.wallet.v1.WalletService.ListRedPackets:input_type -> hyapp.wallet.v1.ListRedPacketsRequest - 266, // 278: hyapp.wallet.v1.WalletService.GetRedPacket:input_type -> hyapp.wallet.v1.GetRedPacketRequest - 268, // 279: hyapp.wallet.v1.WalletService.ExpireRedPackets:input_type -> hyapp.wallet.v1.ExpireRedPacketsRequest - 270, // 280: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:input_type -> hyapp.wallet.v1.RetryRedPacketRefundRequest - 273, // 281: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 273, // 282: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 273, // 283: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 219, // 284: hyapp.wallet.v1.WalletCronService.ProcessVipDailyCoinRebateBatch:output_type -> hyapp.wallet.v1.ProcessVipDailyCoinRebateBatchResponse - 2, // 285: hyapp.wallet.v1.WalletService.DebitGift:output_type -> hyapp.wallet.v1.DebitGiftResponse - 2, // 286: hyapp.wallet.v1.WalletService.DebitDirectGift:output_type -> hyapp.wallet.v1.DebitGiftResponse - 6, // 287: hyapp.wallet.v1.WalletService.BatchDebitGift:output_type -> hyapp.wallet.v1.BatchDebitGiftResponse - 2, // 288: hyapp.wallet.v1.WalletService.DebitRobotGift:output_type -> hyapp.wallet.v1.DebitGiftResponse - 10, // 289: hyapp.wallet.v1.WalletService.GetBalances:output_type -> hyapp.wallet.v1.GetBalancesResponse - 14, // 290: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:output_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse - 17, // 291: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:output_type -> hyapp.wallet.v1.GetHostSalaryProgressResponse - 281, // 292: hyapp.wallet.v1.WalletService.GetHostRevenueStats:output_type -> hyapp.wallet.v1.GetHostRevenueStatsResponse - 284, // 293: hyapp.wallet.v1.WalletService.GetAgencyPointShareStats:output_type -> hyapp.wallet.v1.GetAgencyPointShareStatsResponse - 287, // 294: hyapp.wallet.v1.WalletService.GetAgencyHostGiftStats:output_type -> hyapp.wallet.v1.GetAgencyHostGiftStatsResponse - 20, // 295: hyapp.wallet.v1.WalletService.GetTeamHostSalaryStats:output_type -> hyapp.wallet.v1.GetTeamHostSalaryStatsResponse - 22, // 296: hyapp.wallet.v1.WalletService.AdminCreditAsset:output_type -> hyapp.wallet.v1.AdminCreditAssetResponse - 24, // 297: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:output_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockResponse - 26, // 298: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:output_type -> hyapp.wallet.v1.TransferCoinFromSellerResponse - 28, // 299: hyapp.wallet.v1.WalletService.TransferCoinSellerStockToChild:output_type -> hyapp.wallet.v1.TransferCoinSellerStockToChildResponse - 31, // 300: hyapp.wallet.v1.WalletService.ListCoinSellerSalaryExchangeRateTiers:output_type -> hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersResponse - 33, // 301: hyapp.wallet.v1.WalletService.ExchangeSalaryToCoin:output_type -> hyapp.wallet.v1.ExchangeSalaryToCoinResponse - 35, // 302: hyapp.wallet.v1.WalletService.TransferSalaryToCoinSeller:output_type -> hyapp.wallet.v1.TransferSalaryToCoinSellerResponse - 290, // 303: hyapp.wallet.v1.WalletService.ListPointWithdrawalCoinSellers:output_type -> hyapp.wallet.v1.ListPointWithdrawalCoinSellersResponse - 292, // 304: hyapp.wallet.v1.WalletService.TransferPointToCoinSeller:output_type -> hyapp.wallet.v1.TransferPointToCoinSellerResponse - 294, // 305: hyapp.wallet.v1.WalletService.GetPointWithdrawalConfig:output_type -> hyapp.wallet.v1.GetPointWithdrawalConfigResponse - 37, // 306: hyapp.wallet.v1.WalletService.FreezeSalaryWithdrawal:output_type -> hyapp.wallet.v1.FreezeSalaryWithdrawalResponse - 39, // 307: hyapp.wallet.v1.WalletService.SettleSalaryWithdrawal:output_type -> hyapp.wallet.v1.SettleSalaryWithdrawalResponse - 41, // 308: hyapp.wallet.v1.WalletService.ReleaseSalaryWithdrawal:output_type -> hyapp.wallet.v1.ReleaseSalaryWithdrawalResponse - 43, // 309: hyapp.wallet.v1.WalletService.FreezePointWithdrawal:output_type -> hyapp.wallet.v1.FreezePointWithdrawalResponse - 45, // 310: hyapp.wallet.v1.WalletService.SettlePointWithdrawal:output_type -> hyapp.wallet.v1.SettlePointWithdrawalResponse - 47, // 311: hyapp.wallet.v1.WalletService.ReleasePointWithdrawal:output_type -> hyapp.wallet.v1.ReleasePointWithdrawalResponse - 62, // 312: hyapp.wallet.v1.WalletService.ListResources:output_type -> hyapp.wallet.v1.ListResourcesResponse - 64, // 313: hyapp.wallet.v1.WalletService.GetResource:output_type -> hyapp.wallet.v1.GetResourceResponse - 71, // 314: hyapp.wallet.v1.WalletService.CreateResource:output_type -> hyapp.wallet.v1.ResourceResponse - 71, // 315: hyapp.wallet.v1.WalletService.UpdateResource:output_type -> hyapp.wallet.v1.ResourceResponse - 71, // 316: hyapp.wallet.v1.WalletService.SetResourceStatus:output_type -> hyapp.wallet.v1.ResourceResponse - 71, // 317: hyapp.wallet.v1.WalletService.DeleteResource:output_type -> hyapp.wallet.v1.ResourceResponse - 70, // 318: hyapp.wallet.v1.WalletService.BatchDeleteResources:output_type -> hyapp.wallet.v1.BatchDeleteResourcesResponse - 73, // 319: hyapp.wallet.v1.WalletService.ListResourceGroups:output_type -> hyapp.wallet.v1.ListResourceGroupsResponse - 75, // 320: hyapp.wallet.v1.WalletService.GetResourceGroup:output_type -> hyapp.wallet.v1.GetResourceGroupResponse - 79, // 321: hyapp.wallet.v1.WalletService.CreateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 79, // 322: hyapp.wallet.v1.WalletService.UpdateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 79, // 323: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 53, // 324: hyapp.wallet.v1.WalletService.PinResourceGroupSnapshot:output_type -> hyapp.wallet.v1.PinResourceGroupSnapshotResponse - 81, // 325: hyapp.wallet.v1.WalletService.ListGiftConfigs:output_type -> hyapp.wallet.v1.ListGiftConfigsResponse - 83, // 326: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:output_type -> hyapp.wallet.v1.ListGiftTypeConfigsResponse - 278, // 327: hyapp.wallet.v1.WalletService.GetGiftCatalogVersion:output_type -> hyapp.wallet.v1.GetGiftCatalogVersionResponse - 92, // 328: hyapp.wallet.v1.WalletService.CreateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse - 88, // 329: hyapp.wallet.v1.WalletService.BatchCreateGiftConfigs:output_type -> hyapp.wallet.v1.BatchCreateGiftConfigsResponse - 92, // 330: hyapp.wallet.v1.WalletService.UpdateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse - 92, // 331: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:output_type -> hyapp.wallet.v1.GiftConfigResponse - 92, // 332: hyapp.wallet.v1.WalletService.DeleteGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse - 85, // 333: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:output_type -> hyapp.wallet.v1.GiftTypeConfigResponse - 97, // 334: hyapp.wallet.v1.WalletService.GrantResource:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 97, // 335: hyapp.wallet.v1.WalletService.GrantResourceGroup:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 97, // 336: hyapp.wallet.v1.WalletService.GrantPinnedResourceGroup:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 97, // 337: hyapp.wallet.v1.WalletService.RevokeResourceGrant:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 99, // 338: hyapp.wallet.v1.WalletService.ListUserResources:output_type -> hyapp.wallet.v1.ListUserResourcesResponse - 101, // 339: hyapp.wallet.v1.WalletService.EquipUserResource:output_type -> hyapp.wallet.v1.EquipUserResourceResponse - 103, // 340: hyapp.wallet.v1.WalletService.UnequipUserResource:output_type -> hyapp.wallet.v1.UnequipUserResourceResponse - 106, // 341: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:output_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse - 108, // 342: hyapp.wallet.v1.WalletService.ListResourceGrants:output_type -> hyapp.wallet.v1.ListResourceGrantsResponse - 111, // 343: hyapp.wallet.v1.WalletService.ListResourceShopItems:output_type -> hyapp.wallet.v1.ListResourceShopItemsResponse - 113, // 344: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:output_type -> hyapp.wallet.v1.UpsertResourceShopItemsResponse - 115, // 345: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:output_type -> hyapp.wallet.v1.ResourceShopItemResponse - 276, // 346: hyapp.wallet.v1.WalletService.ListResourceShopPurchaseOrders:output_type -> hyapp.wallet.v1.ListResourceShopPurchaseOrdersResponse - 117, // 347: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:output_type -> hyapp.wallet.v1.PurchaseResourceShopItemResponse - 120, // 348: hyapp.wallet.v1.WalletService.ListRechargeBills:output_type -> hyapp.wallet.v1.ListRechargeBillsResponse - 123, // 349: hyapp.wallet.v1.WalletService.GetRechargeBillSummary:output_type -> hyapp.wallet.v1.GetRechargeBillSummaryResponse - 126, // 350: hyapp.wallet.v1.WalletService.BatchGetUserRechargeStats:output_type -> hyapp.wallet.v1.BatchGetUserRechargeStatsResponse - 132, // 351: hyapp.wallet.v1.WalletService.GetRechargeBillOverview:output_type -> hyapp.wallet.v1.GetRechargeBillOverviewResponse - 135, // 352: hyapp.wallet.v1.WalletService.RefreshGooglePaymentPrices:output_type -> hyapp.wallet.v1.RefreshGooglePaymentPricesResponse - 138, // 353: hyapp.wallet.v1.WalletService.GetWalletOverview:output_type -> hyapp.wallet.v1.GetWalletOverviewResponse - 141, // 354: hyapp.wallet.v1.WalletService.GetWalletValueSummary:output_type -> hyapp.wallet.v1.GetWalletValueSummaryResponse - 144, // 355: hyapp.wallet.v1.WalletService.GetUserGiftWall:output_type -> hyapp.wallet.v1.GetUserGiftWallResponse - 147, // 356: hyapp.wallet.v1.WalletService.ListRechargeProducts:output_type -> hyapp.wallet.v1.ListRechargeProductsResponse - 149, // 357: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:output_type -> hyapp.wallet.v1.ConfirmGooglePaymentResponse - 151, // 358: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:output_type -> hyapp.wallet.v1.ListAdminRechargeProductsResponse - 155, // 359: hyapp.wallet.v1.WalletService.CreateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse - 155, // 360: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse - 156, // 361: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:output_type -> hyapp.wallet.v1.DeleteRechargeProductResponse - 160, // 362: hyapp.wallet.v1.WalletService.ListThirdPartyPaymentChannels:output_type -> hyapp.wallet.v1.ListThirdPartyPaymentChannelsResponse - 162, // 363: hyapp.wallet.v1.WalletService.SetThirdPartyPaymentMethodStatus:output_type -> hyapp.wallet.v1.ThirdPartyPaymentMethodResponse - 162, // 364: hyapp.wallet.v1.WalletService.UpdateThirdPartyPaymentRate:output_type -> hyapp.wallet.v1.ThirdPartyPaymentMethodResponse - 166, // 365: hyapp.wallet.v1.WalletService.SyncThirdPartyPaymentMethods:output_type -> hyapp.wallet.v1.SyncThirdPartyPaymentMethodsResponse - 168, // 366: hyapp.wallet.v1.WalletService.ListH5RechargeOptions:output_type -> hyapp.wallet.v1.H5RechargeOptionsResponse - 177, // 367: hyapp.wallet.v1.WalletService.CreateH5RechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse - 177, // 368: hyapp.wallet.v1.WalletService.CreateTemporaryRechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse - 177, // 369: hyapp.wallet.v1.WalletService.GetTemporaryRechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse - 174, // 370: hyapp.wallet.v1.WalletService.ListTemporaryRechargeOrders:output_type -> hyapp.wallet.v1.ListTemporaryRechargeOrdersResponse - 177, // 371: hyapp.wallet.v1.WalletService.SubmitH5RechargeTx:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse - 177, // 372: hyapp.wallet.v1.WalletService.GetH5RechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse - 179, // 373: hyapp.wallet.v1.WalletService.VerifyCoinSellerRechargeReceipt:output_type -> hyapp.wallet.v1.VerifyCoinSellerRechargeReceiptResponse - 181, // 374: hyapp.wallet.v1.WalletService.HandleMifapayNotify:output_type -> hyapp.wallet.v1.HandleMifapayNotifyResponse - 183, // 375: hyapp.wallet.v1.WalletService.HandleV5PayNotify:output_type -> hyapp.wallet.v1.HandleV5PayNotifyResponse - 186, // 376: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:output_type -> hyapp.wallet.v1.GetDiamondExchangeConfigResponse - 189, // 377: hyapp.wallet.v1.WalletService.ListWalletTransactions:output_type -> hyapp.wallet.v1.ListWalletTransactionsResponse - 199, // 378: hyapp.wallet.v1.WalletService.ListVipPackages:output_type -> hyapp.wallet.v1.ListVipPackagesResponse - 211, // 379: hyapp.wallet.v1.WalletService.GetVipProgramConfig:output_type -> hyapp.wallet.v1.GetVipProgramConfigResponse - 201, // 380: hyapp.wallet.v1.WalletService.GetMyVip:output_type -> hyapp.wallet.v1.GetMyVipResponse - 233, // 381: hyapp.wallet.v1.WalletService.CheckVipBenefit:output_type -> hyapp.wallet.v1.CheckVipBenefitResponse - 203, // 382: hyapp.wallet.v1.WalletService.PurchaseVip:output_type -> hyapp.wallet.v1.PurchaseVipResponse - 205, // 383: hyapp.wallet.v1.WalletService.DebitCPBreakupFee:output_type -> hyapp.wallet.v1.DebitCPBreakupFeeResponse - 207, // 384: hyapp.wallet.v1.WalletService.DebitWheelDraw:output_type -> hyapp.wallet.v1.DebitWheelDrawResponse - 209, // 385: hyapp.wallet.v1.WalletService.GrantVip:output_type -> hyapp.wallet.v1.GrantVipResponse - 227, // 386: hyapp.wallet.v1.WalletService.GrantVipTrialCard:output_type -> hyapp.wallet.v1.GrantVipTrialCardResponse - 229, // 387: hyapp.wallet.v1.WalletService.EquipVipTrialCard:output_type -> hyapp.wallet.v1.EquipVipTrialCardResponse - 231, // 388: hyapp.wallet.v1.WalletService.UnequipVipTrialCard:output_type -> hyapp.wallet.v1.UnequipVipTrialCardResponse - 236, // 389: hyapp.wallet.v1.WalletService.ListAdminVipLevels:output_type -> hyapp.wallet.v1.ListAdminVipLevelsResponse - 238, // 390: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:output_type -> hyapp.wallet.v1.UpdateAdminVipLevelsResponse - 213, // 391: hyapp.wallet.v1.WalletService.UpdateAdminVipProgramConfig:output_type -> hyapp.wallet.v1.UpdateAdminVipProgramConfigResponse - 215, // 392: hyapp.wallet.v1.WalletService.UpdateMyVipSettings:output_type -> hyapp.wallet.v1.UpdateMyVipSettingsResponse - 221, // 393: hyapp.wallet.v1.WalletService.GetMyCurrentVipDailyCoinRebate:output_type -> hyapp.wallet.v1.GetMyCurrentVipDailyCoinRebateResponse - 223, // 394: hyapp.wallet.v1.WalletService.ListMyVipDailyCoinRebateStatuses:output_type -> hyapp.wallet.v1.ListMyVipDailyCoinRebateStatusesResponse - 225, // 395: hyapp.wallet.v1.WalletService.ClaimVipDailyCoinRebate:output_type -> hyapp.wallet.v1.ClaimVipDailyCoinRebateResponse - 240, // 396: hyapp.wallet.v1.WalletService.CreditTaskReward:output_type -> hyapp.wallet.v1.CreditTaskRewardResponse - 242, // 397: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:output_type -> hyapp.wallet.v1.CreditLuckyGiftRewardResponse - 244, // 398: hyapp.wallet.v1.WalletService.CreditWheelReward:output_type -> hyapp.wallet.v1.CreditWheelRewardResponse - 246, // 399: hyapp.wallet.v1.WalletService.CreditRoomTurnoverReward:output_type -> hyapp.wallet.v1.CreditRoomTurnoverRewardResponse - 248, // 400: hyapp.wallet.v1.WalletService.CreditInviteActivityReward:output_type -> hyapp.wallet.v1.CreditInviteActivityRewardResponse - 250, // 401: hyapp.wallet.v1.WalletService.CreditAgencyOpeningReward:output_type -> hyapp.wallet.v1.CreditAgencyOpeningRewardResponse - 252, // 402: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:output_type -> hyapp.wallet.v1.ApplyGameCoinChangeResponse - 257, // 403: hyapp.wallet.v1.WalletService.GetRedPacketConfig:output_type -> hyapp.wallet.v1.GetRedPacketConfigResponse - 259, // 404: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:output_type -> hyapp.wallet.v1.UpdateRedPacketConfigResponse - 261, // 405: hyapp.wallet.v1.WalletService.CreateRedPacket:output_type -> hyapp.wallet.v1.CreateRedPacketResponse - 263, // 406: hyapp.wallet.v1.WalletService.ClaimRedPacket:output_type -> hyapp.wallet.v1.ClaimRedPacketResponse - 265, // 407: hyapp.wallet.v1.WalletService.ListRedPackets:output_type -> hyapp.wallet.v1.ListRedPacketsResponse - 267, // 408: hyapp.wallet.v1.WalletService.GetRedPacket:output_type -> hyapp.wallet.v1.GetRedPacketResponse - 269, // 409: hyapp.wallet.v1.WalletService.ExpireRedPackets:output_type -> hyapp.wallet.v1.ExpireRedPacketsResponse - 271, // 410: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:output_type -> hyapp.wallet.v1.RetryRedPacketRefundResponse - 281, // [281:411] is the sub-list for method output_type - 151, // [151:281] is the sub-list for method input_type - 151, // [151:151] is the sub-list for extension type_name - 151, // [151:151] is the sub-list for extension extendee - 0, // [0:151] is the sub-list for field type_name + 297, // 85: hyapp.wallet.v1.VipBenefit.presentation:type_name -> hyapp.wallet.v1.VipBenefitPresentation + 190, // 86: hyapp.wallet.v1.VipLevel.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 192, // 87: hyapp.wallet.v1.VipLevel.benefits:type_name -> hyapp.wallet.v1.VipBenefit + 194, // 88: hyapp.wallet.v1.VipState.paid_vip:type_name -> hyapp.wallet.v1.UserVip + 195, // 89: hyapp.wallet.v1.VipState.equipped_trial_card:type_name -> hyapp.wallet.v1.VipTrialCard + 194, // 90: hyapp.wallet.v1.VipState.effective_vip:type_name -> hyapp.wallet.v1.UserVip + 192, // 91: hyapp.wallet.v1.VipState.effective_benefits:type_name -> hyapp.wallet.v1.VipBenefit + 191, // 92: hyapp.wallet.v1.VipState.program_config:type_name -> hyapp.wallet.v1.VipProgramConfig + 196, // 93: hyapp.wallet.v1.VipState.user_settings:type_name -> hyapp.wallet.v1.VipUserSettings + 194, // 94: hyapp.wallet.v1.ListVipPackagesResponse.current_vip:type_name -> hyapp.wallet.v1.UserVip + 193, // 95: hyapp.wallet.v1.ListVipPackagesResponse.packages:type_name -> hyapp.wallet.v1.VipLevel + 197, // 96: hyapp.wallet.v1.ListVipPackagesResponse.state:type_name -> hyapp.wallet.v1.VipState + 191, // 97: hyapp.wallet.v1.ListVipPackagesResponse.program_config:type_name -> hyapp.wallet.v1.VipProgramConfig + 194, // 98: hyapp.wallet.v1.GetMyVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 197, // 99: hyapp.wallet.v1.GetMyVipResponse.state:type_name -> hyapp.wallet.v1.VipState + 194, // 100: hyapp.wallet.v1.PurchaseVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 190, // 101: hyapp.wallet.v1.PurchaseVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 197, // 102: hyapp.wallet.v1.PurchaseVipResponse.state:type_name -> hyapp.wallet.v1.VipState + 8, // 103: hyapp.wallet.v1.PurchaseVipResponse.coin_balance:type_name -> hyapp.wallet.v1.AssetBalance + 8, // 104: hyapp.wallet.v1.DebitCPBreakupFeeResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 8, // 105: hyapp.wallet.v1.DebitWheelDrawResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 194, // 106: hyapp.wallet.v1.GrantVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 190, // 107: hyapp.wallet.v1.GrantVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 197, // 108: hyapp.wallet.v1.GrantVipResponse.state:type_name -> hyapp.wallet.v1.VipState + 191, // 109: hyapp.wallet.v1.GetVipProgramConfigResponse.config:type_name -> hyapp.wallet.v1.VipProgramConfig + 192, // 110: hyapp.wallet.v1.GetVipProgramConfigResponse.benefits:type_name -> hyapp.wallet.v1.VipBenefit + 191, // 111: hyapp.wallet.v1.UpdateAdminVipProgramConfigRequest.config:type_name -> hyapp.wallet.v1.VipProgramConfig + 191, // 112: hyapp.wallet.v1.UpdateAdminVipProgramConfigResponse.config:type_name -> hyapp.wallet.v1.VipProgramConfig + 196, // 113: hyapp.wallet.v1.UpdateMyVipSettingsResponse.settings:type_name -> hyapp.wallet.v1.VipUserSettings + 216, // 114: hyapp.wallet.v1.ProcessVipDailyCoinRebateBatchResponse.run:type_name -> hyapp.wallet.v1.VipDailyCoinRebateRun + 217, // 115: hyapp.wallet.v1.GetMyCurrentVipDailyCoinRebateResponse.rebate:type_name -> hyapp.wallet.v1.VipDailyCoinRebate + 217, // 116: hyapp.wallet.v1.ListMyVipDailyCoinRebateStatusesResponse.rebates:type_name -> hyapp.wallet.v1.VipDailyCoinRebate + 217, // 117: hyapp.wallet.v1.ClaimVipDailyCoinRebateResponse.rebate:type_name -> hyapp.wallet.v1.VipDailyCoinRebate + 8, // 118: hyapp.wallet.v1.ClaimVipDailyCoinRebateResponse.coin_balance:type_name -> hyapp.wallet.v1.AssetBalance + 195, // 119: hyapp.wallet.v1.GrantVipTrialCardResponse.trial_card:type_name -> hyapp.wallet.v1.VipTrialCard + 197, // 120: hyapp.wallet.v1.GrantVipTrialCardResponse.state:type_name -> hyapp.wallet.v1.VipState + 195, // 121: hyapp.wallet.v1.EquipVipTrialCardResponse.trial_card:type_name -> hyapp.wallet.v1.VipTrialCard + 197, // 122: hyapp.wallet.v1.EquipVipTrialCardResponse.state:type_name -> hyapp.wallet.v1.VipState + 197, // 123: hyapp.wallet.v1.UnequipVipTrialCardResponse.state:type_name -> hyapp.wallet.v1.VipState + 192, // 124: hyapp.wallet.v1.CheckVipBenefitResponse.benefit:type_name -> hyapp.wallet.v1.VipBenefit + 197, // 125: hyapp.wallet.v1.CheckVipBenefitResponse.state:type_name -> hyapp.wallet.v1.VipState + 192, // 126: hyapp.wallet.v1.AdminVipLevelInput.benefits:type_name -> hyapp.wallet.v1.VipBenefit + 193, // 127: hyapp.wallet.v1.ListAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel + 191, // 128: hyapp.wallet.v1.ListAdminVipLevelsResponse.program_config:type_name -> hyapp.wallet.v1.VipProgramConfig + 234, // 129: hyapp.wallet.v1.UpdateAdminVipLevelsRequest.levels:type_name -> hyapp.wallet.v1.AdminVipLevelInput + 193, // 130: hyapp.wallet.v1.UpdateAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel + 191, // 131: hyapp.wallet.v1.UpdateAdminVipLevelsResponse.program_config:type_name -> hyapp.wallet.v1.VipProgramConfig + 8, // 132: hyapp.wallet.v1.CreditTaskRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 8, // 133: hyapp.wallet.v1.CreditLuckyGiftRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 8, // 134: hyapp.wallet.v1.CreditWheelRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 8, // 135: hyapp.wallet.v1.CreditRoomTurnoverRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 8, // 136: hyapp.wallet.v1.CreditInviteActivityRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 8, // 137: hyapp.wallet.v1.CreditAgencyOpeningRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 254, // 138: hyapp.wallet.v1.RedPacket.claims:type_name -> hyapp.wallet.v1.RedPacketClaim + 253, // 139: hyapp.wallet.v1.GetRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig + 253, // 140: hyapp.wallet.v1.UpdateRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig + 255, // 141: hyapp.wallet.v1.CreateRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 254, // 142: hyapp.wallet.v1.ClaimRedPacketResponse.claim:type_name -> hyapp.wallet.v1.RedPacketClaim + 255, // 143: hyapp.wallet.v1.ClaimRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 255, // 144: hyapp.wallet.v1.ListRedPacketsResponse.packets:type_name -> hyapp.wallet.v1.RedPacket + 255, // 145: hyapp.wallet.v1.GetRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 255, // 146: hyapp.wallet.v1.RetryRedPacketRefundResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 48, // 147: hyapp.wallet.v1.ResourceShopPurchaseOrder.resource:type_name -> hyapp.wallet.v1.Resource + 274, // 148: hyapp.wallet.v1.ListResourceShopPurchaseOrdersResponse.orders:type_name -> hyapp.wallet.v1.ResourceShopPurchaseOrder + 279, // 149: hyapp.wallet.v1.GetHostRevenueStatsResponse.stats:type_name -> hyapp.wallet.v1.HostRevenueStats + 282, // 150: hyapp.wallet.v1.GetAgencyPointShareStatsResponse.stats:type_name -> hyapp.wallet.v1.AgencyPointShareStats + 285, // 151: hyapp.wallet.v1.GetAgencyHostGiftStatsResponse.stats:type_name -> hyapp.wallet.v1.AgencyHostGiftStats + 288, // 152: hyapp.wallet.v1.ListPointWithdrawalCoinSellersResponse.sellers:type_name -> hyapp.wallet.v1.PointWithdrawalCoinSellerConfig + 295, // 153: hyapp.wallet.v1.VipBenefitPresentation.preview_items:type_name -> hyapp.wallet.v1.VipBenefitPreviewItem + 296, // 154: hyapp.wallet.v1.VipBenefitPresentation.numeric_reward:type_name -> hyapp.wallet.v1.VipBenefitNumericReward + 57, // 155: hyapp.wallet.v1.RevokeUserResourceResponse.resource:type_name -> hyapp.wallet.v1.UserResourceEntitlement + 272, // 156: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 272, // 157: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 272, // 158: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 218, // 159: hyapp.wallet.v1.WalletCronService.ProcessVipDailyCoinRebateBatch:input_type -> hyapp.wallet.v1.ProcessVipDailyCoinRebateBatchRequest + 0, // 160: hyapp.wallet.v1.WalletService.DebitGift:input_type -> hyapp.wallet.v1.DebitGiftRequest + 1, // 161: hyapp.wallet.v1.WalletService.DebitDirectGift:input_type -> hyapp.wallet.v1.DebitDirectGiftRequest + 4, // 162: hyapp.wallet.v1.WalletService.BatchDebitGift:input_type -> hyapp.wallet.v1.BatchDebitGiftRequest + 7, // 163: hyapp.wallet.v1.WalletService.DebitRobotGift:input_type -> hyapp.wallet.v1.DebitRobotGiftRequest + 9, // 164: hyapp.wallet.v1.WalletService.GetBalances:input_type -> hyapp.wallet.v1.GetBalancesRequest + 13, // 165: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:input_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyRequest + 16, // 166: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:input_type -> hyapp.wallet.v1.GetHostSalaryProgressRequest + 280, // 167: hyapp.wallet.v1.WalletService.GetHostRevenueStats:input_type -> hyapp.wallet.v1.GetHostRevenueStatsRequest + 283, // 168: hyapp.wallet.v1.WalletService.GetAgencyPointShareStats:input_type -> hyapp.wallet.v1.GetAgencyPointShareStatsRequest + 286, // 169: hyapp.wallet.v1.WalletService.GetAgencyHostGiftStats:input_type -> hyapp.wallet.v1.GetAgencyHostGiftStatsRequest + 19, // 170: hyapp.wallet.v1.WalletService.GetTeamHostSalaryStats:input_type -> hyapp.wallet.v1.GetTeamHostSalaryStatsRequest + 21, // 171: hyapp.wallet.v1.WalletService.AdminCreditAsset:input_type -> hyapp.wallet.v1.AdminCreditAssetRequest + 23, // 172: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:input_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockRequest + 25, // 173: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:input_type -> hyapp.wallet.v1.TransferCoinFromSellerRequest + 27, // 174: hyapp.wallet.v1.WalletService.TransferCoinSellerStockToChild:input_type -> hyapp.wallet.v1.TransferCoinSellerStockToChildRequest + 30, // 175: hyapp.wallet.v1.WalletService.ListCoinSellerSalaryExchangeRateTiers:input_type -> hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersRequest + 32, // 176: hyapp.wallet.v1.WalletService.ExchangeSalaryToCoin:input_type -> hyapp.wallet.v1.ExchangeSalaryToCoinRequest + 34, // 177: hyapp.wallet.v1.WalletService.TransferSalaryToCoinSeller:input_type -> hyapp.wallet.v1.TransferSalaryToCoinSellerRequest + 289, // 178: hyapp.wallet.v1.WalletService.ListPointWithdrawalCoinSellers:input_type -> hyapp.wallet.v1.ListPointWithdrawalCoinSellersRequest + 291, // 179: hyapp.wallet.v1.WalletService.TransferPointToCoinSeller:input_type -> hyapp.wallet.v1.TransferPointToCoinSellerRequest + 293, // 180: hyapp.wallet.v1.WalletService.GetPointWithdrawalConfig:input_type -> hyapp.wallet.v1.GetPointWithdrawalConfigRequest + 36, // 181: hyapp.wallet.v1.WalletService.FreezeSalaryWithdrawal:input_type -> hyapp.wallet.v1.FreezeSalaryWithdrawalRequest + 38, // 182: hyapp.wallet.v1.WalletService.SettleSalaryWithdrawal:input_type -> hyapp.wallet.v1.SettleSalaryWithdrawalRequest + 40, // 183: hyapp.wallet.v1.WalletService.ReleaseSalaryWithdrawal:input_type -> hyapp.wallet.v1.ReleaseSalaryWithdrawalRequest + 42, // 184: hyapp.wallet.v1.WalletService.FreezePointWithdrawal:input_type -> hyapp.wallet.v1.FreezePointWithdrawalRequest + 44, // 185: hyapp.wallet.v1.WalletService.SettlePointWithdrawal:input_type -> hyapp.wallet.v1.SettlePointWithdrawalRequest + 46, // 186: hyapp.wallet.v1.WalletService.ReleasePointWithdrawal:input_type -> hyapp.wallet.v1.ReleasePointWithdrawalRequest + 61, // 187: hyapp.wallet.v1.WalletService.ListResources:input_type -> hyapp.wallet.v1.ListResourcesRequest + 63, // 188: hyapp.wallet.v1.WalletService.GetResource:input_type -> hyapp.wallet.v1.GetResourceRequest + 65, // 189: hyapp.wallet.v1.WalletService.CreateResource:input_type -> hyapp.wallet.v1.CreateResourceRequest + 66, // 190: hyapp.wallet.v1.WalletService.UpdateResource:input_type -> hyapp.wallet.v1.UpdateResourceRequest + 67, // 191: hyapp.wallet.v1.WalletService.SetResourceStatus:input_type -> hyapp.wallet.v1.SetResourceStatusRequest + 68, // 192: hyapp.wallet.v1.WalletService.DeleteResource:input_type -> hyapp.wallet.v1.DeleteResourceRequest + 69, // 193: hyapp.wallet.v1.WalletService.BatchDeleteResources:input_type -> hyapp.wallet.v1.BatchDeleteResourcesRequest + 72, // 194: hyapp.wallet.v1.WalletService.ListResourceGroups:input_type -> hyapp.wallet.v1.ListResourceGroupsRequest + 74, // 195: hyapp.wallet.v1.WalletService.GetResourceGroup:input_type -> hyapp.wallet.v1.GetResourceGroupRequest + 76, // 196: hyapp.wallet.v1.WalletService.CreateResourceGroup:input_type -> hyapp.wallet.v1.CreateResourceGroupRequest + 77, // 197: hyapp.wallet.v1.WalletService.UpdateResourceGroup:input_type -> hyapp.wallet.v1.UpdateResourceGroupRequest + 78, // 198: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:input_type -> hyapp.wallet.v1.SetResourceGroupStatusRequest + 52, // 199: hyapp.wallet.v1.WalletService.PinResourceGroupSnapshot:input_type -> hyapp.wallet.v1.PinResourceGroupSnapshotRequest + 80, // 200: hyapp.wallet.v1.WalletService.ListGiftConfigs:input_type -> hyapp.wallet.v1.ListGiftConfigsRequest + 82, // 201: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:input_type -> hyapp.wallet.v1.ListGiftTypeConfigsRequest + 277, // 202: hyapp.wallet.v1.WalletService.GetGiftCatalogVersion:input_type -> hyapp.wallet.v1.GetGiftCatalogVersionRequest + 86, // 203: hyapp.wallet.v1.WalletService.CreateGiftConfig:input_type -> hyapp.wallet.v1.CreateGiftConfigRequest + 87, // 204: hyapp.wallet.v1.WalletService.BatchCreateGiftConfigs:input_type -> hyapp.wallet.v1.BatchCreateGiftConfigsRequest + 89, // 205: hyapp.wallet.v1.WalletService.UpdateGiftConfig:input_type -> hyapp.wallet.v1.UpdateGiftConfigRequest + 90, // 206: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:input_type -> hyapp.wallet.v1.SetGiftConfigStatusRequest + 91, // 207: hyapp.wallet.v1.WalletService.DeleteGiftConfig:input_type -> hyapp.wallet.v1.DeleteGiftConfigRequest + 84, // 208: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:input_type -> hyapp.wallet.v1.UpsertGiftTypeConfigRequest + 93, // 209: hyapp.wallet.v1.WalletService.GrantResource:input_type -> hyapp.wallet.v1.GrantResourceRequest + 94, // 210: hyapp.wallet.v1.WalletService.GrantResourceGroup:input_type -> hyapp.wallet.v1.GrantResourceGroupRequest + 95, // 211: hyapp.wallet.v1.WalletService.GrantPinnedResourceGroup:input_type -> hyapp.wallet.v1.GrantPinnedResourceGroupRequest + 96, // 212: hyapp.wallet.v1.WalletService.RevokeResourceGrant:input_type -> hyapp.wallet.v1.RevokeResourceGrantRequest + 298, // 213: hyapp.wallet.v1.WalletService.RevokeUserResource:input_type -> hyapp.wallet.v1.RevokeUserResourceRequest + 98, // 214: hyapp.wallet.v1.WalletService.ListUserResources:input_type -> hyapp.wallet.v1.ListUserResourcesRequest + 100, // 215: hyapp.wallet.v1.WalletService.EquipUserResource:input_type -> hyapp.wallet.v1.EquipUserResourceRequest + 102, // 216: hyapp.wallet.v1.WalletService.UnequipUserResource:input_type -> hyapp.wallet.v1.UnequipUserResourceRequest + 104, // 217: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:input_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest + 107, // 218: hyapp.wallet.v1.WalletService.ListResourceGrants:input_type -> hyapp.wallet.v1.ListResourceGrantsRequest + 110, // 219: hyapp.wallet.v1.WalletService.ListResourceShopItems:input_type -> hyapp.wallet.v1.ListResourceShopItemsRequest + 112, // 220: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:input_type -> hyapp.wallet.v1.UpsertResourceShopItemsRequest + 114, // 221: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:input_type -> hyapp.wallet.v1.SetResourceShopItemStatusRequest + 275, // 222: hyapp.wallet.v1.WalletService.ListResourceShopPurchaseOrders:input_type -> hyapp.wallet.v1.ListResourceShopPurchaseOrdersRequest + 116, // 223: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:input_type -> hyapp.wallet.v1.PurchaseResourceShopItemRequest + 119, // 224: hyapp.wallet.v1.WalletService.ListRechargeBills:input_type -> hyapp.wallet.v1.ListRechargeBillsRequest + 121, // 225: hyapp.wallet.v1.WalletService.GetRechargeBillSummary:input_type -> hyapp.wallet.v1.GetRechargeBillSummaryRequest + 125, // 226: hyapp.wallet.v1.WalletService.BatchGetUserRechargeStats:input_type -> hyapp.wallet.v1.BatchGetUserRechargeStatsRequest + 127, // 227: hyapp.wallet.v1.WalletService.GetRechargeBillOverview:input_type -> hyapp.wallet.v1.GetRechargeBillOverviewRequest + 133, // 228: hyapp.wallet.v1.WalletService.RefreshGooglePaymentPrices:input_type -> hyapp.wallet.v1.RefreshGooglePaymentPricesRequest + 137, // 229: hyapp.wallet.v1.WalletService.GetWalletOverview:input_type -> hyapp.wallet.v1.GetWalletOverviewRequest + 140, // 230: hyapp.wallet.v1.WalletService.GetWalletValueSummary:input_type -> hyapp.wallet.v1.GetWalletValueSummaryRequest + 143, // 231: hyapp.wallet.v1.WalletService.GetUserGiftWall:input_type -> hyapp.wallet.v1.GetUserGiftWallRequest + 146, // 232: hyapp.wallet.v1.WalletService.ListRechargeProducts:input_type -> hyapp.wallet.v1.ListRechargeProductsRequest + 148, // 233: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:input_type -> hyapp.wallet.v1.ConfirmGooglePaymentRequest + 150, // 234: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:input_type -> hyapp.wallet.v1.ListAdminRechargeProductsRequest + 152, // 235: hyapp.wallet.v1.WalletService.CreateRechargeProduct:input_type -> hyapp.wallet.v1.CreateRechargeProductRequest + 153, // 236: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:input_type -> hyapp.wallet.v1.UpdateRechargeProductRequest + 154, // 237: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:input_type -> hyapp.wallet.v1.DeleteRechargeProductRequest + 159, // 238: hyapp.wallet.v1.WalletService.ListThirdPartyPaymentChannels:input_type -> hyapp.wallet.v1.ListThirdPartyPaymentChannelsRequest + 161, // 239: hyapp.wallet.v1.WalletService.SetThirdPartyPaymentMethodStatus:input_type -> hyapp.wallet.v1.SetThirdPartyPaymentMethodStatusRequest + 163, // 240: hyapp.wallet.v1.WalletService.UpdateThirdPartyPaymentRate:input_type -> hyapp.wallet.v1.UpdateThirdPartyPaymentRateRequest + 165, // 241: hyapp.wallet.v1.WalletService.SyncThirdPartyPaymentMethods:input_type -> hyapp.wallet.v1.SyncThirdPartyPaymentMethodsRequest + 167, // 242: hyapp.wallet.v1.WalletService.ListH5RechargeOptions:input_type -> hyapp.wallet.v1.H5RechargeOptionsRequest + 170, // 243: hyapp.wallet.v1.WalletService.CreateH5RechargeOrder:input_type -> hyapp.wallet.v1.CreateH5RechargeOrderRequest + 171, // 244: hyapp.wallet.v1.WalletService.CreateTemporaryRechargeOrder:input_type -> hyapp.wallet.v1.CreateTemporaryRechargeOrderRequest + 172, // 245: hyapp.wallet.v1.WalletService.GetTemporaryRechargeOrder:input_type -> hyapp.wallet.v1.GetTemporaryRechargeOrderRequest + 173, // 246: hyapp.wallet.v1.WalletService.ListTemporaryRechargeOrders:input_type -> hyapp.wallet.v1.ListTemporaryRechargeOrdersRequest + 175, // 247: hyapp.wallet.v1.WalletService.SubmitH5RechargeTx:input_type -> hyapp.wallet.v1.SubmitH5RechargeTxRequest + 176, // 248: hyapp.wallet.v1.WalletService.GetH5RechargeOrder:input_type -> hyapp.wallet.v1.GetH5RechargeOrderRequest + 178, // 249: hyapp.wallet.v1.WalletService.VerifyCoinSellerRechargeReceipt:input_type -> hyapp.wallet.v1.VerifyCoinSellerRechargeReceiptRequest + 180, // 250: hyapp.wallet.v1.WalletService.HandleMifapayNotify:input_type -> hyapp.wallet.v1.HandleMifapayNotifyRequest + 182, // 251: hyapp.wallet.v1.WalletService.HandleV5PayNotify:input_type -> hyapp.wallet.v1.HandleV5PayNotifyRequest + 185, // 252: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:input_type -> hyapp.wallet.v1.GetDiamondExchangeConfigRequest + 188, // 253: hyapp.wallet.v1.WalletService.ListWalletTransactions:input_type -> hyapp.wallet.v1.ListWalletTransactionsRequest + 198, // 254: hyapp.wallet.v1.WalletService.ListVipPackages:input_type -> hyapp.wallet.v1.ListVipPackagesRequest + 210, // 255: hyapp.wallet.v1.WalletService.GetVipProgramConfig:input_type -> hyapp.wallet.v1.GetVipProgramConfigRequest + 200, // 256: hyapp.wallet.v1.WalletService.GetMyVip:input_type -> hyapp.wallet.v1.GetMyVipRequest + 232, // 257: hyapp.wallet.v1.WalletService.CheckVipBenefit:input_type -> hyapp.wallet.v1.CheckVipBenefitRequest + 202, // 258: hyapp.wallet.v1.WalletService.PurchaseVip:input_type -> hyapp.wallet.v1.PurchaseVipRequest + 204, // 259: hyapp.wallet.v1.WalletService.DebitCPBreakupFee:input_type -> hyapp.wallet.v1.DebitCPBreakupFeeRequest + 206, // 260: hyapp.wallet.v1.WalletService.DebitWheelDraw:input_type -> hyapp.wallet.v1.DebitWheelDrawRequest + 208, // 261: hyapp.wallet.v1.WalletService.GrantVip:input_type -> hyapp.wallet.v1.GrantVipRequest + 226, // 262: hyapp.wallet.v1.WalletService.GrantVipTrialCard:input_type -> hyapp.wallet.v1.GrantVipTrialCardRequest + 228, // 263: hyapp.wallet.v1.WalletService.EquipVipTrialCard:input_type -> hyapp.wallet.v1.EquipVipTrialCardRequest + 230, // 264: hyapp.wallet.v1.WalletService.UnequipVipTrialCard:input_type -> hyapp.wallet.v1.UnequipVipTrialCardRequest + 235, // 265: hyapp.wallet.v1.WalletService.ListAdminVipLevels:input_type -> hyapp.wallet.v1.ListAdminVipLevelsRequest + 237, // 266: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:input_type -> hyapp.wallet.v1.UpdateAdminVipLevelsRequest + 212, // 267: hyapp.wallet.v1.WalletService.UpdateAdminVipProgramConfig:input_type -> hyapp.wallet.v1.UpdateAdminVipProgramConfigRequest + 214, // 268: hyapp.wallet.v1.WalletService.UpdateMyVipSettings:input_type -> hyapp.wallet.v1.UpdateMyVipSettingsRequest + 220, // 269: hyapp.wallet.v1.WalletService.GetMyCurrentVipDailyCoinRebate:input_type -> hyapp.wallet.v1.GetMyCurrentVipDailyCoinRebateRequest + 222, // 270: hyapp.wallet.v1.WalletService.ListMyVipDailyCoinRebateStatuses:input_type -> hyapp.wallet.v1.ListMyVipDailyCoinRebateStatusesRequest + 224, // 271: hyapp.wallet.v1.WalletService.ClaimVipDailyCoinRebate:input_type -> hyapp.wallet.v1.ClaimVipDailyCoinRebateRequest + 239, // 272: hyapp.wallet.v1.WalletService.CreditTaskReward:input_type -> hyapp.wallet.v1.CreditTaskRewardRequest + 241, // 273: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:input_type -> hyapp.wallet.v1.CreditLuckyGiftRewardRequest + 243, // 274: hyapp.wallet.v1.WalletService.CreditWheelReward:input_type -> hyapp.wallet.v1.CreditWheelRewardRequest + 245, // 275: hyapp.wallet.v1.WalletService.CreditRoomTurnoverReward:input_type -> hyapp.wallet.v1.CreditRoomTurnoverRewardRequest + 247, // 276: hyapp.wallet.v1.WalletService.CreditInviteActivityReward:input_type -> hyapp.wallet.v1.CreditInviteActivityRewardRequest + 249, // 277: hyapp.wallet.v1.WalletService.CreditAgencyOpeningReward:input_type -> hyapp.wallet.v1.CreditAgencyOpeningRewardRequest + 251, // 278: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:input_type -> hyapp.wallet.v1.ApplyGameCoinChangeRequest + 256, // 279: hyapp.wallet.v1.WalletService.GetRedPacketConfig:input_type -> hyapp.wallet.v1.GetRedPacketConfigRequest + 258, // 280: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:input_type -> hyapp.wallet.v1.UpdateRedPacketConfigRequest + 260, // 281: hyapp.wallet.v1.WalletService.CreateRedPacket:input_type -> hyapp.wallet.v1.CreateRedPacketRequest + 262, // 282: hyapp.wallet.v1.WalletService.ClaimRedPacket:input_type -> hyapp.wallet.v1.ClaimRedPacketRequest + 264, // 283: hyapp.wallet.v1.WalletService.ListRedPackets:input_type -> hyapp.wallet.v1.ListRedPacketsRequest + 266, // 284: hyapp.wallet.v1.WalletService.GetRedPacket:input_type -> hyapp.wallet.v1.GetRedPacketRequest + 268, // 285: hyapp.wallet.v1.WalletService.ExpireRedPackets:input_type -> hyapp.wallet.v1.ExpireRedPacketsRequest + 270, // 286: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:input_type -> hyapp.wallet.v1.RetryRedPacketRefundRequest + 273, // 287: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 273, // 288: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 273, // 289: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 219, // 290: hyapp.wallet.v1.WalletCronService.ProcessVipDailyCoinRebateBatch:output_type -> hyapp.wallet.v1.ProcessVipDailyCoinRebateBatchResponse + 2, // 291: hyapp.wallet.v1.WalletService.DebitGift:output_type -> hyapp.wallet.v1.DebitGiftResponse + 2, // 292: hyapp.wallet.v1.WalletService.DebitDirectGift:output_type -> hyapp.wallet.v1.DebitGiftResponse + 6, // 293: hyapp.wallet.v1.WalletService.BatchDebitGift:output_type -> hyapp.wallet.v1.BatchDebitGiftResponse + 2, // 294: hyapp.wallet.v1.WalletService.DebitRobotGift:output_type -> hyapp.wallet.v1.DebitGiftResponse + 10, // 295: hyapp.wallet.v1.WalletService.GetBalances:output_type -> hyapp.wallet.v1.GetBalancesResponse + 14, // 296: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:output_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse + 17, // 297: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:output_type -> hyapp.wallet.v1.GetHostSalaryProgressResponse + 281, // 298: hyapp.wallet.v1.WalletService.GetHostRevenueStats:output_type -> hyapp.wallet.v1.GetHostRevenueStatsResponse + 284, // 299: hyapp.wallet.v1.WalletService.GetAgencyPointShareStats:output_type -> hyapp.wallet.v1.GetAgencyPointShareStatsResponse + 287, // 300: hyapp.wallet.v1.WalletService.GetAgencyHostGiftStats:output_type -> hyapp.wallet.v1.GetAgencyHostGiftStatsResponse + 20, // 301: hyapp.wallet.v1.WalletService.GetTeamHostSalaryStats:output_type -> hyapp.wallet.v1.GetTeamHostSalaryStatsResponse + 22, // 302: hyapp.wallet.v1.WalletService.AdminCreditAsset:output_type -> hyapp.wallet.v1.AdminCreditAssetResponse + 24, // 303: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:output_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockResponse + 26, // 304: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:output_type -> hyapp.wallet.v1.TransferCoinFromSellerResponse + 28, // 305: hyapp.wallet.v1.WalletService.TransferCoinSellerStockToChild:output_type -> hyapp.wallet.v1.TransferCoinSellerStockToChildResponse + 31, // 306: hyapp.wallet.v1.WalletService.ListCoinSellerSalaryExchangeRateTiers:output_type -> hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersResponse + 33, // 307: hyapp.wallet.v1.WalletService.ExchangeSalaryToCoin:output_type -> hyapp.wallet.v1.ExchangeSalaryToCoinResponse + 35, // 308: hyapp.wallet.v1.WalletService.TransferSalaryToCoinSeller:output_type -> hyapp.wallet.v1.TransferSalaryToCoinSellerResponse + 290, // 309: hyapp.wallet.v1.WalletService.ListPointWithdrawalCoinSellers:output_type -> hyapp.wallet.v1.ListPointWithdrawalCoinSellersResponse + 292, // 310: hyapp.wallet.v1.WalletService.TransferPointToCoinSeller:output_type -> hyapp.wallet.v1.TransferPointToCoinSellerResponse + 294, // 311: hyapp.wallet.v1.WalletService.GetPointWithdrawalConfig:output_type -> hyapp.wallet.v1.GetPointWithdrawalConfigResponse + 37, // 312: hyapp.wallet.v1.WalletService.FreezeSalaryWithdrawal:output_type -> hyapp.wallet.v1.FreezeSalaryWithdrawalResponse + 39, // 313: hyapp.wallet.v1.WalletService.SettleSalaryWithdrawal:output_type -> hyapp.wallet.v1.SettleSalaryWithdrawalResponse + 41, // 314: hyapp.wallet.v1.WalletService.ReleaseSalaryWithdrawal:output_type -> hyapp.wallet.v1.ReleaseSalaryWithdrawalResponse + 43, // 315: hyapp.wallet.v1.WalletService.FreezePointWithdrawal:output_type -> hyapp.wallet.v1.FreezePointWithdrawalResponse + 45, // 316: hyapp.wallet.v1.WalletService.SettlePointWithdrawal:output_type -> hyapp.wallet.v1.SettlePointWithdrawalResponse + 47, // 317: hyapp.wallet.v1.WalletService.ReleasePointWithdrawal:output_type -> hyapp.wallet.v1.ReleasePointWithdrawalResponse + 62, // 318: hyapp.wallet.v1.WalletService.ListResources:output_type -> hyapp.wallet.v1.ListResourcesResponse + 64, // 319: hyapp.wallet.v1.WalletService.GetResource:output_type -> hyapp.wallet.v1.GetResourceResponse + 71, // 320: hyapp.wallet.v1.WalletService.CreateResource:output_type -> hyapp.wallet.v1.ResourceResponse + 71, // 321: hyapp.wallet.v1.WalletService.UpdateResource:output_type -> hyapp.wallet.v1.ResourceResponse + 71, // 322: hyapp.wallet.v1.WalletService.SetResourceStatus:output_type -> hyapp.wallet.v1.ResourceResponse + 71, // 323: hyapp.wallet.v1.WalletService.DeleteResource:output_type -> hyapp.wallet.v1.ResourceResponse + 70, // 324: hyapp.wallet.v1.WalletService.BatchDeleteResources:output_type -> hyapp.wallet.v1.BatchDeleteResourcesResponse + 73, // 325: hyapp.wallet.v1.WalletService.ListResourceGroups:output_type -> hyapp.wallet.v1.ListResourceGroupsResponse + 75, // 326: hyapp.wallet.v1.WalletService.GetResourceGroup:output_type -> hyapp.wallet.v1.GetResourceGroupResponse + 79, // 327: hyapp.wallet.v1.WalletService.CreateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 79, // 328: hyapp.wallet.v1.WalletService.UpdateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 79, // 329: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 53, // 330: hyapp.wallet.v1.WalletService.PinResourceGroupSnapshot:output_type -> hyapp.wallet.v1.PinResourceGroupSnapshotResponse + 81, // 331: hyapp.wallet.v1.WalletService.ListGiftConfigs:output_type -> hyapp.wallet.v1.ListGiftConfigsResponse + 83, // 332: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:output_type -> hyapp.wallet.v1.ListGiftTypeConfigsResponse + 278, // 333: hyapp.wallet.v1.WalletService.GetGiftCatalogVersion:output_type -> hyapp.wallet.v1.GetGiftCatalogVersionResponse + 92, // 334: hyapp.wallet.v1.WalletService.CreateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse + 88, // 335: hyapp.wallet.v1.WalletService.BatchCreateGiftConfigs:output_type -> hyapp.wallet.v1.BatchCreateGiftConfigsResponse + 92, // 336: hyapp.wallet.v1.WalletService.UpdateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse + 92, // 337: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:output_type -> hyapp.wallet.v1.GiftConfigResponse + 92, // 338: hyapp.wallet.v1.WalletService.DeleteGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse + 85, // 339: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:output_type -> hyapp.wallet.v1.GiftTypeConfigResponse + 97, // 340: hyapp.wallet.v1.WalletService.GrantResource:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 97, // 341: hyapp.wallet.v1.WalletService.GrantResourceGroup:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 97, // 342: hyapp.wallet.v1.WalletService.GrantPinnedResourceGroup:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 97, // 343: hyapp.wallet.v1.WalletService.RevokeResourceGrant:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 299, // 344: hyapp.wallet.v1.WalletService.RevokeUserResource:output_type -> hyapp.wallet.v1.RevokeUserResourceResponse + 99, // 345: hyapp.wallet.v1.WalletService.ListUserResources:output_type -> hyapp.wallet.v1.ListUserResourcesResponse + 101, // 346: hyapp.wallet.v1.WalletService.EquipUserResource:output_type -> hyapp.wallet.v1.EquipUserResourceResponse + 103, // 347: hyapp.wallet.v1.WalletService.UnequipUserResource:output_type -> hyapp.wallet.v1.UnequipUserResourceResponse + 106, // 348: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:output_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse + 108, // 349: hyapp.wallet.v1.WalletService.ListResourceGrants:output_type -> hyapp.wallet.v1.ListResourceGrantsResponse + 111, // 350: hyapp.wallet.v1.WalletService.ListResourceShopItems:output_type -> hyapp.wallet.v1.ListResourceShopItemsResponse + 113, // 351: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:output_type -> hyapp.wallet.v1.UpsertResourceShopItemsResponse + 115, // 352: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:output_type -> hyapp.wallet.v1.ResourceShopItemResponse + 276, // 353: hyapp.wallet.v1.WalletService.ListResourceShopPurchaseOrders:output_type -> hyapp.wallet.v1.ListResourceShopPurchaseOrdersResponse + 117, // 354: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:output_type -> hyapp.wallet.v1.PurchaseResourceShopItemResponse + 120, // 355: hyapp.wallet.v1.WalletService.ListRechargeBills:output_type -> hyapp.wallet.v1.ListRechargeBillsResponse + 123, // 356: hyapp.wallet.v1.WalletService.GetRechargeBillSummary:output_type -> hyapp.wallet.v1.GetRechargeBillSummaryResponse + 126, // 357: hyapp.wallet.v1.WalletService.BatchGetUserRechargeStats:output_type -> hyapp.wallet.v1.BatchGetUserRechargeStatsResponse + 132, // 358: hyapp.wallet.v1.WalletService.GetRechargeBillOverview:output_type -> hyapp.wallet.v1.GetRechargeBillOverviewResponse + 135, // 359: hyapp.wallet.v1.WalletService.RefreshGooglePaymentPrices:output_type -> hyapp.wallet.v1.RefreshGooglePaymentPricesResponse + 138, // 360: hyapp.wallet.v1.WalletService.GetWalletOverview:output_type -> hyapp.wallet.v1.GetWalletOverviewResponse + 141, // 361: hyapp.wallet.v1.WalletService.GetWalletValueSummary:output_type -> hyapp.wallet.v1.GetWalletValueSummaryResponse + 144, // 362: hyapp.wallet.v1.WalletService.GetUserGiftWall:output_type -> hyapp.wallet.v1.GetUserGiftWallResponse + 147, // 363: hyapp.wallet.v1.WalletService.ListRechargeProducts:output_type -> hyapp.wallet.v1.ListRechargeProductsResponse + 149, // 364: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:output_type -> hyapp.wallet.v1.ConfirmGooglePaymentResponse + 151, // 365: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:output_type -> hyapp.wallet.v1.ListAdminRechargeProductsResponse + 155, // 366: hyapp.wallet.v1.WalletService.CreateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse + 155, // 367: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse + 156, // 368: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:output_type -> hyapp.wallet.v1.DeleteRechargeProductResponse + 160, // 369: hyapp.wallet.v1.WalletService.ListThirdPartyPaymentChannels:output_type -> hyapp.wallet.v1.ListThirdPartyPaymentChannelsResponse + 162, // 370: hyapp.wallet.v1.WalletService.SetThirdPartyPaymentMethodStatus:output_type -> hyapp.wallet.v1.ThirdPartyPaymentMethodResponse + 162, // 371: hyapp.wallet.v1.WalletService.UpdateThirdPartyPaymentRate:output_type -> hyapp.wallet.v1.ThirdPartyPaymentMethodResponse + 166, // 372: hyapp.wallet.v1.WalletService.SyncThirdPartyPaymentMethods:output_type -> hyapp.wallet.v1.SyncThirdPartyPaymentMethodsResponse + 168, // 373: hyapp.wallet.v1.WalletService.ListH5RechargeOptions:output_type -> hyapp.wallet.v1.H5RechargeOptionsResponse + 177, // 374: hyapp.wallet.v1.WalletService.CreateH5RechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse + 177, // 375: hyapp.wallet.v1.WalletService.CreateTemporaryRechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse + 177, // 376: hyapp.wallet.v1.WalletService.GetTemporaryRechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse + 174, // 377: hyapp.wallet.v1.WalletService.ListTemporaryRechargeOrders:output_type -> hyapp.wallet.v1.ListTemporaryRechargeOrdersResponse + 177, // 378: hyapp.wallet.v1.WalletService.SubmitH5RechargeTx:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse + 177, // 379: hyapp.wallet.v1.WalletService.GetH5RechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse + 179, // 380: hyapp.wallet.v1.WalletService.VerifyCoinSellerRechargeReceipt:output_type -> hyapp.wallet.v1.VerifyCoinSellerRechargeReceiptResponse + 181, // 381: hyapp.wallet.v1.WalletService.HandleMifapayNotify:output_type -> hyapp.wallet.v1.HandleMifapayNotifyResponse + 183, // 382: hyapp.wallet.v1.WalletService.HandleV5PayNotify:output_type -> hyapp.wallet.v1.HandleV5PayNotifyResponse + 186, // 383: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:output_type -> hyapp.wallet.v1.GetDiamondExchangeConfigResponse + 189, // 384: hyapp.wallet.v1.WalletService.ListWalletTransactions:output_type -> hyapp.wallet.v1.ListWalletTransactionsResponse + 199, // 385: hyapp.wallet.v1.WalletService.ListVipPackages:output_type -> hyapp.wallet.v1.ListVipPackagesResponse + 211, // 386: hyapp.wallet.v1.WalletService.GetVipProgramConfig:output_type -> hyapp.wallet.v1.GetVipProgramConfigResponse + 201, // 387: hyapp.wallet.v1.WalletService.GetMyVip:output_type -> hyapp.wallet.v1.GetMyVipResponse + 233, // 388: hyapp.wallet.v1.WalletService.CheckVipBenefit:output_type -> hyapp.wallet.v1.CheckVipBenefitResponse + 203, // 389: hyapp.wallet.v1.WalletService.PurchaseVip:output_type -> hyapp.wallet.v1.PurchaseVipResponse + 205, // 390: hyapp.wallet.v1.WalletService.DebitCPBreakupFee:output_type -> hyapp.wallet.v1.DebitCPBreakupFeeResponse + 207, // 391: hyapp.wallet.v1.WalletService.DebitWheelDraw:output_type -> hyapp.wallet.v1.DebitWheelDrawResponse + 209, // 392: hyapp.wallet.v1.WalletService.GrantVip:output_type -> hyapp.wallet.v1.GrantVipResponse + 227, // 393: hyapp.wallet.v1.WalletService.GrantVipTrialCard:output_type -> hyapp.wallet.v1.GrantVipTrialCardResponse + 229, // 394: hyapp.wallet.v1.WalletService.EquipVipTrialCard:output_type -> hyapp.wallet.v1.EquipVipTrialCardResponse + 231, // 395: hyapp.wallet.v1.WalletService.UnequipVipTrialCard:output_type -> hyapp.wallet.v1.UnequipVipTrialCardResponse + 236, // 396: hyapp.wallet.v1.WalletService.ListAdminVipLevels:output_type -> hyapp.wallet.v1.ListAdminVipLevelsResponse + 238, // 397: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:output_type -> hyapp.wallet.v1.UpdateAdminVipLevelsResponse + 213, // 398: hyapp.wallet.v1.WalletService.UpdateAdminVipProgramConfig:output_type -> hyapp.wallet.v1.UpdateAdminVipProgramConfigResponse + 215, // 399: hyapp.wallet.v1.WalletService.UpdateMyVipSettings:output_type -> hyapp.wallet.v1.UpdateMyVipSettingsResponse + 221, // 400: hyapp.wallet.v1.WalletService.GetMyCurrentVipDailyCoinRebate:output_type -> hyapp.wallet.v1.GetMyCurrentVipDailyCoinRebateResponse + 223, // 401: hyapp.wallet.v1.WalletService.ListMyVipDailyCoinRebateStatuses:output_type -> hyapp.wallet.v1.ListMyVipDailyCoinRebateStatusesResponse + 225, // 402: hyapp.wallet.v1.WalletService.ClaimVipDailyCoinRebate:output_type -> hyapp.wallet.v1.ClaimVipDailyCoinRebateResponse + 240, // 403: hyapp.wallet.v1.WalletService.CreditTaskReward:output_type -> hyapp.wallet.v1.CreditTaskRewardResponse + 242, // 404: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:output_type -> hyapp.wallet.v1.CreditLuckyGiftRewardResponse + 244, // 405: hyapp.wallet.v1.WalletService.CreditWheelReward:output_type -> hyapp.wallet.v1.CreditWheelRewardResponse + 246, // 406: hyapp.wallet.v1.WalletService.CreditRoomTurnoverReward:output_type -> hyapp.wallet.v1.CreditRoomTurnoverRewardResponse + 248, // 407: hyapp.wallet.v1.WalletService.CreditInviteActivityReward:output_type -> hyapp.wallet.v1.CreditInviteActivityRewardResponse + 250, // 408: hyapp.wallet.v1.WalletService.CreditAgencyOpeningReward:output_type -> hyapp.wallet.v1.CreditAgencyOpeningRewardResponse + 252, // 409: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:output_type -> hyapp.wallet.v1.ApplyGameCoinChangeResponse + 257, // 410: hyapp.wallet.v1.WalletService.GetRedPacketConfig:output_type -> hyapp.wallet.v1.GetRedPacketConfigResponse + 259, // 411: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:output_type -> hyapp.wallet.v1.UpdateRedPacketConfigResponse + 261, // 412: hyapp.wallet.v1.WalletService.CreateRedPacket:output_type -> hyapp.wallet.v1.CreateRedPacketResponse + 263, // 413: hyapp.wallet.v1.WalletService.ClaimRedPacket:output_type -> hyapp.wallet.v1.ClaimRedPacketResponse + 265, // 414: hyapp.wallet.v1.WalletService.ListRedPackets:output_type -> hyapp.wallet.v1.ListRedPacketsResponse + 267, // 415: hyapp.wallet.v1.WalletService.GetRedPacket:output_type -> hyapp.wallet.v1.GetRedPacketResponse + 269, // 416: hyapp.wallet.v1.WalletService.ExpireRedPackets:output_type -> hyapp.wallet.v1.ExpireRedPacketsResponse + 271, // 417: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:output_type -> hyapp.wallet.v1.RetryRedPacketRefundResponse + 287, // [287:418] is the sub-list for method output_type + 156, // [156:287] is the sub-list for method input_type + 156, // [156:156] is the sub-list for extension type_name + 156, // [156:156] is the sub-list for extension extendee + 0, // [0:156] is the sub-list for field type_name } func init() { file_proto_wallet_v1_wallet_proto_init() } @@ -32673,9 +29788,9 @@ func file_proto_wallet_v1_wallet_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_wallet_v1_wallet_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_wallet_v1_wallet_proto_rawDesc), len(file_proto_wallet_v1_wallet_proto_rawDesc)), NumEnums: 0, - NumMessages: 296, + NumMessages: 301, NumExtensions: 0, NumServices: 2, }, @@ -32684,7 +29799,6 @@ 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 8db79a85..a81f76c6 100644 --- a/api/proto/wallet/v1/wallet.proto +++ b/api/proto/wallet/v1/wallet.proto @@ -1196,6 +1196,8 @@ message ResourceShopItemInput { int64 effective_from_ms = 5; int64 effective_to_ms = 6; int32 sort_order = 7; + // coin_price 是当前售卖规格自己的金币价;新建传 0 使用资源列表价,更新已有规格传 0 保留当前售价。 + int64 coin_price = 8; } message ListResourceShopItemsRequest { @@ -2025,6 +2027,7 @@ message VipBenefit { string metadata_json = 12; int64 created_at_ms = 13; int64 updated_at_ms = 14; + VipBenefitPresentation presentation = 15; } message VipLevel { @@ -2082,13 +2085,16 @@ message VipTrialCard { } // VipUserSettings 是用户按 App 隔离的可关闭 VIP 功能偏好。没有持久记录时 wallet -// 仍返回两个默认开启值,updated_at_ms=0;设置本身不授予任何 VIP 权益。 +// 仍返回五个默认开启值,updated_at_ms=0;设置本身不授予任何 VIP 权益。 message VipUserSettings { string app_code = 1; int64 user_id = 2; bool room_entry_notice_enabled = 3; bool online_global_notice_enabled = 4; int64 updated_at_ms = 5; + bool hide_profile_data_enabled = 6; + bool anonymous_profile_visit_enabled = 7; + bool leaderboard_invisible_enabled = 8; } // VipState 同时返回付费会员、当前佩戴体验卡和最终生效会员,避免调用方自行合并两层状态。 @@ -2145,6 +2151,8 @@ message PurchaseVipResponse { int64 coin_balance_after = 5; repeated VipRewardItem reward_items = 6; VipState state = 7; + // coin_balance 是购买事务提交后的带版本余额快照;coin_balance_after 仅保留旧客户端兼容。 + AssetBalance coin_balance = 8; } message DebitCPBreakupFeeRequest { @@ -2229,6 +2237,9 @@ message UpdateMyVipSettingsRequest { int64 user_id = 3; optional bool room_entry_notice_enabled = 4; optional bool online_global_notice_enabled = 5; + optional bool hide_profile_data_enabled = 6; + optional bool anonymous_profile_visit_enabled = 7; + optional bool leaderboard_invisible_enabled = 8; } message UpdateMyVipSettingsResponse { @@ -2949,6 +2960,52 @@ message GetPointWithdrawalConfigResponse { string policy_instance_code = 5; } +// VipBenefitPreviewItem 是同一权益下的一项预览内容;独立稳定键允许 Flutter 在多图、动态资源间切换, +// 且不会把数组下标误当成资源身份。 +message VipBenefitPreviewItem { + string preview_id = 1; + string title = 2; + // media_type: image/animation;animation 使用 animation_url,静态兜底使用 preview_url/asset_url。 + string media_type = 3; + string asset_url = 4; + string preview_url = 5; + string animation_url = 6; + // composition_type: none/user_avatar_center/user_avatar_waveform,客户端据此把当前用户头像合成到预览中。 + string composition_type = 7; + int32 sort_order = 8; +} + +message VipBenefitNumericReward { + string label = 1; + int64 value = 2; + string unit = 3; + // period: once/daily/monthly,由服务端配置返回,客户端只展示不据此结算。 + string period = 4; +} + +// VipBenefitPresentation 是 Flutter 可直接渲染的结构化特权说明。metadata_json 继续保留后台扩展和 +// 历史兼容,但客户端不得按 benefit_code 自行解析 metadata_json 生成预览。 +message VipBenefitPresentation { + string description = 1; + repeated VipBenefitPreviewItem preview_items = 2; + VipBenefitNumericReward numeric_reward = 3; +} + +// RevokeUserResourceRequest targets one entitlement instead of its source grant. This keeps +// resource-group siblings intact when an operator removes a single badge/frame from a user. +message RevokeUserResourceRequest { + string request_id = 1; + string app_code = 2; + int64 user_id = 3; + string entitlement_id = 4; + string reason = 5; + int64 operator_user_id = 6; +} + +message RevokeUserResourceResponse { + UserResourceEntitlement resource = 1; +} + // WalletCronService 只给 cron-service 调用;账务状态仍由 wallet-service owner 修改。 service WalletCronService { rpc ProcessHostSalaryDailySettlementBatch(CronBatchRequest) returns (CronBatchResponse); @@ -3013,6 +3070,7 @@ service WalletService { rpc GrantResourceGroup(GrantResourceGroupRequest) returns (ResourceGrantResponse); rpc GrantPinnedResourceGroup(GrantPinnedResourceGroupRequest) returns (ResourceGrantResponse); rpc RevokeResourceGrant(RevokeResourceGrantRequest) returns (ResourceGrantResponse); + rpc RevokeUserResource(RevokeUserResourceRequest) returns (RevokeUserResourceResponse); rpc ListUserResources(ListUserResourcesRequest) returns (ListUserResourcesResponse); rpc EquipUserResource(EquipUserResourceRequest) returns (EquipUserResourceResponse); rpc UnequipUserResource(UnequipUserResourceRequest) returns (UnequipUserResourceResponse); diff --git a/api/proto/wallet/v1/wallet_grpc.pb.go b/api/proto/wallet/v1/wallet_grpc.pb.go index 141c0633..5a1368a3 100644 --- a/api/proto/wallet/v1/wallet_grpc.pb.go +++ b/api/proto/wallet/v1/wallet_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.6.2 -// - protoc v5.29.2 +// - protoc v7.35.0 // source: proto/wallet/v1/wallet.proto package walletv1 @@ -292,6 +292,7 @@ const ( WalletService_GrantResourceGroup_FullMethodName = "/hyapp.wallet.v1.WalletService/GrantResourceGroup" WalletService_GrantPinnedResourceGroup_FullMethodName = "/hyapp.wallet.v1.WalletService/GrantPinnedResourceGroup" WalletService_RevokeResourceGrant_FullMethodName = "/hyapp.wallet.v1.WalletService/RevokeResourceGrant" + WalletService_RevokeUserResource_FullMethodName = "/hyapp.wallet.v1.WalletService/RevokeUserResource" WalletService_ListUserResources_FullMethodName = "/hyapp.wallet.v1.WalletService/ListUserResources" WalletService_EquipUserResource_FullMethodName = "/hyapp.wallet.v1.WalletService/EquipUserResource" WalletService_UnequipUserResource_FullMethodName = "/hyapp.wallet.v1.WalletService/UnequipUserResource" @@ -427,6 +428,7 @@ type WalletServiceClient interface { GrantResourceGroup(ctx context.Context, in *GrantResourceGroupRequest, opts ...grpc.CallOption) (*ResourceGrantResponse, error) GrantPinnedResourceGroup(ctx context.Context, in *GrantPinnedResourceGroupRequest, opts ...grpc.CallOption) (*ResourceGrantResponse, error) RevokeResourceGrant(ctx context.Context, in *RevokeResourceGrantRequest, opts ...grpc.CallOption) (*ResourceGrantResponse, error) + RevokeUserResource(ctx context.Context, in *RevokeUserResourceRequest, opts ...grpc.CallOption) (*RevokeUserResourceResponse, error) ListUserResources(ctx context.Context, in *ListUserResourcesRequest, opts ...grpc.CallOption) (*ListUserResourcesResponse, error) EquipUserResource(ctx context.Context, in *EquipUserResourceRequest, opts ...grpc.CallOption) (*EquipUserResourceResponse, error) UnequipUserResource(ctx context.Context, in *UnequipUserResourceRequest, opts ...grpc.CallOption) (*UnequipUserResourceResponse, error) @@ -1040,6 +1042,16 @@ func (c *walletServiceClient) RevokeResourceGrant(ctx context.Context, in *Revok return out, nil } +func (c *walletServiceClient) RevokeUserResource(ctx context.Context, in *RevokeUserResourceRequest, opts ...grpc.CallOption) (*RevokeUserResourceResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(RevokeUserResourceResponse) + err := c.cc.Invoke(ctx, WalletService_RevokeUserResource_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *walletServiceClient) ListUserResources(ctx context.Context, in *ListUserResourcesRequest, opts ...grpc.CallOption) (*ListUserResourcesResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ListUserResourcesResponse) @@ -1830,6 +1842,7 @@ type WalletServiceServer interface { GrantResourceGroup(context.Context, *GrantResourceGroupRequest) (*ResourceGrantResponse, error) GrantPinnedResourceGroup(context.Context, *GrantPinnedResourceGroupRequest) (*ResourceGrantResponse, error) RevokeResourceGrant(context.Context, *RevokeResourceGrantRequest) (*ResourceGrantResponse, error) + RevokeUserResource(context.Context, *RevokeUserResourceRequest) (*RevokeUserResourceResponse, error) ListUserResources(context.Context, *ListUserResourcesRequest) (*ListUserResourcesResponse, error) EquipUserResource(context.Context, *EquipUserResourceRequest) (*EquipUserResourceResponse, error) UnequipUserResource(context.Context, *UnequipUserResourceRequest) (*UnequipUserResourceResponse, error) @@ -2072,6 +2085,9 @@ func (UnimplementedWalletServiceServer) GrantPinnedResourceGroup(context.Context func (UnimplementedWalletServiceServer) RevokeResourceGrant(context.Context, *RevokeResourceGrantRequest) (*ResourceGrantResponse, error) { return nil, status.Error(codes.Unimplemented, "method RevokeResourceGrant not implemented") } +func (UnimplementedWalletServiceServer) RevokeUserResource(context.Context, *RevokeUserResourceRequest) (*RevokeUserResourceResponse, error) { + return nil, status.Error(codes.Unimplemented, "method RevokeUserResource not implemented") +} func (UnimplementedWalletServiceServer) ListUserResources(context.Context, *ListUserResourcesRequest) (*ListUserResourcesResponse, error) { return nil, status.Error(codes.Unimplemented, "method ListUserResources not implemented") } @@ -3266,6 +3282,24 @@ func _WalletService_RevokeResourceGrant_Handler(srv interface{}, ctx context.Con return interceptor(ctx, in, info, handler) } +func _WalletService_RevokeUserResource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RevokeUserResourceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).RevokeUserResource(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_RevokeUserResource_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).RevokeUserResource(ctx, req.(*RevokeUserResourceRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _WalletService_ListUserResources_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListUserResourcesRequest) if err := dec(in); err != nil { @@ -4799,6 +4833,10 @@ var WalletService_ServiceDesc = grpc.ServiceDesc{ MethodName: "RevokeResourceGrant", Handler: _WalletService_RevokeResourceGrant_Handler, }, + { + MethodName: "RevokeUserResource", + Handler: _WalletService_RevokeUserResource_Handler, + }, { MethodName: "ListUserResources", Handler: _WalletService_ListUserResources_Handler, diff --git a/docker-compose.yml b/docker-compose.yml index 226b584a..742ad547 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -132,6 +132,8 @@ services: depends_on: mysql: condition: service_healthy + redis: + condition: service_healthy rocketmq-broker: condition: service_started healthcheck: @@ -381,10 +383,14 @@ services: redis: image: redis:7.4-alpine container_name: hyapp-redis + # Session denylist 不能被内存淘汰;AOF + volume 保证正常重启时先恢复撤销事实再接受连接。 + command: ["redis-server", "--appendonly", "yes", "--appendfsync", "everysec", "--maxmemory-policy", "noeviction"] environment: TZ: UTC ports: - "13379:6379" + volumes: + - redis-data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s @@ -393,4 +399,5 @@ services: volumes: mysql-data: + redis-data: rocketmq-store: diff --git a/docs/Fami_VIP_Flutter对接方案.md b/docs/Fami_VIP_Flutter对接方案.md index 18c81fff..8e787fda 100644 --- a/docs/Fami_VIP_Flutter对接方案.md +++ b/docs/Fami_VIP_Flutter对接方案.md @@ -2,6 +2,14 @@ 本文定义 Flutter 与当前已落地 VIP 后端的对接契约。客户端不要重复实现 VIP 状态机,也不要按 App、VIP 等级或最低解锁等级推导权限。界面和文案统一使用“VIP”,不再使用“SVIP”。 +## 0. 当前稳定契约 + +- `GET /vip/me`、`GET /vip/packages`、购买、佩戴体验卡、卸下体验卡的 `state` 完全同构,固定包含 `paid_vip`、`equipped_trial_card`、`effective_vip`、`effective_source`、`effective_benefits`、`evaluated_at_ms`、完整 `program_config`、完整 `user_settings`。写成功后整体替换 store,禁止局部合并。 +- `user_settings` 固定包含 5 项开关:进房通知、上线全服通知、隐藏个人数据、匿名访问主页、榜单隐身;均按 App 隔离、无记录默认开启。 +- 权益富展示读取结构化 `benefits[].presentation`。它覆盖说明文案、多项静态/动态预览、用户头像合成方式和数值奖励;Flutter 不解析 `metadata_json` 生成 UI。 +- VIP 购买后的余额读取带 `version` 的 `coin_balance`;`coin_balance_after` 仅兼容旧客户端。历史幂等回放若 `version=0`,必须重新请求钱包余额。 +- 业务分支只判断稳定 `code`,不得解析 `message`。精确 JSON、`presentation` Schema 和错误码矩阵以 [新版 VIP 权限策略 Flutter 客户端对接文档](./新版VIP权限策略_Flutter客户端对接文档.md) 为唯一协议定义;本文后续较短 JSON 只解释场景,不定义裁剪响应。 + ## 1. 通用约定 - 地址前缀:`/api/v1`,实际 host 按环境配置。 @@ -82,6 +90,20 @@ class VipEntitlementSnapshot { return has('online_global_notice') && settings.onlineGlobalNoticeEnabled; } + + bool allowsHideProfileData() { + return has('hide_profile_data') && settings.hideProfileDataEnabled; + } + + bool allowsAnonymousProfileVisit() { + return has('anonymous_profile_visit') && + settings.anonymousProfileVisitEnabled; + } + + bool allowsLeaderboardInvisible() { + return has('leaderboard_invisible') && + settings.leaderboardInvisibleEnabled; + } } ``` @@ -106,7 +128,7 @@ final benefitHandlers = { | 功能入口 | `store.has(code)` 决定正常态/锁态和升级引导 | 点击后的写接口再次鉴权 | | 装扮权益 | 同时检查权益和服务端资源字段;素材为空时使用无图兜底 | 保存/佩戴仍调用资源 owner 接口 | | 进房通知 | 本人的设置页读 store;房间内展示读 Join/房间 IM 快照 | room-service 在 Join 时校验 | -| 防踢、防禁言 | 不根据目标用户本地 VIP 快照禁用管理按钮 | 正常调用房管接口,处理 `PERMISSION_DENIED` | +| 防踢、防禁言 | 不根据目标用户本地 VIP 快照禁用管理按钮 | 正常调用房管接口,分别处理 `VIP_ANTI_KICK`、`VIP_ANTI_MUTE` | | 金币返现 | `daily_coin_rebate` 可用于显示入口,金额/状态不在本地推导 | current/statuses/claim 接口决定资格和入账 | | 上线全服通知 | 权益和开关满足时发起 `/vip/online-notice` | activity/notice 链路异步投递 | @@ -176,7 +198,7 @@ final benefitHandlers = { | 体验卡背包 | `GET /api/v1/users/me/resources?resource_type=vip_trial_card` | 只更新卡列表 | | 佩戴体验卡 | `POST /api/v1/vip/trial-cards/{entitlement_id}/equip` | 成功后使用响应 `state` | | 卸下体验卡 | `DELETE /api/v1/vip/trial-cards/equipped` | 成功后使用响应 `state` | -| VIP 用户开关 | `GET/PATCH /api/v1/vip/settings` | 更新 `user_settings`,不改变权益集 | +| VIP 功能开关 | `GET/PATCH /api/v1/vip/settings` | 更新 `user_settings`,不改变权益集 | | 金币返现 | `/api/v1/vip/coin-rebates/*` | 使用服务端记录和余额回执 | | 上线全服通知 | `POST /api/v1/vip/online-notice` | 只创建异步播报事件 | @@ -250,6 +272,22 @@ final benefitHandlers = { "auto_equip": false, "sort_order": 110, "metadata_json": "", + "presentation": { + "description": "进入房间时展示动态背景和用户头像", + "preview_items": [ + { + "preview_id": "room_background_gold", + "title": "鎏金房间背景", + "media_type": "animation", + "asset_url": "https://cdn.example/vip/room-bg.png", + "preview_url": "https://cdn.example/vip/room-bg-preview.png", + "animation_url": "https://cdn.example/vip/room-bg.svga", + "composition_type": "user_avatar_center", + "sort_order": 10 + } + ], + "numeric_reward": null + }, "created_at_ms": 0, "updated_at_ms": 0 } @@ -302,6 +340,9 @@ final benefitHandlers = { "user_id": 10001, "room_entry_notice_enabled": true, "online_global_notice_enabled": true, + "hide_profile_data_enabled": true, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true, "updated_at_ms": 0 } } @@ -412,7 +453,8 @@ final benefitHandlers = { "execution_scope": "room", "auto_equip": false, "sort_order": 290, - "metadata_json": "" + "metadata_json": "", + "presentation": null } ], "evaluated_at_ms": 1780101000000, @@ -426,6 +468,9 @@ final benefitHandlers = { "user_id": 10001, "room_entry_notice_enabled": true, "online_global_notice_enabled": true, + "hide_profile_data_enabled": true, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true, "updated_at_ms": 0 } } @@ -447,7 +492,7 @@ final benefitHandlers = { - 当体验卡被佩戴时,不限制卡等级高低,它会覆盖付费 VIP 成为 `effective_vip`;卸下或过期后自然回落到仍有效的 `paid_vip`。 - 体验卡状态下,`daily_coin_rebate` 不会进入 `effective_benefits`。Flutter 不要只看卡等级猜测权益。 - 无 VIP 时,`effective_source="none"`、`effective_vip.active=false`、`effective_benefits=[]`。 -- `user_settings.updated_at_ms=0` 表示用户尚未修改,两个开关使用默认开启值;设置在无 VIP 时也保留,但不会单独授权。 +- `user_settings.updated_at_ms=0` 表示用户尚未修改,5 个开关使用默认开启值;设置在无 VIP 时也保留,但不会单独授权。 ## 8. 购买、续期和升级 @@ -490,6 +535,12 @@ final benefitHandlers = { }, "coin_spent": 4000, "coin_balance_after": 6000, + "coin_balance": { + "asset_type": "COIN", + "available_amount": 6000, + "frozen_amount": 0, + "version": 18 + }, "reward_items": [], "program_config": { "app_code": "fami", @@ -523,6 +574,16 @@ final benefitHandlers = { "app_code": "fami", "program_type": "tiered_privilege_v1", "config_version": 7 + }, + "user_settings": { + "app_code": "fami", + "user_id": 10001, + "room_entry_notice_enabled": true, + "online_global_notice_enabled": true, + "hide_profile_data_enabled": true, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true, + "updated_at_ms": 0 } } } @@ -549,8 +610,9 @@ Flutter 收到后用 `event_id` 做会话内去重,再调 `GET /vip/me`。不 - Fami 同级续期:新截止时间 = 旧 `expires_at_ms` + `duration_ms`,保留剩余时间。 - Fami 高级升级:新截止时间 = 购买时间 + `duration_ms`,旧低等级剩余时间丢弃。例如 VIP3 剩 15 天购买 VIP4 30 天,结果是 VIP4 30 天。 - 购买更低等级由后端拒绝,错误 `VIP_DOWNGRADE_NOT_ALLOWED`。 -- 余额不足返回 `INSUFFICIENT_BALANCE`;等级未启用返回 `VIP_LEVEL_DISABLED`。 +- 余额不足返回 `VIP_INSUFFICIENT_COIN`;套餐不存在、停用或不可购买返回 `VIP_PACKAGE_NOT_PURCHASABLE`;体系停用返回 `VIP_PROGRAM_INACTIVE`。 - 如果购买时仍佩戴体验卡,购买结果会写入 `paid_vip`,但当前展示仍可能是 `effective_source="trial"`。购买成功页也必须以返回的 `state.effective_vip` 为准。 +- 购买成功后用 `coin_balance.version` 防止旧响应覆盖新余额。`version=0` 只可能来自升级前的历史幂等订单,必须刷新钱包余额。 ## 9. 体验卡背包列表 @@ -660,17 +722,73 @@ Flutter 收到后用 `event_id` 做会话内去重,再调 `GET /vip/me`。不 "program_config": { "app_code": "fami", "program_type": "tiered_privilege_v1", - "trial_card_enabled": true + "level_count": 9, + "same_level_expiry_policy": "extend_remaining", + "upgrade_expiry_policy": "replace_from_now", + "downgrade_purchase_policy": "reject", + "benefit_inheritance_policy": "target_only", + "grant_mode": "trial_card", + "trial_card_enabled": true, + "status": "active", + "config_version": 7 }, "state": { - "effective_source": "trial", + "paid_vip": null, + "equipped_trial_card": { + "trial_card_id": "vip_trial_card_b", + "entitlement_id": "ent_card_b", + "resource_id": 102, + "user_id": 10001, + "level": 4, + "name": "VIP4", + "status": "active", + "equipped": true, + "duration_ms": 1728000000, + "effective_at_ms": 1780200000000, + "expires_at_ms": 1781928000000, + "remaining_duration_ms": 1700000000, + "grant_source": "admin_grant", + "source_grant_id": "grant_b", + "created_at_ms": 1780200000000, + "updated_at_ms": 1780200000000 + }, "effective_vip": { + "user_id": 10001, "level": 4, "name": "VIP4", "active": true, - "expires_at_ms": 1781928000000 + "started_at_ms": 1780200000000, + "expires_at_ms": 1781928000000, + "updated_at_ms": 1780200000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 }, - "effective_benefits": [] + "effective_source": "trial", + "effective_benefits": [], + "evaluated_at_ms": 1780228000000, + "program_config": { + "app_code": "fami", + "program_type": "tiered_privilege_v1", + "level_count": 9, + "same_level_expiry_policy": "extend_remaining", + "upgrade_expiry_policy": "replace_from_now", + "downgrade_purchase_policy": "reject", + "benefit_inheritance_policy": "target_only", + "grant_mode": "trial_card", + "trial_card_enabled": true, + "status": "active", + "config_version": 7 + }, + "user_settings": { + "app_code": "fami", + "user_id": 10001, + "room_entry_notice_enabled": true, + "online_global_notice_enabled": true, + "hide_profile_data_enabled": true, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true, + "updated_at_ms": 0 + } }, "server_time_ms": 1780228000000 } @@ -710,22 +828,67 @@ Flutter 收到后用 `event_id` 做会话内去重,再调 `GET /vip/me`。不 "unequipped": true, "program_config": { "app_code": "fami", - "program_type": "tiered_privilege_v1" + "program_type": "tiered_privilege_v1", + "level_count": 9, + "same_level_expiry_policy": "extend_remaining", + "upgrade_expiry_policy": "replace_from_now", + "downgrade_purchase_policy": "reject", + "benefit_inheritance_policy": "target_only", + "grant_mode": "trial_card", + "trial_card_enabled": true, + "status": "active", + "config_version": 7 }, "state": { - "effective_source": "paid", "paid_vip": { + "user_id": 10001, "level": 3, "name": "VIP3", - "active": true + "active": true, + "started_at_ms": 1780000000000, + "expires_at_ms": 1782592000000, + "updated_at_ms": 1780000000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 }, "equipped_trial_card": null, "effective_vip": { + "user_id": 10001, "level": 3, "name": "VIP3", - "active": true + "active": true, + "started_at_ms": 1780000000000, + "expires_at_ms": 1782592000000, + "updated_at_ms": 1780000000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 }, - "effective_benefits": [] + "effective_source": "paid", + "effective_benefits": [], + "evaluated_at_ms": 1780229000000, + "program_config": { + "app_code": "fami", + "program_type": "tiered_privilege_v1", + "level_count": 9, + "same_level_expiry_policy": "extend_remaining", + "upgrade_expiry_policy": "replace_from_now", + "downgrade_purchase_policy": "reject", + "benefit_inheritance_policy": "target_only", + "grant_mode": "trial_card", + "trial_card_enabled": true, + "status": "active", + "config_version": 7 + }, + "user_settings": { + "app_code": "fami", + "user_id": 10001, + "room_entry_notice_enabled": true, + "online_global_notice_enabled": true, + "hide_profile_data_enabled": true, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true, + "updated_at_ms": 0 + } }, "server_time_ms": 1780229000000 } @@ -898,7 +1061,7 @@ Fami(`trial_card`)发一张 30 天体验卡到背包,不自动佩戴: - 用 `event_id` 去重。重连/重复 Join 仍可收到进房展示事件,不要以本地 presence 猜测是否展示。 - 进房 VIP 查询失败时后端会降级为普通进房,不阻断进房主链路。 -## 14. VIP 通知开关 +## 14. VIP 功能开关 ### 接口地址 @@ -909,17 +1072,15 @@ Fami(`trial_card`)发一张 30 天体验卡到背包,不自动佩戴: ### 参数 -GET 无参数。PATCH 是局部更新,两个字段至少传一个;显式 `false` 不能被当成未传: +GET 无参数。PATCH 是局部更新,5 个字段至少传一个;显式 `false` 不能被当成未传: ```json { - "room_entry_notice_enabled": false -} -``` - -```json -{ - "online_global_notice_enabled": true + "room_entry_notice_enabled": false, + "online_global_notice_enabled": true, + "hide_profile_data_enabled": false, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true } ``` @@ -940,6 +1101,9 @@ GET: "user_id": 10001, "room_entry_notice_enabled": true, "online_global_notice_enabled": false, + "hide_profile_data_enabled": true, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true, "updated_at_ms": 1780300000000 }, "evaluated_at_ms": 1780300001000 @@ -960,6 +1124,9 @@ PATCH: "user_id": 10001, "room_entry_notice_enabled": false, "online_global_notice_enabled": false, + "hide_profile_data_enabled": false, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true, "updated_at_ms": 1780300010000 }, "server_time_ms": 1780300010000 @@ -967,7 +1134,7 @@ PATCH: } ``` -用户从未修改过时,两项默认为 `true`,`updated_at_ms=0`。PATCH 只改本次提交的字段,不会覆盖另一项。 +用户从未修改过时,5 项均默认为 `true`,`updated_at_ms=0`。PATCH 只改本次提交的字段,不会覆盖其他项。 ### 相关 IM @@ -978,6 +1145,7 @@ PATCH: - 开关是用户偏好,不是权益;无 VIP 时也可保存,但不会产生进房或上线播报。 - 进房展示必须同时满足 `effective_benefits` 含 `room_entry_notice` 且 `room_entry_notice_enabled=true`。 - 上线展示必须同时满足 `online_global_notice` 权益和开关;最终以触发接口的服务端判定为准。 +- 隐藏个人数据、匿名访问主页、榜单隐身分别要求对应权益和同名开关同时成立;客户端不得只看设置值授权。 - 设置按 App 隔离,Fami 的修改不影响 Lalu。 ## 15. 每日 VIP 金币返现 @@ -1246,7 +1414,7 @@ Flutter 先把 `action_param` 再解析为 JSON。点击前可将页面上所有 - 同进程同 UTC 日首次进入 App,且 `/vip/me` 中具有 `online_global_notice` 资格、`online_global_notice_enabled=true` 时触发。成功后当日不再产生新 command。 - 超时/5xx 可用同一 `command_id` 重试;不能在同进程同日换 command 规避幂等。 - 杀掉进程后内存清空,新进程产生新 `process_boot_id` 和 `command_id`,同日可再播一次,这是已确认产品规则。 -- 权益过期、后台停用、体验卡不允许或用户关闭开关时,服务端返回 `PERMISSION_DENIED`;Flutter 不做本地飘屏,可重拉 `/vip/me`。 +- 权益过期、后台停用、体验卡不允许或用户关闭开关时,服务端返回 `VIP_BENEFIT_REQUIRED`;Flutter 不做本地飘屏,可重拉 `/vip/me`。 - 不把“每日一次”放到服务端持久化去重,否则无法满足杀进程后同日可再展示。 ## 17. 权益场景和完成边界 @@ -1258,10 +1426,10 @@ Flutter 先把 `action_param` 再解析为 JSON。点击前可将页面上所有 | 同级续期 | 不在本地计算,以响应为准 | 已强制,从旧截止时间累加 | | 体验卡自由切换 | 按 `entitlement_id` 佩戴,每次直接替换全局 `state` | 已强制,不限等级,不作废旧卡,不改绝对截止时间 | | 体验卡权益 | 只渲染 `effective_benefits` 资格 | 已强制过滤 `trial_enabled=false`,金币返现不给体验卡 | -| VIP 通知开关 | 读 `state.user_settings`,用 PATCH 局部修改 | 已按 App 持久化,无记录默认两项开启,开关不单独授权 | +| VIP 功能开关 | 读 `state.user_settings`,用 PATCH 局部修改 | 已按 App 持久化,无记录默认 5 项开启,开关不单独授权 | | 进房高亮通知 | 本人首屏读 Join HTTP `effective_vip`,其他成员消费当前房间 `room_user_joined` | 后端已同时校验权益与用户开关,并透传 Join HTTP 和当前房间 IM;不发全服 | -| 防踢 | 房管操作返回 `PERMISSION_DENIED` 时显示不可踢,不做本地预判 | 已在 room-service 强制;只阻止普通房主/管理员的 KickUser | -| 防禁言 | 房管操作返回 `PERMISSION_DENIED` 时显示不可禁言,解禁始终可发起 | 已在 room-service 强制;只阻止普通房主/管理员新增禁言 | +| 防踢 | 房管操作返回 `VIP_ANTI_KICK` 时显示不可踢,不做本地预判 | 已在 room-service 强制;只阻止普通房主/管理员的 KickUser | +| 防禁言 | 房管操作返回 `VIP_ANTI_MUTE` 时显示不可禁言,解禁始终可发起 | 已在 room-service 强制;只阻止普通房主/管理员新增禁言 | | 平台封禁/风控/超级管理 | Flutter 不作 VIP 免责提示 | 独立 `SystemEvictUser` 治理链路会绕过防踢,VIP 不能绕过平台治理 | | 自定义房间背景 | 按现有房间背景页面调用 | `tiered_privilege_v1` 已由 room-service 强制校验 `custom_room_background` | | 金币返现 | 消费 system inbox,批量恢复状态,手动领取后使用响应余额 | 已完成 UTC 日资格、异步系统消息、24 小时窗口和 wallet 原子入账;体验卡不参与 | @@ -1277,4 +1445,4 @@ Flutter 先把 `action_param` 再解析为 JSON。点击前可将页面上所有 5. 所有房间、个人页和消息展示都使用 `effective_vip`,不要用 `paid_vip` 覆盖体验卡展示。 6. system inbox 遇到 `action_type=vip_coin_rebate_claim` 时,批量用 statuses 恢复真实状态;领取成功后替换余额与返现状态。 7. IM 登录并加入全局播报群后,按进程内 UTC 日规则触发 `/vip/online-notice`;收到 `vip_online_notice` 时用 `event_id` 去重。 -8. 修改通知开关成功后,用 PATCH 响应替换本地 `user_settings`,不修改 `effective_benefits`。 +8. 修改 VIP 功能开关成功后,用 PATCH 响应替换本地 `user_settings`,不修改 `effective_benefits`。 diff --git a/docs/VIP系统架构.md b/docs/VIP系统架构.md index 5b82fe60..77254a7a 100644 --- a/docs/VIP系统架构.md +++ b/docs/VIP系统架构.md @@ -85,12 +85,19 @@ Fami 的 VIP1–VIP9 初始全部为 `disabled`。30 天只是不产生零时长 ### 用户功能开关 -`user_vip_settings` 按 `(app_code,user_id)` 保存两个用户偏好: +`user_vip_settings` 按 `(app_code,user_id)` 保存 5 个用户偏好: - `room_entry_notice_enabled`:进房 VIP 高亮通知; -- `online_global_notice_enabled`:上线 VIP 全服飘屏。 +- `online_global_notice_enabled`:上线 VIP 全服飘屏; +- `hide_profile_data_enabled`:隐藏个人数据; +- `anonymous_profile_visit_enabled`:匿名访问主页; +- `leaderboard_invisible_enabled`:榜单隐身。 -无记录时两项默认为 `true`,首次修改才写行。偏好不授予权益:无 VIP 或对应等级没有权益时,即使开关为开也不会放行。用户可在无 VIP、VIP 过期或切换体验卡时保留偏好;Fami 与 Lalu 互不影响。 +无记录时 5 项默认为 `true`,首次修改才写行。偏好不授予权益:无 VIP 或对应等级没有权益时,即使开关为开也不会放行。用户可在无 VIP、VIP 过期或切换体验卡时保留偏好;Fami 与 Lalu 互不影响。 + +### 权益展示投影 + +`vip_level_benefits.metadata_json.presentation` 是后台保存的扩展配置,wallet 在读取时解析并校验,跨服务和 HTTP 统一投影为结构化 `presentation`。它包含说明文案、多项预览、`image/animation` 媒体类型、`none/user_avatar_center/user_avatar_waveform` 合成方式,以及 `once/daily/monthly` 数值奖励。Flutter 只消费结构化字段,不按 `benefit_code` 解释原始 JSON;未知扩展因此不会变成客户端隐形配置表。 ### 每日金币返现 @@ -115,8 +122,11 @@ Fami 的 VIP1–VIP9 初始全部为 `disabled`。30 天只是不产生零时长 - `effective_vip`:最终展示和权限使用的 VIP; - `effective_source`:`paid`、`trial` 或 `none`; - `effective_benefits`:最终身份拥有的权益资格;可关闭的通知类权益还要与 `user_settings` 做 AND; +- `evaluated_at_ms`:本次状态合并的服务端时间; - `program_config`:当前 App 规则; -- `user_settings`:当前 App 下的进房/上线通知偏好。 +- `user_settings`:当前 App 下完整的 5 项功能偏好。 + +`GET /vip/me`、`GET /vip/packages`、购买、佩戴体验卡和卸下体验卡返回完全同构的 `VipState`。写接口成功响应不是 patch;Flutter 必须原子替换 store。灰度期间如旧节点返回缺字段状态,客户端应丢弃该局部对象并重拉 `/vip/me`。 program 启用时的优先级固定为:`trial_card_enabled=true` 且体验卡有效并已佩戴时覆盖展示;否则使用有效付费会员;二者都无效则为 `none`。关闭体验卡开关只停止它参与最终权限合并,背包和佩戴原始事实仍保留;关闭整个 program 时付费与卡片原始事实仍可查询,但最终身份为 `none`、不下发权益。 @@ -156,8 +166,8 @@ program 启用时的优先级固定为:`trial_card_enabled=true` 且体验卡 - `GET /vip/packages`:program、可购买等级、每级权益和完整 state。 - `GET /vip/me`:付费、体验卡、最终 VIP、权益资格和用户功能开关。 -- `POST /vip/purchase`:请求 `{command_id,level}`;价格、时长和资源由服务端读取。 -- `GET|PATCH /vip/settings`:读取或局部修改进房/上线通知偏好;空 PATCH 拒绝。 +- `POST /vip/purchase`:请求 `{command_id,level}`;价格、时长和资源由服务端读取;响应 `coin_balance` 是带 `version` 的账后快照,旧 `coin_balance_after` 仅兼容历史客户端。 +- `GET|PATCH /vip/settings`:读取或局部修改 5 项 VIP 功能偏好;空 PATCH 拒绝。 - `POST /vip/online-notice`:请求 `{command_id}`,服务端校验权益、开关和资料后写全服播报 outbox。 - `GET /vip/coin-rebates/current`:返回当前 UTC 日返现资格;无资格或 cron 尚未生成时 `found=false`。 - `POST /vip/coin-rebates/statuses`:按最多 100 个 `rebate_ids` 恢复系统消息真实状态,或用受限分页查历史。 @@ -175,6 +185,8 @@ program 启用时的优先级固定为:`trial_card_enabled=true` 且体验卡 - `POST /v1/admin/activity/vip-trial-card-grants` - `POST /v1/admin/activity/vip-grants`,仅用于 `direct_membership` program +App 业务错误通过 xerr 目录稳定映射:购买使用 `VIP_PROGRAM_INACTIVE`、`VIP_PACKAGE_NOT_PURCHASABLE`、`VIP_DOWNGRADE_NOT_ALLOWED`、`VIP_RECHARGE_REQUIRED`、`VIP_INSUFFICIENT_COIN`;体验卡使用 `VIP_TRIAL_CARD_NOT_FOUND`、`VIP_TRIAL_CARD_EXPIRED`;权益拒绝使用 `VIP_BENEFIT_REQUIRED`,普通房管防踢/防禁言分别使用 `VIP_ANTI_KICK`、`VIP_ANTI_MUTE`;返现使用 `VIP_COIN_REBATE_NOT_FOUND`、`VIP_COIN_REBATE_EXPIRED`。客户端不得解析 message。返现重复领取沿用幂等成功回执,不额外定义 already-claimed 错误。 + ## 权益落地边界 当前服务端已强制执行购买有效期、体验卡状态合并、用户通知开关、每日金币返现资格/消息/手动领取入账、自定义房间背景、防踢、防禁言、房内进场通知和上线全服通知。装扮类权益由已绑定的钱包资源与 Flutter 展示链路执行。 diff --git a/docs/flutter对接/房内猜拳Flutter对接.md b/docs/flutter对接/房内猜拳Flutter对接.md index bb21a0ef..6d70aa2b 100644 --- a/docs/flutter对接/房内猜拳Flutter对接.md +++ b/docs/flutter对接/房内猜拳Flutter对接.md @@ -198,6 +198,18 @@ Content-Type: application/json - `room_rps_reveal_countdown` - `room_rps_finished` +当挑战到达 `timeout_at_ms` 后,应战接口返回 HTTP `409`: + +```json +{ + "code": "ROOM_RPS_CHALLENGE_EXPIRED", + "message": "猜拳已过期", + "request_id": "req_xxx" +} +``` + +Flutter 必须按 `code` 识别该状态,关闭应战弹窗并提示“猜拳已过期”;不要依赖 `message` 判断业务类型。 + ## 7. 查询挑战详情 地址: @@ -319,4 +331,3 @@ IM 示例: } } ``` - diff --git a/docs/flutter对接/用户排行榜Flutter对接.md b/docs/flutter对接/用户排行榜Flutter对接.md index 4fe78485..81e07ac8 100644 --- a/docs/flutter对接/用户排行榜Flutter对接.md +++ b/docs/flutter对接/用户排行榜Flutter对接.md @@ -1,6 +1,6 @@ # 用户排行榜 Flutter 对接 -本文描述 Flutter App 对接用户排行榜、送礼榜、收礼榜和房间榜的 HTTP 接口。榜单事实来自 `wallet-service` 已成功的礼物扣费流水;客户端只展示 gateway 返回的榜单投影,不在本地重算排名、礼物价值或统计窗口。 +本文描述 Flutter App 对接财富榜、魅力榜、游戏榜和房间榜的 HTTP 接口。`sent/received` 来自钱包已提交的礼物事实,`game` 来自游戏成功扣币的 `game_spend_coin` 事实,`room` 来自 room-service 的房间收礼投影;客户端只展示 gateway 返回的榜单,不在本地重算排名或统计窗口。 ## 基础约定 @@ -49,7 +49,7 @@ Query 参数: | 字段 | 类型 | 必填 | 默认 | 说明 | | --- | --- | --- | --- | --- | -| `board_type` | string | 否 | `sent` | 榜单类型。`sent` 是送礼榜;`received` 是收礼榜;`room` 是房间收礼榜。 | +| `board_type` | string | 否 | `sent` | 榜单类型。`sent` 是送礼财富榜;`received` 是收礼魅力榜;`game` 是游戏消费榜;`room` 是房间收礼榜。 | | `period` | string | 否 | `today` | 统计周期。`today`、`week`、`month`。 | | `page` | int32 | 否 | `1` | 页码,从 1 开始。必须大于 0。 | | `page_size` | int32 | 否 | `20` | 每页数量。必须大于 0;服务端最大返回 `100`。 | @@ -60,6 +60,7 @@ Query 参数: | --- | --- | --- | | `sent` | 空字符串、`send`、`sender`、`gift_sent`、`user_sent` | 按送礼用户聚合,展示用户送礼贡献。 | | `received` | `receive`、`receiver`、`gift_received`、`user_received` | 按收礼用户聚合,展示用户收礼魅力。 | +| `game` | `games`、`gaming` | 按用户聚合成功游戏扣币额;不累计派奖、退款或净输赢。 | | `room` | `rooms`、`room_gift`、`room_gifts` | 按房间聚合,展示房间礼物流水。 | `period` 兼容别名: @@ -70,7 +71,7 @@ Query 参数: | `week` | `weekly` | UTC 本周周一 00:00:00 到当前服务端时间。 | | `month` | `monthly` | UTC 本月 1 日 00:00:00 到当前服务端时间。 | -服务端实际查询范围是 `[start_at_ms, end_at_ms)`,其中 `end_at_ms` 是本次请求的当前服务端时间。排序固定为 `gift_value DESC, last_gift_at_ms DESC, subject_id ASC`;礼物价值相同的情况下,最近送礼时间更晚的排名更靠前,再用用户 ID 或房间 ID 保证稳定顺序。 +服务端实际查询范围是 `[start_at_ms, end_at_ms)`,其中 `end_at_ms` 是本次请求的当前服务端时间。用户榜按窗口累计值倒序;`game` 的累计值是 `game_spend_coin`,为兼容既有 JSON 暂时仍通过 `gift_value` 返回。房间榜由 room-service 按同一周期返回。 ### 送礼榜 @@ -92,6 +93,16 @@ X-App-Code: lalu 收礼榜按 `target_user_id` 聚合。返回项里的 `user_id` 和 `user` 表示收礼用户。 +### 游戏榜 + +```http +GET /api/v1/activities/user-leaderboards?board_type=game&period=today&page=1&page_size=20 +Authorization: Bearer +X-App-Code: huwaa +``` + +游戏榜按成功扣币订单的 `user_id` 聚合 `game_spend_coin`。只有 `op_type=debit` 且扣币成功、金额大于 0 的订单进入榜单;派奖、退款和净输赢不会改变游戏榜积分。返回项中的 `gift_value` 是兼容字段,游戏榜场景表示累计游戏扣币额。 + ### 房间榜 ```http @@ -104,7 +115,7 @@ X-App-Code: lalu ## 房间内贡献榜边界 -本接口是全局活动榜,按 `board_type + period` 查询成功送礼流水。房间页里的当前房间送礼贡献榜不是通过本接口读取: +本接口是全局活动榜,按 `board_type + period` 查询对应的用户或房间聚合。房间页里的当前房间送礼贡献榜不是通过本接口读取: | 场景 | 接口 | 榜单字段 | 说明 | | --- | --- | --- | --- | @@ -210,24 +221,24 @@ X-App-Code: lalu | `total` | int64 | 当前榜单和周期下的总上榜主体数。 | | `page` | int32 | 服务端解析后的页码。 | | `page_size` | int32 | 服务端实际使用的每页数量;请求超过 100 时返回 100。 | -| `board_type` | string | 服务端归一化后的榜单类型:`sent`、`received`、`room`。 | +| `board_type` | string | 服务端归一化后的榜单类型:`sent`、`received`、`game`、`room`。 | | `period` | string | 服务端归一化后的统计周期:`today`、`week`、`month`。 | | `start_at_ms` | int64 | 本次统计窗口开始时间,UTC。 | | `end_at_ms` | int64 | 本次统计窗口结束时间,等于请求时的当前服务端时间。 | | `server_time_ms` | int64 | 服务端当前时间,可用于前端展示“更新时间”。 | -| `my_rank` | object? | 当前登录用户在送礼榜或收礼榜中的排名;未上榜或 `board_type=room` 时不返回。 | +| `my_rank` | object? | 当前登录用户在送礼榜、收礼榜或游戏榜中的排名;未上榜或 `board_type=room` 时不返回。 | `items[]` / `my_rank` 字段: | 字段 | 类型 | 说明 | | --- | --- | --- | | `rank` | int64 | 排名,从 1 开始。 | -| `user_id` | string | 用户榜单主体 ID;`sent`、`received` 才有。 | +| `user_id` | string | 用户榜单主体 ID;`sent`、`received`、`game` 才有。 | | `room_id` | string | 房间榜单主体 ID;`room` 才有。 | -| `gift_value` | int64 | 统计窗口内礼物价值总和,用于排名和主数值展示。 | -| `gift_count` | int64 | 统计窗口内礼物数量总和。 | -| `transaction_count` | int64 | 统计窗口内成功送礼扣费流水数。 | -| `last_gift_at_ms` | int64 | 该主体最近一次成功送礼流水时间。 | +| `gift_value` | int64 | 排名累计值。`sent/received/room` 表示礼物价值;`game` 表示成功游戏扣币额。 | +| `gift_count` | int64 | 礼物榜的礼物数量总和;`game` 固定为 0。 | +| `transaction_count` | int64 | 用户榜的成功事实数;`game` 表示成功扣币订单数。 | +| `last_gift_at_ms` | int64 | 最近一次计榜事实时间;`game` 表示最近一次成功游戏扣币时间。字段名为兼容既有协议保留。 | | `user` | object? | 用户资料;正常会补充展示 ID、昵称和头像;本地未注入用户资料 client 时至少返回 `user_id`。 | | `room` | object? | 房间基础投影;房间榜返回 `room_id`、`room_short_id`、`title`、`cover_url`、`room_avatar`。 | @@ -415,7 +426,7 @@ class LeaderboardRoom { 请求封装示例: ```dart -enum LeaderboardType { sent, received, room } +enum LeaderboardType { sent, received, game, room } enum LeaderboardPeriod { today, week, month } extension on LeaderboardType { @@ -493,15 +504,15 @@ class ApiException implements Exception { | `401` | `SESSION_REVOKED` | 会话已被服务端撤销。 | 清理本地登录态并重新登录。 | | `403` | `PROFILE_REQUIRED` | 当前 token 对应用户未完成资料。 | 跳资料补全流程。 | | `405` | `INVALID_ARGUMENT` | 使用了非 GET 方法。 | 修正客户端请求方法。 | -| `502` | `UPSTREAM_ERROR` | 钱包库、用户资料服务或上游依赖异常。 | 展示通用失败,可保留旧榜单并允许下拉重试;记录 `request_id`。 | -| `503` | `UPSTREAM_ERROR` | gateway 未配置榜单钱包只读库。 | 展示通用失败,记录 `request_id`。 | +| `502` | `UPSTREAM_ERROR` | 榜单 Redis、用户资料、钱包装扮或房间上游依赖异常。 | 展示通用失败,可保留旧榜单并允许下拉重试;记录 `request_id`。 | +| `503` | `UPSTREAM_ERROR` | gateway 未配置榜单 Redis 读模型。 | 展示通用失败,记录 `request_id`。 | ## 客户端展示规则 榜单页建议用 `board_type + period + page + page_size` 做缓存 key。用户切换榜单类型或周期时重新请求第一页;上拉加载下一页时用返回的 `total` 判断是否还有更多:`page * page_size < total`。 -`my_rank` 只表示当前登录用户在当前用户榜单中的排名。送礼榜里是“我的送礼排名”,收礼榜里是“我的收礼排名”;房间榜没有个人排名。未上榜时 `my_rank` 不存在,客户端展示“未上榜”即可,不要自行用 `items` 推断。 +`my_rank` 只表示当前登录用户在当前用户榜单中的排名。送礼榜里是“我的送礼排名”,收礼榜里是“我的收礼排名”,游戏榜里是“我的游戏消费排名”;房间榜没有个人排名。未上榜时 `my_rank` 不存在,客户端展示“未上榜”即可,不要自行用 `items` 推断。 时间展示用 `server_time_ms` 或 `end_at_ms` 标注“更新于”。`today`、`week`、`month` 的统计口径固定为 UTC,展示文案如果需要本地化,只能改时间格式,不能改变请求周期含义。 -榜单数据当前没有单独 IM 推送。用户送礼后如果当前页面正在展示对应榜单,可以延迟刷新第一页或由用户手动下拉刷新;不要依赖房间公屏 IM 来本地累加全局榜单。 +榜单数据当前没有单独 IM 推送。送礼或游戏扣币后如果当前页面正在展示对应榜单,可以延迟刷新第一页或由用户手动下拉刷新;不要依赖房间公屏 IM 来本地累加全局榜单。 diff --git a/docs/房内猜拳接口文档.md b/docs/房内猜拳接口文档.md index d0ff83ea..aa280760 100644 --- a/docs/房内猜拳接口文档.md +++ b/docs/房内猜拳接口文档.md @@ -51,6 +51,7 @@ - `gesture`:`rock` / `paper` / `scissors` - 返回值: - `challenge`:应战后的挑战单 +- 超时错误:HTTP `409`,`code=ROOM_RPS_CHALLENGE_EXPIRED`。客户端应关闭当前挑战弹窗并提示“猜拳已过期”。 - 相关 IM: - `room_rps_challenge_accepted`:服务端通知房间挑战已被锁定,带发起人和应战人头像昵称。 - `room_rps_reveal_countdown`:服务端通知双方展示 3 秒倒计时,带发起人和应战人头像昵称。 diff --git a/docs/数据大屏统计口径.md b/docs/数据大屏统计口径.md index a9ff4317..a7118324 100644 --- a/docs/数据大屏统计口径.md +++ b/docs/数据大屏统计口径.md @@ -8,6 +8,7 @@ - 默认统计时区是 `UTC`;传 `stat_tz=Asia/Shanghai` 时按中国自然日查询统计读模型。 - 国家和区域只使用事件里的国家/区域字段或统计服务保存的用户维度,不用服务器所在地、IP 或本地时区推断。 - 查询只读 `statistics-service` 聚合表,不回查 wallet、room、game、user owner 明细表。 +- 运营宽表的 DAU 统一读取 `stat_social_user_day`,再用 `stat_social_identity_day` 把同一登录会话内的 `d:` 临时归并到 `u:`;维度筛选和国家/区域明细均在归并后计算。 - `coin_total` 为兼容前端保留 JSON 字段名,展示名改为“用户金币数”。 ## 字段口径 @@ -19,7 +20,7 @@ | `start_ms` / `end_ms` | 查询时间 | 本次查询的毫秒时间范围。 | | `country_id` / `region_id` | 国家/区域 | 聚合维度;未筛选国家时返回国家分解。 | | `new_users` | 新增用户 | `UserRegistered` 注册 cohort 去重用户数。 | -| `active_users` | 活跃用户 | `RoomUserJoined`、`GameOrderSettled` 和注册当天活跃写入 `stat_user_day_activity` 后按用户去重。 | +| `active_users` | 活跃用户 | `stat_social_user_day.active_user` 经设备日级 canonical 身份归并后的用户日去重数;多日汇总为活跃人天。 | | `paid_users` | 付费用户 | `WalletRechargeRecorded` 写入 `stat_recharge_day_payers` 后按用户去重。 | | `new_paid_users` | 新增付费用户 | 付费用户中注册 cohort 也落在查询周期内的用户数。 | | `recharge_usd_minor` | 总充值 | `WalletRechargeRecorded.usd_minor_amount` 累加,单位是美元最小单位。 | @@ -64,7 +65,7 @@ | `super_lucky_gift_payout` | super lucky 返奖 | `pool_id` 包含 `super_lucky` 的奖池返奖。 | | `super_lucky_gift_profit` | super lucky 利润 | `super_lucky_gift_turnover - super_lucky_gift_payout`。 | | `super_lucky_gift_profit_rate` | super lucky 利润率 | `super_lucky_gift_profit / super_lucky_gift_turnover`。 | -| `arpu_usd_minor` | ARPU | `recharge_usd_minor / active_users`。 | +| `arpu_usd_minor` | ARPU | `recharge_usd_minor / canonical active_users`。 | | `arppu_usd_minor` | ARPPU | `recharge_usd_minor / paid_users`。 | | `up_value_usd_minor` | UP 值 | 当前与 ARPPU 同口径。 | @@ -79,9 +80,9 @@ | 字段 | 口径 | | --- | --- | | `retention` | `registered_users` 为注册 cohort;`day1/day7/day30_users` 为注册后第 1/7/30 天有活跃的用户;rate 为对应用户数除以注册用户数。 | -| `daily_series` | 按日返回本页主要字段;`coin_total` 和 `salary_usd_minor` 是每天余额快照,其它流水字段按当天累加。 | -| `country_breakdown` | 按国家返回本页主要字段;`coin_total` 和 `salary_usd_minor` 是查询结束日该国家余额快照,其它字段按查询周期累加。 | -| `daily_country_breakdown` | 按日 + 国家返回主要字段,用于国家弹窗明细。 | +| `daily_series` | 按日返回本页主要字段;DAU 使用 canonical Social,`coin_total` 和 `salary_usd_minor` 是每天余额快照,其它流水字段按当天累加。 | +| `country_breakdown` | 按国家返回本页主要字段;DAU 维度在 canonical 归并后确定,`coin_total` 和 `salary_usd_minor` 是查询结束日该国家余额快照,其它字段按查询周期累加。 | +| `daily_country_breakdown` | 按日 + 国家返回主要字段,DAU 与顶部/按日使用同一 canonical Social 数据源。 | | `game_ranking` | 按 `platform_code/game_id` 聚合游戏流水、返奖、退款、玩家数、利润和利润率。 | | `lucky_gift_pools` | 按 `pool_id` 聚合 lucky 礼物流水、返奖、利润、返奖率和利润率。 | | `report_metric_sources` | 返回字段来源和口径说明,供前端展示或排查。 | @@ -92,3 +93,4 @@ - 平台发放的礼物价值同理,需要 `ResourceGranted/ResourceGroupGranted` 事件携带可统计的资源金币价值和来源;当前只可靠计入 COIN 入账和已存在的 `Wallet*RewardCredited` 金币奖励。 - 装扮价值不进入 `platform_grant_coin` 和 `output_coin`。 - 后台人工发放只进入 `manual_grant_coin`,不进入 `platform_grant_coin`。 +- `retention` 仍是注册 cohort 对 `stat_user_day_activity` 的回看口径,不属于运营宽表 DAU 分母;Social 数据需求页的用户留存则使用 canonical Social 用户日口径。 diff --git a/docs/新版VIP权限策略_Flutter客户端对接文档.md b/docs/新版VIP权限策略_Flutter客户端对接文档.md index 6ebc57ab..959a54f1 100644 --- a/docs/新版VIP权限策略_Flutter客户端对接文档.md +++ b/docs/新版VIP权限策略_Flutter客户端对接文档.md @@ -35,6 +35,20 @@ class VipEntitlementState { return has('online_global_notice') && settings.onlineGlobalNoticeEnabled; } + + bool allowsHideProfileData() { + return has('hide_profile_data') && settings.hideProfileDataEnabled; + } + + bool allowsAnonymousProfileVisit() { + return has('anonymous_profile_visit') && + settings.anonymousProfileVisitEnabled; + } + + bool allowsLeaderboardInvisible() { + return has('leaderboard_invisible') && + settings.leaderboardInvisibleEnabled; + } } ``` @@ -52,6 +66,8 @@ class VipEntitlementState { | `config_version` 不一致 | 用户权限以 `/vip/me.state` 为准,重新请求 `/vip/packages`,不得合并不同版本的权益数组 | | VIP 到期倒计时结束 | 可更新页面显示,但执行功能前仍以服务端接口结果为准 | +购买、佩戴体验卡、卸下体验卡成功时,`data.state` 与 `GET /api/v1/vip/me` 的 `data.state` **完全同构**,不是局部补丁。Flutter 必须整体替换 VIP store,禁止按字段合并。若灰度期间收到缺少下文任一顶层字段的旧节点响应,应放弃该响应中的 `state` 并立即重拉 `/vip/me`。 + ### 1.4 Fami 初始等级权益 下表只用于识别初始配置。Flutter 实际必须渲染 `/vip/packages` 返回的数据。 @@ -89,6 +105,52 @@ class VipEntitlementState { - `request_id` 只用于链路追踪。 - 带 `command_id` 的接口,网络重试必须复用原 `command_id`;新的业务动作必须生成新值。 +### 2.1 `VipState` 唯一结构 + +`GET /vip/me`、`GET /vip/packages`、购买、佩戴体验卡和卸下体验卡返回的 `state` 使用同一结构,固定包含以下 8 个顶层字段: + +| 字段 | 含义 | +|---|---| +| `paid_vip` | 当前付费 VIP;没有时为 `null` | +| `equipped_trial_card` | 当前佩戴的体验卡;没有时为 `null` | +| `effective_vip` | 付费 VIP 与体验卡合并后的当前展示身份 | +| `effective_source` | `paid`、`trial`、`none` | +| `effective_benefits` | 服务端计算后的最终权益集合 | +| `evaluated_at_ms` | 本次状态计算时间 | +| `program_config` | 本次计算使用的完整 App VIP 配置 | +| `user_settings` | 当前 App 下完整的 5 项用户开关 | + +`paid_vip`、`effective_vip` 非空时都返回完整 `UserVip` 字段:`user_id`、`level`、`name`、`active`、`started_at_ms`、`expires_at_ms`、`updated_at_ms`、`program_type`、`config_version`。`program_config` 返回完整字段,不允许写接口只返回 `app_code/program_type` 的裁剪对象。 + +### 2.2 特权展示协议 + +每项 `VipBenefit` 除执行字段外提供结构化 `presentation`,Flutter 不解析 `metadata_json`,也不按 `benefit_code` 维护隐形展示配置: + +```json +{ + "description": "进入房间时展示动态背景和用户头像", + "preview_items": [ + { + "preview_id": "room_background_gold", + "title": "鎏金房间背景", + "media_type": "animation", + "asset_url": "https://cdn.example/vip/room-bg.png", + "preview_url": "https://cdn.example/vip/room-bg-preview.png", + "animation_url": "https://cdn.example/vip/room-bg.svga", + "composition_type": "user_avatar_center", + "sort_order": 10 + } + ], + "numeric_reward": null +} +``` + +- `media_type`:`image` 或 `animation`;动态资源加载失败时依次使用 `preview_url`、`asset_url`。 +- `composition_type`:`none`、`user_avatar_center`、`user_avatar_waveform`,分别表示无合成、头像居中、头像与声波纹合成。 +- `preview_items` 可返回多项,按 `sort_order` 升序、`preview_id` 去重。 +- `numeric_reward` 用于数值权益,字段为 `label/value/unit/period`,其中 `period` 为 `once/daily/monthly`。该字段只用于展示,结算仍以后端接口为准。 +- 没有富预览时 `presentation` 为 `null`;Flutter 回退展示权益名称和通用图标。 + ## 3. VIP 套餐 ### 接口地址 @@ -144,7 +206,23 @@ class VipEntitlementState { "execution_scope": "room", "auto_equip": false, "sort_order": 110, - "metadata_json": "" + "metadata_json": "", + "presentation": { + "description": "进入房间时展示动态背景和用户头像", + "preview_items": [ + { + "preview_id": "room_background_gold", + "title": "鎏金房间背景", + "media_type": "animation", + "asset_url": "https://cdn.example/vip/room-bg.png", + "preview_url": "https://cdn.example/vip/room-bg-preview.png", + "animation_url": "https://cdn.example/vip/room-bg.svga", + "composition_type": "user_avatar_center", + "sort_order": 10 + } + ], + "numeric_reward": null + } } ], "config_version": 7 @@ -165,17 +243,27 @@ class VipEntitlementState { }, "state": { "paid_vip": { + "user_id": 10001, "level": 3, "name": "VIP3", "active": true, - "expires_at_ms": 1782592000000 + "started_at_ms": 1780000000000, + "expires_at_ms": 1782592000000, + "updated_at_ms": 1780000000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 }, "equipped_trial_card": null, "effective_vip": { + "user_id": 10001, "level": 3, "name": "VIP3", "active": true, - "expires_at_ms": 1782592000000 + "started_at_ms": 1780000000000, + "expires_at_ms": 1782592000000, + "updated_at_ms": 1780000000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 }, "effective_source": "paid", "effective_benefits": [ @@ -185,9 +273,27 @@ class VipEntitlementState { } ], "evaluated_at_ms": 1780000000000, + "program_config": { + "app_code": "fami", + "program_type": "tiered_privilege_v1", + "level_count": 9, + "same_level_expiry_policy": "extend_remaining", + "upgrade_expiry_policy": "replace_from_now", + "downgrade_purchase_policy": "reject", + "benefit_inheritance_policy": "target_only", + "grant_mode": "trial_card", + "trial_card_enabled": true, + "status": "active", + "config_version": 7 + }, "user_settings": { + "app_code": "fami", + "user_id": 10001, "room_entry_notice_enabled": true, "online_global_notice_enabled": true, + "hide_profile_data_enabled": true, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true, "updated_at_ms": 0 } } @@ -235,11 +341,13 @@ class VipEntitlementState { }, "state": { "paid_vip": { + "user_id": 10001, "level": 3, "name": "VIP3", "active": true, "started_at_ms": 1780000000000, "expires_at_ms": 1782592000000, + "updated_at_ms": 1780000000000, "program_type": "tiered_privilege_v1", "config_version": 7 }, @@ -255,14 +363,20 @@ class VipEntitlementState { "duration_ms": 2592000000, "effective_at_ms": 1780100000000, "expires_at_ms": 1782692000000, - "remaining_duration_ms": 2591000000 + "remaining_duration_ms": 2591000000, + "grant_source": "admin", + "source_grant_id": "grant_xxx", + "created_at_ms": 1780100000000, + "updated_at_ms": 1780100000000 }, "effective_vip": { + "user_id": 10001, "level": 8, "name": "VIP8", "active": true, "started_at_ms": 1780100000000, "expires_at_ms": 1782692000000, + "updated_at_ms": 1780100000000, "program_type": "tiered_privilege_v1", "config_version": 7 }, @@ -279,13 +393,22 @@ class VipEntitlementState { "execution_scope": "room", "auto_equip": false, "sort_order": 290, - "metadata_json": "" + "metadata_json": "", + "presentation": null } ], "evaluated_at_ms": 1780101000000, "program_config": { "app_code": "fami", "program_type": "tiered_privilege_v1", + "level_count": 9, + "same_level_expiry_policy": "extend_remaining", + "upgrade_expiry_policy": "replace_from_now", + "downgrade_purchase_policy": "reject", + "benefit_inheritance_policy": "target_only", + "grant_mode": "trial_card", + "trial_card_enabled": true, + "status": "active", "config_version": 7 }, "user_settings": { @@ -293,6 +416,9 @@ class VipEntitlementState { "user_id": 10001, "room_entry_notice_enabled": true, "online_global_notice_enabled": true, + "hide_profile_data_enabled": true, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true, "updated_at_ms": 0 } } @@ -346,35 +472,81 @@ class VipEntitlementState { }, "coin_spent": 4000, "coin_balance_after": 6000, + "coin_balance": { + "asset_type": "COIN", + "available_amount": 6000, + "frozen_amount": 0, + "version": 18 + }, "reward_items": [], "program_config": { "app_code": "fami", "program_type": "tiered_privilege_v1", + "level_count": 9, + "same_level_expiry_policy": "extend_remaining", "upgrade_expiry_policy": "replace_from_now", + "downgrade_purchase_policy": "reject", + "benefit_inheritance_policy": "target_only", + "grant_mode": "trial_card", + "trial_card_enabled": true, + "status": "active", "config_version": 7 }, "state": { - "effective_source": "paid", "paid_vip": { + "user_id": 10001, "level": 4, "name": "VIP4", "active": true, - "expires_at_ms": 1782692000000 + "started_at_ms": 1780100000000, + "expires_at_ms": 1782692000000, + "updated_at_ms": 1780100000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 }, "equipped_trial_card": null, "effective_vip": { + "user_id": 10001, "level": 4, "name": "VIP4", "active": true, - "expires_at_ms": 1782692000000 + "started_at_ms": 1780100000000, + "expires_at_ms": 1782692000000, + "updated_at_ms": 1780100000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 }, + "effective_source": "paid", "effective_benefits": [ { "benefit_code": "custom_room_background", "status": "active" } ], - "evaluated_at_ms": 1780100000000 + "evaluated_at_ms": 1780100000000, + "program_config": { + "app_code": "fami", + "program_type": "tiered_privilege_v1", + "level_count": 9, + "same_level_expiry_policy": "extend_remaining", + "upgrade_expiry_policy": "replace_from_now", + "downgrade_purchase_policy": "reject", + "benefit_inheritance_policy": "target_only", + "grant_mode": "trial_card", + "trial_card_enabled": true, + "status": "active", + "config_version": 7 + }, + "user_settings": { + "app_code": "fami", + "user_id": 10001, + "room_entry_notice_enabled": true, + "online_global_notice_enabled": true, + "hide_profile_data_enabled": true, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true, + "updated_at_ms": 0 + } } } } @@ -384,6 +556,8 @@ class VipEntitlementState { - Fami 高等级购买:立即替换低等级,从购买时间重新计时,低等级剩余时间丢弃。 - 低等级购买:服务端拒绝。 - 购买时佩戴体验卡:付费 VIP 会更新,但 `effective_vip` 仍可能来自体验卡,必须使用响应 `state`。 +- 钱包缓存只使用 `coin_balance`。应用时比较 `version`,低版本响应不得覆盖本地高版本余额;`coin_balance_after` 仅保留旧客户端兼容。 +- 历史幂等订单在升级前没有记录版本时可能返回 `coin_balance.version=0`,Flutter 必须调用现有钱包余额接口刷新,不得把版本 0 写入余额 store。 ## 6. VIP 体验卡 @@ -473,22 +647,92 @@ class VipEntitlementState { "duration_ms": 1728000000, "effective_at_ms": 1780200000000, "expires_at_ms": 1781928000000, - "remaining_duration_ms": 1700000000 + "remaining_duration_ms": 1700000000, + "grant_source": "admin", + "source_grant_id": "grant_b", + "created_at_ms": 1780200000000, + "updated_at_ms": 1780200000000 }, "program_config": { "app_code": "fami", "program_type": "tiered_privilege_v1", - "trial_card_enabled": true + "level_count": 9, + "same_level_expiry_policy": "extend_remaining", + "upgrade_expiry_policy": "replace_from_now", + "downgrade_purchase_policy": "reject", + "benefit_inheritance_policy": "target_only", + "grant_mode": "trial_card", + "trial_card_enabled": true, + "status": "active", + "config_version": 7 }, "state": { - "effective_source": "trial", + "paid_vip": { + "user_id": 10001, + "level": 3, + "name": "VIP3", + "active": true, + "started_at_ms": 1780000000000, + "expires_at_ms": 1782592000000, + "updated_at_ms": 1780000000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 + }, + "equipped_trial_card": { + "trial_card_id": "vip_trial_card_b", + "entitlement_id": "ent_card_b", + "resource_id": 102, + "user_id": 10001, + "level": 4, + "name": "VIP4", + "status": "active", + "equipped": true, + "duration_ms": 1728000000, + "effective_at_ms": 1780200000000, + "expires_at_ms": 1781928000000, + "remaining_duration_ms": 1700000000, + "grant_source": "admin", + "source_grant_id": "grant_b", + "created_at_ms": 1780200000000, + "updated_at_ms": 1780200000000 + }, "effective_vip": { + "user_id": 10001, "level": 4, "name": "VIP4", "active": true, - "expires_at_ms": 1781928000000 + "started_at_ms": 1780200000000, + "expires_at_ms": 1781928000000, + "updated_at_ms": 1780200000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 }, - "effective_benefits": [] + "effective_source": "trial", + "effective_benefits": [], + "evaluated_at_ms": 1780228000000, + "program_config": { + "app_code": "fami", + "program_type": "tiered_privilege_v1", + "level_count": 9, + "same_level_expiry_policy": "extend_remaining", + "upgrade_expiry_policy": "replace_from_now", + "downgrade_purchase_policy": "reject", + "benefit_inheritance_policy": "target_only", + "grant_mode": "trial_card", + "trial_card_enabled": true, + "status": "active", + "config_version": 7 + }, + "user_settings": { + "app_code": "fami", + "user_id": 10001, + "room_entry_notice_enabled": true, + "online_global_notice_enabled": true, + "hide_profile_data_enabled": true, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true, + "updated_at_ms": 0 + } }, "server_time_ms": 1780228000000 } @@ -516,22 +760,67 @@ class VipEntitlementState { "unequipped": true, "program_config": { "app_code": "fami", - "program_type": "tiered_privilege_v1" + "program_type": "tiered_privilege_v1", + "level_count": 9, + "same_level_expiry_policy": "extend_remaining", + "upgrade_expiry_policy": "replace_from_now", + "downgrade_purchase_policy": "reject", + "benefit_inheritance_policy": "target_only", + "grant_mode": "trial_card", + "trial_card_enabled": true, + "status": "active", + "config_version": 7 }, "state": { - "effective_source": "paid", "paid_vip": { + "user_id": 10001, "level": 3, "name": "VIP3", - "active": true + "active": true, + "started_at_ms": 1780000000000, + "expires_at_ms": 1782592000000, + "updated_at_ms": 1780000000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 }, "equipped_trial_card": null, "effective_vip": { + "user_id": 10001, "level": 3, "name": "VIP3", - "active": true + "active": true, + "started_at_ms": 1780000000000, + "expires_at_ms": 1782592000000, + "updated_at_ms": 1780000000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 }, - "effective_benefits": [] + "effective_source": "paid", + "effective_benefits": [], + "evaluated_at_ms": 1780229000000, + "program_config": { + "app_code": "fami", + "program_type": "tiered_privilege_v1", + "level_count": 9, + "same_level_expiry_policy": "extend_remaining", + "upgrade_expiry_policy": "replace_from_now", + "downgrade_purchase_policy": "reject", + "benefit_inheritance_policy": "target_only", + "grant_mode": "trial_card", + "trial_card_enabled": true, + "status": "active", + "config_version": 7 + }, + "user_settings": { + "app_code": "fami", + "user_id": 10001, + "room_entry_notice_enabled": true, + "online_global_notice_enabled": true, + "hide_profile_data_enabled": true, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true, + "updated_at_ms": 0 + } }, "server_time_ms": 1780229000000 } @@ -543,7 +832,7 @@ class VipEntitlementState { - 每张卡的剩余时间按绝对 `expires_at_ms` 计算。 - 佩戴和卸下成功后立即使用响应 `state` 替换本地 VIP 状态。 -## 7. VIP 通知开关 +## 7. VIP 功能开关 ### 7.1 查询开关 @@ -568,6 +857,9 @@ class VipEntitlementState { "user_id": 10001, "room_entry_notice_enabled": true, "online_global_notice_enabled": false, + "hide_profile_data_enabled": true, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true, "updated_at_ms": 1780300000000 }, "evaluated_at_ms": 1780300001000 @@ -588,7 +880,10 @@ class VipEntitlementState { ```json { "room_entry_notice_enabled": false, - "online_global_notice_enabled": true + "online_global_notice_enabled": true, + "hide_profile_data_enabled": false, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true } ``` @@ -605,6 +900,9 @@ class VipEntitlementState { "user_id": 10001, "room_entry_notice_enabled": false, "online_global_notice_enabled": true, + "hide_profile_data_enabled": false, + "anonymous_profile_visit_enabled": true, + "leaderboard_invisible_enabled": true, "updated_at_ms": 1780300010000 }, "server_time_ms": 1780300010000 @@ -612,6 +910,8 @@ class VipEntitlementState { } ``` +5 个字段都使用 PATCH 语义:不传表示保持原值,显式 `false` 表示关闭。没有持久记录时均默认 `true`;设置只限制用户主动启用对应效果,不会单独授予 VIP 权益。服务端执行时使用“当前有效权益 AND 用户设置”判定,Flutter 不能只看开关。 + ## 8. 每日 VIP 金币返现 ### 8.1 查询当前返现 @@ -1050,3 +1350,35 @@ Flutter 将 `action_param` 解析为 JSON,打开页面后调用 `/vip/coin-reb 接口:`GET /api/v1/im/usersig`。 Flutter 使用返回的 UserSig 登录腾讯云 IM,并加入响应 `join_groups` 中 `type=global_broadcast` 的群组后,再消费 `vip_online_notice`。 + +## 13. 稳定业务错误码 + +失败仍使用统一 envelope,Flutter 只判断 `code`,不得解析 `message`: + +```json +{ + "code": "VIP_INSUFFICIENT_COIN", + "message": "insufficient coin balance", + "request_id": "req_purchase", + "data": null +} +``` + +| HTTP | `code` | 场景 | Flutter 处理 | +|---:|---|---|---| +| 409 | `VIP_PROGRAM_INACTIVE` | 当前 App 的 VIP 体系未启用 | 关闭购买/体验卡操作并刷新配置 | +| 409 | `VIP_PACKAGE_NOT_PURCHASABLE` | 套餐不存在、停用或不在当前体系范围 | 刷新 `/vip/packages` | +| 409 | `VIP_DOWNGRADE_NOT_ALLOWED` | 购买等级低于当前付费等级 | 提示不可降级,刷新 `/vip/me` | +| 409 | `VIP_RECHARGE_REQUIRED` | 未达到套餐充值门槛 | 展示充值引导 | +| 409 | `VIP_INSUFFICIENT_COIN` | 购买金币余额不足 | 展示金币充值入口 | +| 404 | `VIP_TRIAL_CARD_NOT_FOUND` | 卡不存在、不属于本人或背包权益已撤销 | 刷新体验卡列表和 `/vip/me` | +| 409 | `VIP_TRIAL_CARD_EXPIRED` | 卡或背包权益已越过绝对截止时间 | 刷新体验卡列表和 `/vip/me` | +| 403 | `VIP_BENEFIT_REQUIRED` | 操作需要的权益未生效或被用户关闭 | 刷新 `/vip/me`,保持入口锁态 | +| 403 | `VIP_ANTI_KICK` | 普通房主/管理员踢人被目标用户防踢拦截 | 提示目标不可被踢出,不改变房间本地状态 | +| 403 | `VIP_ANTI_MUTE` | 普通房主/管理员禁言被目标用户防禁言拦截 | 提示目标不可被禁言,不改变房间本地状态 | +| 404 | `VIP_COIN_REBATE_NOT_FOUND` | 返现不存在或不属于当前用户/App | 刷新返现列表 | +| 409 | `VIP_COIN_REBATE_EXPIRED` | 已越过 UTC 次日 0 点的领取结束边界 | 标记过期并刷新返现列表 | +| 409 | `IDEMPOTENCY_CONFLICT` | 同一 `command_id` 被用于不同业务参数 | 停止重试,为新动作生成新 ID | +| 409 | `LEDGER_CONFLICT` | 钱包并发版本冲突 | 刷新余额和 `/vip/me` 后由用户重新发起 | + +返现重复领取采用幂等成功语义:相同 `command_id` 重试返回首次成功回执,不返回 `VIP_REBATE_ALREADY_CLAIMED`。因此客户端不应实现该错误分支。 diff --git a/docs/统计服务技术方案.md b/docs/统计服务技术方案.md index 11f7139d..c90ca3e2 100644 --- a/docs/统计服务技术方案.md +++ b/docs/统计服务技术方案.md @@ -73,7 +73,8 @@ flowchart LR | 指标 | 口径 | | --- | --- | | 新增用户 | `UserRegistered` 按 UTC 日、`app_code`、国家维度聚合 | -| 活跃用户 | `RoomUserJoined` 和 `GameOrderSettled` 写入 `stat_user_day_activity`,按用户去重 | +| 运营宽表活跃用户 | `stat_social_user_day.active_user` 先经 `stat_social_identity_day` 完成设备→账号日级归并,再按 canonical 用户日去重 | +| 注册 cohort 留存活跃 | `RoomUserJoined` 和 `GameOrderSettled` 写入 `stat_user_day_activity`,按用户去重 | | 次日留存 | 注册 cohort 中,注册日 + 1 天存在活跃记录的用户数 / 注册用户数 | | 7 日留存 | 注册 cohort 中,注册日 + 7 天存在活跃记录的用户数 / 注册用户数 | | 30 日留存 | 注册 cohort 中,注册日 + 30 天存在活跃记录的用户数 / 注册用户数 | @@ -129,6 +130,8 @@ flowchart LR | `statistics_event_consumption` | 消费幂等表 | `(app_code, source, event_id)` | | `stat_app_day_country` | App/UTC 日/国家总览 | `(app_code, stat_day, country_id)` | | `stat_user_day_activity` | 用户日活跃去重 | `(app_code, stat_day, user_id)` | +| `stat_social_user_day` | Social 用户/匿名设备日级宽表 | `(app_code, stat_tz, stat_day, subject_key)` | +| `stat_social_identity_day` | 同日匿名设备的 canonical 登录账号解析 | `(app_code, stat_tz, stat_day, device_id)` | | `stat_user_registration` | 注册 cohort | `(app_code, user_id)` | | `stat_recharge_day_payers` | 日付费用户去重 | `(app_code, stat_day, user_id)` | | `stat_lucky_gift_day_payers` | 幸运礼物日付费用户去重 | `(app_code, stat_day, country_id, user_id)` | diff --git a/docs/钱包服务架构.md b/docs/钱包服务架构.md index 83e85924..f9db21cd 100644 --- a/docs/钱包服务架构.md +++ b/docs/钱包服务架构.md @@ -84,8 +84,8 @@ - 送礼实时加主播 `GIFT_POINT`,但美元奖励由结算任务按政策转换,不能写死在送礼链路。 - 奖励结算生成 `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`,审核拒绝解冻,审核通过后进入人工打款流程。 -- 人工打款完成后从冻结余额出账;打款失败回到可重试状态,不能自动解冻后丢失审核上下文。 +- 提现申请必须先冻结 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD`,再依次经过运营初审和财务终审。运营通过只转交财务,不改 frozen;任一阶段拒绝都释放 frozen。 +- 财务确认人工打款凭证并通过终审后从冻结余额出账;外部动作失败时保留当前审核阶段,依靠阶段固定幂等命令重试,不能自动解冻后丢失审核上下文。 ## Component Diagram @@ -333,25 +333,34 @@ flowchart LR 1. 送礼时钱包给主播增加 `GIFT_POINT`。 2. 结算任务读取积分和政策,生成 `anchor_reward_settlements`。 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`。 +4. 主播提现时先冻结 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD`,申请进入运营初审。 +5. 运营通过只把申请转入财务终审,冻结金额保持不变;运营拒绝立即释放 frozen 并结束申请。 +6. 财务结合人工转账凭证终审:通过后扣减 frozen,拒绝后释放 frozen。 提现状态机: ```mermaid stateDiagram-v2 - [*] --> pending_review - pending_review --> rejected - rejected --> refunded - pending_review --> approved - approved --> paying - paying --> paid - paying --> pay_failed - pay_failed --> approved + [*] --> operations_pending + operations_pending --> operations_rejecting + operations_rejecting --> operations_rejecting: retry rejection + operations_rejecting --> operations_rejected: release + notice + finalize + operations_rejected --> released + operations_pending --> finance_pending + finance_pending --> finance_rejected + finance_rejected --> released + finance_pending --> approved + approved --> settled ``` 提现申请时必须从 `available_amount` 转到 `frozen_amount`,不能只写一个待审核单。否则审核期间用户可以重复提现同一笔余额。 +运营拒绝先在 admin 独立短事务把 `operations_status` 从 `pending` 改为 `rejecting`,固定第一次审核人、原因和 operations stage command;再执行 wallet release 与幂等通知,最后以第二个短事务收敛为 operations/overall 双重 `rejected`。因此 release 已成功但通知或最终提交失败时,申请仍保持 `rejecting`,只能重试拒绝,不能改点运营通过或进入财务。 + +运营/财务审核的资金幂等边界是 `(app_code, withdrawal_application_id)`,不是审核人、备注或单一版本的 command id。`wallet_withdrawal_terminal_locks` 先串行化同一申请的 settle/release,再通过 `wallet_transactions.external_ref` 读取已有终局:同决策换审核人或修改备注时返回原回执,相反决策返回 `IDEMPOTENCY_CONFLICT`。这同时兼容旧 `salary-withdrawal::approved|rejected` 和新 `salary-withdrawal::finance` command;财务通知继续使用 `finance-withdrawal::` 事件 ID,避免旧通知已成功但 admin 未终态时重复发送。 + +新审核流程不能与旧 admin 混跑发布:先执行 wallet 终局锁迁移并完成 wallet-service 滚动,再摘流旧 admin、执行 admin 102、部署新 admin,恢复 admin 后才滚动 gateway。admin 102 只把执行时已存在且已经终审的历史行标记为 `operations_status=skipped`;尚未终审的存量申请和发布窗口内由旧 gateway 新建的申请都保持数据库默认 `pending`,必须先进入运营初审。 + ## RPC Surface 当前开发阶段直接使用新的 wallet RPC 契约: @@ -365,7 +374,7 @@ stateDiagram-v2 - `ExchangeDiamond`: 钻石兑换金币或美元余额。 - `CreditRewardBalance`: 结算任务给主播发美元余额奖励。 - `CreateWithdrawRequest`: 主播提现申请并冻结余额。 -- `ReviewWithdrawRequest`: 后台审核提现。 +- `ReviewWithdrawRequest`: 后台按运营初审、财务终审推进提现;运营通过不调用钱包,任一拒绝调用 release,财务通过调用 settle。 - `MarkWithdrawPaid`: 人工打款后确认出账。 外部 HTTP 入口仍在 `gateway-service`,内部统一 gRPC + protobuf。当前处于开发阶段,不做历史兼容保留;修改 `api/proto` 后必须运行 `make proto` 和 `go test ./...`。 @@ -500,8 +509,9 @@ stateDiagram-v2 提现: - 提现申请成功后 `identity salary wallet.available_amount` 减少,`frozen_amount` 增加。 -- 审核拒绝后冻结金额回到 available。 -- 打款完成后 frozen 减少并写出账分录。 +- 运营审核通过后冻结金额保持不变,申请进入财务审核。 +- 运营或财务拒绝后冻结金额回到 available。 +- 财务确认打款并通过后 frozen 减少并写出账分录。 - 打款失败后状态可重试,不丢失冻结关系和审核上下文。 验证命令: @@ -535,6 +545,6 @@ docker compose config - 币商充值分两段:平台给币商发 `COIN_SELLER_COIN` 库存,币商再把库存转成用户 `COIN`;必须有币商金币余额、充值政策快照、限额和审计。 - `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` 是可提现负债,调账和奖励发放需要更高权限和审计。 - 兑换汇率和奖励政策必须记录快照,不能只存当前 policy id。 -- 提现人工打款前必须冻结余额,打款失败要回到可重新处理状态。 +- 提现人工打款前必须冻结余额并完成运营初审;运营通过不得提前扣减 frozen,财务终审通过才 settle,任一拒绝都 release。 - 钱包事件投递使用 outbox,MQ 投递失败不回滚账务事实。 - 礼物价格和积分比例必须来自服务端配置,不能由客户端决定。 diff --git a/pkg/userleaderboard/store.go b/pkg/userleaderboard/store.go index 0ec9adb1..707889e6 100644 --- a/pkg/userleaderboard/store.go +++ b/pkg/userleaderboard/store.go @@ -1,4 +1,4 @@ -// Package userleaderboard owns the Redis read model for App user gift rankings. +// Package userleaderboard owns the Redis read model for App user rankings. package userleaderboard import ( @@ -17,6 +17,7 @@ import ( const ( BoardSent = "sent" BoardReceived = "received" + BoardGame = "game" PeriodToday = "today" PeriodWeek = "week" @@ -33,8 +34,8 @@ const ( var ErrNotConfigured = errors.New("user leaderboard redis is not configured") -// Store keeps sent/received gift leaderboard buckets in Redis zsets plus per-user hashes. -// The write side consumes wallet committed facts; the read side is used by gateway only. +// Store keeps user leaderboard buckets in Redis zsets plus per-user hashes. +// Gift facts populate sent/received, while successful game debits populate game; gateway only reads this projection. type Store struct { client *redis.Client keyPrefix string @@ -52,6 +53,16 @@ type GiftEvent struct { DirectGift bool } +// GameEvent is the successful game debit fact used by the game-spend leaderboard. +// CoinSpent follows the existing game growth metric and deliberately excludes payout, refund and net-win values. +type GameEvent struct { + AppCode string + EventID string + UserID int64 + CoinSpent int64 + OccurredAtMS int64 +} + // Query describes one App leaderboard page. Now must be UTC-compatible; zero means current UTC time. type Query struct { AppCode string @@ -119,14 +130,6 @@ func (s *Store) ApplyGiftEvent(ctx context.Context, event GiftEvent) (bool, erro } occurredAt := time.UnixMilli(event.OccurredAtMS).UTC() - keys := []string{s.dedupeKey(event.AppCode, event.EventID)} - args := []any{ - strconv.FormatInt(int64(defaultEventDedupeTTL/time.Millisecond), 10), - strconv.FormatInt(event.GiftValue, 10), - strconv.FormatInt(event.GiftCount, 10), - strconv.FormatInt(event.OccurredAtMS, 10), - } - updates := make([]leaderboardUpdate, 0, 6) for _, period := range []string{PeriodToday, PeriodWeek, PeriodMonth} { updates = append(updates, @@ -134,17 +137,27 @@ func (s *Store) ApplyGiftEvent(ctx context.Context, event GiftEvent) (bool, erro s.updateFor(event.AppCode, BoardReceived, period, event.TargetUserID, occurredAt), ) } - args = append(args, strconv.Itoa(len(updates))) - for _, update := range updates { - keys = append(keys, update.scoreKey, update.itemKey) - args = append(args, update.member, strconv.FormatInt(int64(update.ttl/time.Second), 10)) + return s.applyValueEvent(ctx, event.AppCode, event.EventID, event.GiftValue, event.GiftCount, event.OccurredAtMS, updates) +} + +// ApplyGameEvent projects one successful game debit into UTC day/week/month game buckets. +// The Redis hash keeps the legacy gift_* field names because the public leaderboard JSON already exposes them; +// for board_type=game, gift_value means game_spend_coin, gift_count stays zero and transaction_count counts debit orders. +func (s *Store) ApplyGameEvent(ctx context.Context, event GameEvent) (bool, error) { + if s == nil || s.client == nil { + return false, ErrNotConfigured + } + event = normalizeGameEvent(event) + if event.AppCode == "" || event.EventID == "" || event.UserID <= 0 || event.CoinSpent <= 0 { + return false, nil } - result, err := applyGiftEventScript.Run(ctx, s.client, keys, args...).Int64() - if err != nil { - return false, err + occurredAt := time.UnixMilli(event.OccurredAtMS).UTC() + updates := make([]leaderboardUpdate, 0, 3) + for _, period := range []string{PeriodToday, PeriodWeek, PeriodMonth} { + updates = append(updates, s.updateFor(event.AppCode, BoardGame, period, event.UserID, occurredAt)) } - return result == 1, nil + return s.applyValueEvent(ctx, event.AppCode, event.EventID, event.CoinSpent, 0, event.OccurredAtMS, updates) } // List reads a leaderboard page from the current Redis bucket. Empty keys are valid empty rankings. @@ -225,6 +238,8 @@ func NormalizeBoardType(raw string) string { return BoardSent case BoardReceived, "receive", "receiver", "gift_received", "user_received": return BoardReceived + case BoardGame, "games", "gaming": + return BoardGame default: return "" } @@ -308,6 +323,37 @@ func normalizeGiftEvent(event GiftEvent) GiftEvent { return event } +func normalizeGameEvent(event GameEvent) GameEvent { + event.AppCode = appcode.Normalize(event.AppCode) + event.EventID = strings.TrimSpace(event.EventID) + if event.OccurredAtMS <= 0 { + event.OccurredAtMS = time.Now().UTC().UnixMilli() + } + return event +} + +func (s *Store) applyValueEvent(ctx context.Context, app string, eventID string, valueDelta int64, countDelta int64, occurredAtMS int64, updates []leaderboardUpdate) (bool, error) { + keys := []string{s.dedupeKey(app, eventID)} + args := []any{ + strconv.FormatInt(int64(defaultEventDedupeTTL/time.Millisecond), 10), + strconv.FormatInt(valueDelta, 10), + strconv.FormatInt(countDelta, 10), + strconv.FormatInt(occurredAtMS, 10), + strconv.Itoa(len(updates)), + } + for _, update := range updates { + keys = append(keys, update.scoreKey, update.itemKey) + args = append(args, update.member, strconv.FormatInt(int64(update.ttl/time.Second), 10)) + } + + // Dedupe and all period updates execute without interleaving; after a successful script, relay retries cannot double-count. + result, err := applyValueEventScript.Run(ctx, s.client, keys, args...).Int64() + if err != nil { + return false, err + } + return result == 1, nil +} + func normalizeQuery(query Query) Query { query.AppCode = appcode.Normalize(query.AppCode) query.BoardType = NormalizeBoardType(query.BoardType) @@ -385,13 +431,13 @@ func int64FromHash(values map[string]string, key string) int64 { return value } -var applyGiftEventScript = redis.NewScript(` +var applyValueEventScript = redis.NewScript(` if redis.call("EXISTS", KEYS[1]) == 1 then return 0 end redis.call("PSETEX", KEYS[1], ARGV[1], "1") -local gift_value = tonumber(ARGV[2]) -local gift_count = tonumber(ARGV[3]) +local value_delta = tonumber(ARGV[2]) +local count_delta = tonumber(ARGV[3]) local occurred_at_ms = tonumber(ARGV[4]) local updates = tonumber(ARGV[5]) for i = 0, updates - 1 do @@ -399,8 +445,8 @@ for i = 0, updates - 1 do local item_key = KEYS[3 + i * 2] local member = ARGV[6 + i * 2] local ttl_seconds = tonumber(ARGV[7 + i * 2]) - local current_value = redis.call("HINCRBY", item_key, "gift_value", gift_value) - redis.call("HINCRBY", item_key, "gift_count", gift_count) + local current_value = redis.call("HINCRBY", item_key, "gift_value", value_delta) + redis.call("HINCRBY", item_key, "gift_count", count_delta) redis.call("HINCRBY", item_key, "transaction_count", 1) local previous_last = tonumber(redis.call("HGET", item_key, "last_gift_at_ms") or "0") local last_gift_at_ms = previous_last diff --git a/pkg/userleaderboard/store_test.go b/pkg/userleaderboard/store_test.go index cef09ca2..ea3ce104 100644 --- a/pkg/userleaderboard/store_test.go +++ b/pkg/userleaderboard/store_test.go @@ -1,6 +1,9 @@ package userleaderboard import ( + "context" + "fmt" + "os" "testing" "time" ) @@ -34,6 +37,9 @@ func TestNormalizeAliases(t *testing.T) { if NormalizeBoardType("gift_sent") != BoardSent { t.Fatal("gift_sent should normalize to sent") } + if NormalizeBoardType("gaming") != BoardGame { + t.Fatal("gaming should normalize to game") + } if NormalizePeriod("monthly") != PeriodMonth { t.Fatal("monthly should normalize to month") } @@ -49,4 +55,63 @@ func TestStoreKeyPrefixAndBucketAreStable(t *testing.T) { if got := store.itemKey("hyapp_prod", BoardReceived, PeriodToday, time.Date(2026, 6, 26, 0, 0, 0, 0, time.UTC), "10001"); got != "activity:user_leaderboard:hyapp_prod:received:today:20260626:users:10001" { t.Fatalf("item key mismatch: %s", got) } + if got := store.scoreKey("huwaa", BoardGame, PeriodMonth, time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC)); got != "activity:user_leaderboard:huwaa:game:month:202607:scores" { + t.Fatalf("game score key mismatch: %s", got) + } +} + +func TestApplyGameEventUsesDedicatedRedisBucket(t *testing.T) { + redisAddr := os.Getenv("HYAPP_TEST_REDIS_ADDR") + if redisAddr == "" { + t.Skip("HYAPP_TEST_REDIS_ADDR is not set") + } + ctx := context.Background() + client, err := NewRedisClient(ctx, redisAddr, "", 0) + if err != nil { + t.Fatalf("connect test Redis: %v", err) + } + defer client.Close() + prefix := fmt.Sprintf("test:user_leaderboard:%d", time.Now().UnixNano()) + defer func() { + keys, _, scanErr := client.Scan(ctx, 0, prefix+":*", 100).Result() + if scanErr == nil && len(keys) > 0 { + _ = client.Del(ctx, keys...).Err() + } + }() + store := NewStore(client, prefix) + occurredAt := time.Date(2026, 7, 15, 12, 0, 0, 0, time.UTC) + event := GameEvent{ + AppCode: "huwaa", + EventID: "game_level:test_order_1", + UserID: 20002, + CoinSpent: 120, + OccurredAtMS: occurredAt.UnixMilli(), + } + + applied, err := store.ApplyGameEvent(ctx, event) + if err != nil || !applied { + t.Fatalf("first game event should apply: applied=%v err=%v", applied, err) + } + applied, err = store.ApplyGameEvent(ctx, event) + if err != nil || applied { + t.Fatalf("duplicate game event should no-op: applied=%v err=%v", applied, err) + } + page, err := store.List(ctx, Query{ + AppCode: "huwaa", + BoardType: BoardGame, + Period: PeriodToday, + Page: 1, + PageSize: 20, + Now: occurredAt.Add(time.Minute), + }) + if err != nil { + t.Fatalf("list game leaderboard: %v", err) + } + if page.BoardType != BoardGame || page.Total != 1 || len(page.Items) != 1 || page.Items[0].UserID != "20002" || page.Items[0].GiftValue != 120 || page.Items[0].GiftCount != 0 || page.Items[0].TransactionCount != 1 || page.Items[0].LastGiftAtMS != occurredAt.UnixMilli() { + t.Fatalf("game leaderboard item mismatch: %+v", page) + } + sent, err := store.List(ctx, Query{AppCode: "huwaa", BoardType: BoardSent, Period: PeriodToday, Page: 1, PageSize: 20, Now: occurredAt.Add(time.Minute)}) + if err != nil || sent.Total != 0 { + t.Fatalf("game event must not leak into sent board: page=%+v err=%v", sent, err) + } } diff --git a/pkg/xerr/catalog.go b/pkg/xerr/catalog.go index 3c1d954f..d039a6e6 100644 --- a/pkg/xerr/catalog.go +++ b/pkg/xerr/catalog.go @@ -27,6 +27,18 @@ var catalog = map[Code]Spec{ NotFound: spec(codes.NotFound, httpStatusNotFound, NotFound, "not found"), Conflict: spec(codes.FailedPrecondition, httpStatusConflict, Conflict, "request cannot be completed in current state"), RoomClosed: spec(codes.FailedPrecondition, httpStatusConflict, RoomClosed, "room closed"), + RoomRPSChallengeTaken: spec( + codes.FailedPrecondition, + httpStatusConflict, + RoomRPSChallengeTaken, + "手慢啦,该 PK 已被其他人接单", + ), + RoomRPSChallengeExpired: spec( + codes.FailedPrecondition, + httpStatusConflict, + RoomRPSChallengeExpired, + "猜拳已过期", + ), Unauthorized: spec(codes.Unauthenticated, httpStatusUnauthorized, Unauthorized, "unauthorized"), PermissionDenied: spec(codes.PermissionDenied, httpStatusForbidden, PermissionDenied, "permission denied"), @@ -84,6 +96,14 @@ var catalog = map[Code]Spec{ VIPLevelNotFound: spec(codes.NotFound, httpStatusNotFound, VIPLevelNotFound, "not found"), VIPLevelDisabled: spec(codes.FailedPrecondition, httpStatusConflict, VIPLevelDisabled, "vip level is disabled"), VIPDowngradeNotAllowed: spec(codes.FailedPrecondition, httpStatusConflict, VIPDowngradeNotAllowed, "vip downgrade is not allowed"), + VIPProgramInactive: spec(codes.FailedPrecondition, httpStatusConflict, VIPProgramInactive, "vip program is inactive"), + VIPPackageNotPurchasable: spec(codes.FailedPrecondition, httpStatusConflict, VIPPackageNotPurchasable, "vip package is not purchasable"), + VIPInsufficientCoin: spec(codes.FailedPrecondition, httpStatusConflict, VIPInsufficientCoin, "insufficient coin balance"), + VIPTrialCardNotFound: spec(codes.NotFound, httpStatusNotFound, VIPTrialCardNotFound, "vip trial card not found"), + VIPTrialCardExpired: spec(codes.FailedPrecondition, httpStatusConflict, VIPTrialCardExpired, "vip trial card expired"), + VIPBenefitRequired: spec(codes.PermissionDenied, httpStatusForbidden, VIPBenefitRequired, "vip benefit is required"), + VIPAntiKick: spec(codes.PermissionDenied, httpStatusForbidden, VIPAntiKick, "target user cannot be kicked"), + VIPAntiMute: spec(codes.PermissionDenied, httpStatusForbidden, VIPAntiMute, "target user cannot be muted"), VIPRechargeRequired: spec(codes.FailedPrecondition, httpStatusConflict, VIPRechargeRequired, "vip recharge is required"), VIPCoinRebateNotFound: spec(codes.NotFound, httpStatusNotFound, VIPCoinRebateNotFound, "vip coin rebate not found"), VIPCoinRebateExpired: spec(codes.FailedPrecondition, httpStatusConflict, VIPCoinRebateExpired, "vip coin rebate expired"), diff --git a/pkg/xerr/errors.go b/pkg/xerr/errors.go index 91d92bcc..ca386c2a 100644 --- a/pkg/xerr/errors.go +++ b/pkg/xerr/errors.go @@ -18,6 +18,10 @@ const ( Conflict Code = "CONFLICT" // RoomClosed 表示房间已被后台关闭,客户端不能再进入。 RoomClosed Code = "ROOM_CLOSED" + // RoomRPSChallengeTaken 表示房内猜拳挑战已被其他用户接单,当前用户不能再重复应战。 + RoomRPSChallengeTaken Code = "ROOM_RPS_CHALLENGE_TAKEN" + // RoomRPSChallengeExpired 表示房内猜拳挑战已越过无人应战截止时间,客户端应关闭应战入口并提示过期。 + RoomRPSChallengeExpired Code = "ROOM_RPS_CHALLENGE_EXPIRED" // Unauthorized 表示身份不存在或认证失败。 Unauthorized Code = "UNAUTHORIZED" // PermissionDenied 表示已认证但没有执行权限。 @@ -102,6 +106,22 @@ const ( VIPLevelDisabled Code = "VIP_LEVEL_DISABLED" // VIPDowngradeNotAllowed 表示用户当前有效 VIP 等级高于本次购买目标等级。 VIPDowngradeNotAllowed Code = "VIP_DOWNGRADE_NOT_ALLOWED" + // VIPProgramInactive 表示当前 App 未启用可执行的 VIP 体系。 + VIPProgramInactive Code = "VIP_PROGRAM_INACTIVE" + // VIPPackageNotPurchasable 表示目标套餐不存在、停用或不在当前体系等级范围内。 + VIPPackageNotPurchasable Code = "VIP_PACKAGE_NOT_PURCHASABLE" + // VIPInsufficientCoin 表示 VIP 购买事务中的 COIN 余额不足。 + VIPInsufficientCoin Code = "VIP_INSUFFICIENT_COIN" + // VIPTrialCardNotFound 表示体验卡实例不存在、不属于当前用户或其背包权益已撤销。 + VIPTrialCardNotFound Code = "VIP_TRIAL_CARD_NOT_FOUND" + // VIPTrialCardExpired 表示体验卡或对应背包权益已越过绝对过期时间。 + VIPTrialCardExpired Code = "VIP_TRIAL_CARD_EXPIRED" + // VIPBenefitRequired 表示当前操作需要一项未生效或已被用户关闭的 VIP 权益。 + VIPBenefitRequired Code = "VIP_BENEFIT_REQUIRED" + // VIPAntiKick 表示普通房主/管理员踢人动作被目标用户的防踢权益拦截。 + VIPAntiKick Code = "VIP_ANTI_KICK" + // VIPAntiMute 表示普通房主/管理员禁言动作被目标用户的防禁言权益拦截。 + VIPAntiMute Code = "VIP_ANTI_MUTE" // VIPRechargeRequired 表示目标 VIP 等级需要用户先达到累计充值门槛。 VIPRechargeRequired Code = "VIP_RECHARGE_REQUIRED" // VIPCoinRebateNotFound 表示返现不存在,或不属于当前 App/用户。 diff --git a/pkg/xerr/grpc_test.go b/pkg/xerr/grpc_test.go index a569bfa5..8ab7b71e 100644 --- a/pkg/xerr/grpc_test.go +++ b/pkg/xerr/grpc_test.go @@ -135,6 +135,14 @@ func TestCatalogMappings(t *testing.T) { publicCode: string(CPAlreadyExistsOther), publicMessage: "The other party already has a CP", }, + { + name: "vip anti kick keeps actionable forbidden code", + code: VIPAntiKick, + grpcCode: codes.PermissionDenied, + httpStatus: httpStatusForbidden, + publicCode: string(VIPAntiKick), + publicMessage: "target user cannot be kicked", + }, { name: "region mismatch keeps forbidden transport but exposes concrete app prompt", code: RegionMismatch, @@ -143,6 +151,22 @@ func TestCatalogMappings(t *testing.T) { publicCode: string(RegionMismatch), publicMessage: "不是同一个地区", }, + { + name: "room rps taken exposes late challenger prompt", + code: RoomRPSChallengeTaken, + grpcCode: codes.FailedPrecondition, + httpStatus: httpStatusConflict, + publicCode: string(RoomRPSChallengeTaken), + publicMessage: "手慢啦,该 PK 已被其他人接单", + }, + { + name: "room rps expired exposes actionable prompt", + code: RoomRPSChallengeExpired, + grpcCode: codes.FailedPrecondition, + httpStatus: httpStatusConflict, + publicCode: string(RoomRPSChallengeExpired), + publicMessage: "猜拳已过期", + }, } for _, test := range tests { diff --git a/scripts/apply-local-mysql-initdb.sh b/scripts/apply-local-mysql-initdb.sh index c23340d5..eab81850 100755 --- a/scripts/apply-local-mysql-initdb.sh +++ b/scripts/apply-local-mysql-initdb.sh @@ -29,12 +29,14 @@ SQL_FILES=( ) # initdb only creates missing tables; a reused local MySQL volume therefore -# needs incremental migrations as well. Keep the owned user-service migrations -# in this local bootstrap path so authentication schema changes (for example -# login_audit client-version fields) cannot leave a locally logged-in client -# receiving a misleading 401 during token refresh. -USER_MIGRATION_FILES=( +# needs incremental migrations as well. Keep owner migrations here when reused +# volumes need more than CREATE TABLE IF NOT EXISTS can provide; otherwise new +# binaries may start against a structurally valid-looking but stale table. +INCREMENTAL_MIGRATION_FILES=( "services/user-service/deploy/mysql/migrations/012_login_audit_client_version.sql" + "services/user-service/deploy/mysql/migrations/017_cp_application_gift_coin_value.sql" + "services/user-service/deploy/mysql/migrations/018_auth_refresh_token_rotation.sql" + "services/wallet-service/deploy/mysql/migrations/002_resource_shop_price_tiers.sql" ) # Keep MySQL as the only required dependency for this script. Business services @@ -71,7 +73,7 @@ for sql_file in "${SQL_FILES[@]}"; do docker compose exec -T mysql mysql --default-character-set=utf8mb4 -h 127.0.0.1 -uroot -p"${MYSQL_ROOT_PASSWORD}" < "${sql_file}" done -for sql_file in "${USER_MIGRATION_FILES[@]}"; do +for sql_file in "${INCREMENTAL_MIGRATION_FILES[@]}"; do if [[ ! -f "${sql_file}" ]]; then printf 'skipping mysql migration because it is absent or not a regular file: %s\n' "${sql_file}" continue diff --git a/scripts/mysql/062_vip_user_settings.sql b/scripts/mysql/062_vip_user_settings.sql index 7b5f77d5..d4a72b3d 100644 --- a/scripts/mysql/062_vip_user_settings.sql +++ b/scripts/mysql/062_vip_user_settings.sql @@ -9,6 +9,9 @@ CREATE TABLE IF NOT EXISTS user_vip_settings ( user_id BIGINT NOT NULL COMMENT '用户 ID', room_entry_notice_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否开启进房通知', online_global_notice_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否开启上线全服通知', + hide_profile_data_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否开启隐藏个人数据', + anonymous_profile_visit_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否开启匿名访问主页', + leaderboard_invisible_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否开启榜单隐身', created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', PRIMARY KEY (app_code, user_id) diff --git a/scripts/mysql/067_vip_user_privacy_settings.sql b/scripts/mysql/067_vip_user_privacy_settings.sql new file mode 100644 index 00000000..c14f343e --- /dev/null +++ b/scripts/mysql/067_vip_user_privacy_settings.sql @@ -0,0 +1,33 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +USE hyapp_wallet; + +-- user_vip_settings 以 (app_code,user_id) 为主键且新增列均为常量默认值。MySQL 8.4 可用 +-- ALGORITHM=INSTANT 仅修改数据字典,不扫描或重写历史行;MySQL 8.4 的 INSTANT 算法不接受 +-- 显式 LOCK 子句,因此只保留算法硬约束,避免语法失败且禁止静默退化为 COPY/INPLACE。 +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_vip_settings' AND COLUMN_NAME = 'hide_profile_data_enabled') = 0, + 'ALTER TABLE user_vip_settings ADD COLUMN hide_profile_data_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT ''是否开启隐藏个人数据'', ALGORITHM=INSTANT', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_vip_settings' AND COLUMN_NAME = 'anonymous_profile_visit_enabled') = 0, + 'ALTER TABLE user_vip_settings ADD COLUMN anonymous_profile_visit_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT ''是否开启匿名访问主页'', ALGORITHM=INSTANT', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_vip_settings' AND COLUMN_NAME = 'leaderboard_invisible_enabled') = 0, + 'ALTER TABLE user_vip_settings ADD COLUMN leaderboard_invisible_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT ''是否开启榜单隐身'', ALGORITHM=INSTANT', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; diff --git a/scripts/mysql/068_wallet_withdrawal_terminal_locks.sql b/scripts/mysql/068_wallet_withdrawal_terminal_locks.sql new file mode 100644 index 00000000..de09a5a7 --- /dev/null +++ b/scripts/mysql/068_wallet_withdrawal_terminal_locks.sql @@ -0,0 +1,11 @@ +USE hyapp_wallet; + +-- 该表只按用户提现申请增长,创建空表不扫描 wallet_transactions,不会在现有 10GB 级流水表上建索引或持有行锁。 +-- 必须在部署包含新终局幂等逻辑的 wallet-service 之前执行;CREATE TABLE IF NOT EXISTS 可安全重复执行。 +CREATE TABLE IF NOT EXISTS wallet_withdrawal_terminal_locks ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码', + withdrawal_application_id VARCHAR(64) 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, withdrawal_application_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='提现申请钱包终局串行锁'; diff --git a/server/admin/cmd/server/main.go b/server/admin/cmd/server/main.go index fba94b91..bf00ea17 100644 --- a/server/admin/cmd/server/main.go +++ b/server/admin/cmd/server/main.go @@ -45,6 +45,7 @@ import ( dailytaskmodule "hyapp-admin-server/internal/modules/dailytask" dashboardmodule "hyapp-admin-server/internal/modules/dashboard" databimodule "hyapp-admin-server/internal/modules/databi" + externaladminmodule "hyapp-admin-server/internal/modules/externaladmin" financeordermodule "hyapp-admin-server/internal/modules/financeorder" financewithdrawalmodule "hyapp-admin-server/internal/modules/financewithdrawal" firstrechargerewardmodule "hyapp-admin-server/internal/modules/firstrechargereward" @@ -103,6 +104,7 @@ import ( "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" + userv1 "hyapp.local/api/proto/user/v1" walletv1 "hyapp.local/api/proto/wallet/v1" ) @@ -382,7 +384,24 @@ func main() { return paymentmodule.RegionIDForCountryCode(ctx, moneyRegionSources, appCode, countryCode) })), FinanceWithdrawal: financewithdrawalmodule.New(store, walletclient.NewGRPC(walletConn), activityclient.NewGRPC(activityConn), auditHandler), - FullServerNotice: fullservernoticemodule.New(activityclient.NewGRPC(activityConn), auditHandler), + ExternalAdmin: externaladminmodule.New(db, userDB, externaladminmodule.Config{ + SessionTTL: cfg.ExternalAdmin.SessionTTL, + MaxLoginFailures: cfg.ExternalAdmin.MaxLoginFailures, + LockDuration: cfg.ExternalAdmin.LockDuration, + CookieSecure: cfg.RefreshCookieSecure, + CookieSameSite: cfg.RefreshCookieSameSite, + LoginRateLimit: externaladminmodule.LoginRateLimitConfig{ + Window: cfg.ExternalAdmin.LoginRateLimit.Window, + SystemLimit: cfg.ExternalAdmin.LoginRateLimit.SystemLimit, + AppLimit: cfg.ExternalAdmin.LoginRateLimit.AppLimit, + IPLimit: cfg.ExternalAdmin.LoginRateLimit.IPLimit, + IdentityLimit: cfg.ExternalAdmin.LoginRateLimit.IdentityLimit, + }, + }, auditHandler, + externaladminmodule.WithUserHostClient(userv1.NewUserHostServiceClient(userConn)), + externaladminmodule.WithLoginRateLimiter(redisClient), + ), + FullServerNotice: fullservernoticemodule.New(activityclient.NewGRPC(activityConn), auditHandler), Game: gamemanagementmodule.New( gameclient.NewGRPC(gameConn), userclient.NewGRPC(userConn), diff --git a/server/admin/configs/config.tencent.example.yaml b/server/admin/configs/config.tencent.example.yaml index 1a5f190f..d3158544 100644 --- a/server/admin/configs/config.tencent.example.yaml +++ b/server/admin/configs/config.tencent.example.yaml @@ -8,6 +8,11 @@ log: include_response_body: false max_payload_bytes: 2048 http_addr: "127.0.0.1:13100" +# 示例只信任本机回源代理;上线必须按实际 RemoteAddr 验证 Nginx/Caddy/ +# Docker/EdgeOne 完整链路,仅追加精确 hop,禁止信任整段私网。 +trusted_proxies: + - "127.0.0.0/8" + - "::1" mysql_dsn: "admin_user:REPLACE_ME@tcp(10.2.21.3:3306)/hyapp_admin?parseTime=true&charset=utf8mb4&loc=UTC" user_mysql_dsn: "user_reader:REPLACE_ME@tcp(10.2.21.3:3306)/hyapp_user?parseTime=true&charset=utf8mb4&loc=UTC" wallet_mysql_dsn: "wallet_reader:REPLACE_ME@tcp(10.2.21.3:3306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=UTC" @@ -80,6 +85,16 @@ cors_allowed_origins: - "https://api-acc.global-interaction.com" refresh_cookie_secure: true refresh_cookie_same_site: "none" +external_admin: + session_ttl: "12h" + max_login_failures: 5 + lock_duration: "15m" + login_rate_limit: + window: "60s" + system_limit: 300 + app_limit: 120 + ip_limit: 30 + identity_limit: 10 bootstrap: # 仅首次初始化或显式 -bootstrap 时打开;生产常驻进程不要每次启动重放 seed。 enabled: false diff --git a/server/admin/configs/config.yaml b/server/admin/configs/config.yaml index 30734e78..766612ec 100644 --- a/server/admin/configs/config.yaml +++ b/server/admin/configs/config.yaml @@ -8,6 +8,9 @@ log: include_response_body: false max_payload_bytes: 2048 http_addr: ":13100" +trusted_proxies: + - "127.0.0.0/8" + - "::1" mysql_dsn: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_admin?parseTime=true&charset=utf8mb4&loc=UTC" user_mysql_dsn: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_user?parseTime=true&charset=utf8mb4&loc=UTC" wallet_mysql_dsn: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=UTC" @@ -80,6 +83,16 @@ cors_allowed_origins: - "http://127.0.0.1:7002" refresh_cookie_secure: false refresh_cookie_same_site: "lax" +external_admin: + session_ttl: "12h" + max_login_failures: 5 + lock_duration: "15m" + login_rate_limit: + window: "60s" + system_limit: 300 + app_limit: 120 + ip_limit: 30 + identity_limit: 10 bootstrap: enabled: true seed_demo_data: true diff --git a/server/admin/docs/外管后台.md b/server/admin/docs/外管后台.md new file mode 100644 index 00000000..81f6934d --- /dev/null +++ b/server/admin/docs/外管后台.md @@ -0,0 +1,67 @@ +# 外管后台 + +## 系统边界 + +外管后台是独立于主后台、Databi 和 Finance 的浏览器入口: + +- 主后台 `/operations/external-admin-users` 继续使用主后台 JWT、RBAC 和全局 App 选择器,负责查找 App 用户、签发外管账号、配置权限、启停账号和重置密码。 +- 外管入口 `/external-admin/` 使用独立账号、服务端 opaque session 和 CSRF token,不读取主后台 token 或 localStorage。 +- 外管账号、会话、登录日志和操作日志分别保存在 `external_admin_accounts`、`external_admin_sessions`、`external_admin_login_logs`、`external_admin_operation_logs`。 +- 登录只提交外管账号和密码,不提交或选择 App。账号名全局唯一,服务端通过账号行自动确定 `app_code` 并固化到会话;Fami 账号只能访问 Fami 数据,请求头缺省时由会话补齐,伪造其他 App 时直接拒绝。 + +## 账号签发和岗位边界 + +创建账号时必须先在当前 App 内用长 ID、短 ID 或靓号精确匹配用户,再提交服务端返回的稳定 `user_id`。昵称不参与绑定,避免重名用户拿到外管凭据。 + +- `platform-admin`:查看、创建、配置权限、启停和重置密码。创建账号必须同时具备 `external-admin-user:create` 和 `external-admin-user:permissions`,避免只有凭据创建权限的调用方通过省略权限字段签发默认全权限账号。 +- `ops-admin`、`operations-specialist`:查看、启停。运营岗位不能通过创建或重置账号间接获得自身权限矩阵中没有的 VIP 发放等能力。 +- 外管登录账号名跨 App 全局唯一;绑定 App 用户仍按 `(app_code, linked_app_user_id)` 唯一。创建服务先做全局账号名检查,数据库唯一索引负责收敛并发创建竞态。 +- 创建、重置后的密码可直接使用,不要求首次登录修改;停用或重置仍会撤销该账号的全部活跃会话。 + +## 权限配置 + +- `GET /api/v1/admin/external-admin-users/permission-catalog` 返回固定的 20 项业务权限目录;服务端只接受目录内 code,不接受通配符或主后台 RBAC code。 +- `GET /api/v1/admin/external-admin-users/:id/permissions` 按当前 App 返回权限快照和 `revision`;`PUT` 必须提交 `permissions` 与 `expectedRevision`。版本不一致返回 409,防止两个管理员互相覆盖。 +- 创建请求省略 `permissions` 时保留兼容行为,使用完整默认目录;显式 `[]` 表示零业务权限。无论是否省略字段,调用方都必须具备权限委派能力。 +- 权限实际变化与撤销该账号全部活跃会话在同一事务提交,并递增 `permission_revision`;相同快照重复提交不递增版本、不重复撤销会话。 +- 特权道具、用户称号和房间背景图在 owner 资源模型可可靠分类前按一个原子权限包校验,不能只选择其中一项。外管资源与 VIP 发放使用 `manager_center` 来源,由 Wallet 在写事务内再次检查经理可发放规则;主后台仍使用原有来源。 + +## 外管能力 + +外管只注册显式白名单路由,不提供主后台的通用代理能力: + +- 用户:用户列表、资料编辑、封禁列表、封禁和解封。 +- 组织:主播、公会、BD、BD Manager、Super Admin 列表和我的团队。 +- 房间:房间列表和房间编辑。 +- 发放:特权道具、靓号、用户称号、房间背景图和财富/VIP 等级。 +- 运营:Banner 创建。 + +底层业务写入仍由各 owner service 或既有后台 Handler 负责;外管模块只做独立认证、App 约束、权限白名单和审计,不复制用户、房间或钱包业务事实。 + +## 登录安全 + +- Session cookie 为 HttpOnly,作用域仅 `/api/v1/external`;写请求同时校验 CSRF cookie、header 和服务端 hash。 +- Session 绝对有效期默认 12 小时。每次请求都会确认账号和 App 仍为 active;App 停用后旧会话不能绕过 `/auth/me` 直接调用业务接口。 +- 同一账号连续失败 5 次后锁定 15 分钟;账号、密码或账号所属 App 不可用均对外返回相同的 HTTP 401 / 业务码 40100,前端按当前语言渲染本地化文案。 +- Redis 在账号查询、bcrypt 和登录日志之前,先按系统全局 300、单真实 IP 30、全局账号名 10 执行 60 秒固定窗口限流;命中唯一账号后,再按服务端解析出的 App 执行单 App 120 限流。两个阶段不会重复消耗系统/IP/账号计数,请求中的旧版 `appCode` 字段即使存在也会被忽略。 +- 登录请求体上限为 8 KiB;限流 Redis 在 200 ms 内不可用时 fail-closed 返回 503,不降级为可绕过的单机计数。 +- 认证接口统一返回 `Cache-Control: no-store`。 + +## 上线步骤 + +1. 通过 admin-server 迁移器依次应用 `migrations/098_external_admin_portal.sql`、`099_external_admin_credential_delegation.sql`、`100_external_admin_global_username.sql` 和 `101_external_admin_permission_assignment.sql`。发布前先执行 `EXPLAIN SELECT username, COUNT(*) FROM external_admin_accounts GROUP BY username HAVING COUNT(*) > 1` 评估访问计划,再执行同一查询确认结果为空。该检查和 100 的唯一索引构建只扫描小型凭据表,不访问用户、房间或钱包表;100、101 使用 `INPLACE + LOCK=NONE`,但仍建议避开凭据集中创建时段。101 只为小型凭据表增加定长版本列并写入一项平台权限,不扫描或更新业务数据。若 100 检测到重复,DDL 会 fail-closed,不会自动改名或删除账号;先由业务确认保留的登录名并处理冲突,再清理迁移器 dirty 记录并重跑。 +2. 确认 Redis 已启用且 `/readyz` 为成功。生产配置缺少 Redis 时 admin-server 会拒绝启动,运行中限流 Redis 故障会阻断新登录但不破坏已建立会话。 +3. 配置 `trusted_proxies` 为真实入口链路的精确 IP/CIDR。默认只信任 loopback;不要信任 `0.0.0.0/0`、`::/0` 或整段未知私网。 +4. 构建并发布前端 `dist/external-admin/`,保留 Nginx 对 `/external-admin` 的 301 和所有 `/external-admin/*` 深链回退到独立 HTML。 +5. 在 EdgeOne/WAF 对精确路径 `POST /api/v1/external/auth/login` 配置按真实客户端 IP 的 token-bucket/挑战规则,建议基线 30 次/分钟、burst 10;同时限制源站直连。WAF 负责 Redis 前的大包和连接洪峰,应用层 Redis 负责系统、App 和账号维度的正确性。 + +## 上线验收 + +- 登录请求不带 App 即可进入账号所属租户;即使旧客户端伪造其他 `appCode`,也必须登录到账号行所属 App。Fami 账号登录后请求 Lalu 的 `X-App-Code` 必须返回 403,省略 header 时仍只能看到 Fami 数据。 +- 外管账号或 App 停用后,已有会话直接访问任一业务接口必须返回 401。 +- 创建或重置密码后可直接进入已授权页面;历史 `password_change_required` 标记也不能阻断登录或业务接口。 +- 用旧 `revision` 更新权限必须返回 409;成功减少权限后旧会话必须立即返回 401,原权限接口必须返回 403。重复提交相同快照时版本保持不变。 +- 从同一真实 IP 连发超过阈值的登录请求必须返回 429 和 `Retry-After`;伪造 `X-Forwarded-For` 不能改变限流身份。 +- Redis 临时不可用时新登录应在约 200 ms 后返回 503;恢复后不需要重启服务。 +- `/external-admin/`、一个桌面深链和一个移动端深链均返回外管独立 HTML,不能回退到主后台入口。 +- 停用、密码重置、封禁、房间编辑、资源/VIP 发放和 Banner 创建均应在外管操作日志中留下 App、外管账号、请求 ID、资源 ID 和结果。 diff --git a/server/admin/docs/权限管理.md b/server/admin/docs/权限管理.md index 1d99edca..6dc6c4c0 100644 --- a/server/admin/docs/权限管理.md +++ b/server/admin/docs/权限管理.md @@ -282,9 +282,24 @@ | `wallet:view` | `menu` | 钱包概览、余额查询 | | `wallet:transaction-view` | `menu` | 交易流水 | | `wallet:adjust` | `button` | 后台调账 | -| `withdrawal:view` | `menu` | 提现记录 | -| `withdrawal:review` | `button` | 提现审核 | -| `withdrawal:export` | `button` | 提现导出 | +| `operations-withdrawal:view` | `menu` | 用户提现运营审核列表;不包含 `operations_status=skipped` 的历史单 | +| `operations-withdrawal:audit` | `button` | 运营初审;通过后转交财务,拒绝时释放冻结余额并终止流程 | +| `finance-withdrawal:view` | `menu` | 用户提现财务审核列表;只包含运营已通过和 `skipped` 历史兼容单 | +| `finance-withdrawal:audit` | `button` | 财务终审;通过时扣减 frozen,拒绝时释放 frozen | + +两个提现工作台都以 `admin_user_money_scopes` 作为 App 数据范围:显式选择 App 时必须命中授权,未选 App 的列表只查授权 App 集合,仅 `platform-admin` 的全量资金范围可跨全部 App。审核请求必须显式携带目标行的 `X-App-Code`,后端会在钱包动作前再校验 MoneyAccess。`GET /admin/finance/scope` 仅返回这份授权目录,其读权限为 `finance:view`、`finance-withdrawal:view|audit` 或 `operations-withdrawal:view|audit`,不因此赋予审核写权。 + +运营状态 `rejecting` 表示拒绝 claim 已独立提交、钱包释放或通知/终态收敛仍需重试。该状态只能继续调用原拒绝接口,后端沿用第一次审核人、原因和固定 command;不能改点通过,也不会进入财务列表。运营工作台必须显示“重试拒绝”,不能把它当成普通 `pending`。 + +#### 用户提现两级审核发布顺序 + +`102_user_withdrawal_operations_review.sql` 不能和旧 admin 实例混跑。旧 admin 只识别总体 `status=pending`,会绕过 `operations_status` 直接调钱包终审。生产必须按以下顺序发布: + +1. 先执行 `scripts/mysql/068_wallet_withdrawal_terminal_locks.sql`,完成新 wallet-service 的全量滚动,确保所有钱包实例都能按申请 ID 收敛旧/新 command。 +2. 摘流所有旧 admin 实例,确认无旧版财务审核请求在飞。 +3. 执行 admin 102 迁移。迁移持久化当时的最大申请 ID,仅把该范围内已经终审的历史行标记 `skipped`;尚未终审的 `status=pending` 申请和迁移后新申请都保持运营 `pending`。 +4. 部署新 admin 并恢复流量,验证运营/财务列表和 MoneyAccess 隔离。 +5. 最后滚动 gateway。即使窗口内旧 gateway 不写 `operations_status`,数据库默认也会让新单进入运营待审。 ### 礼物和活动 @@ -350,6 +365,7 @@ `ops-admin` - 负责运营、团队、房间、资源、活动和游戏的日常管理。 +- 负责用户提现运营初审,不拥有用户提现财务终审权限。 - 不包含后台设置、版本管理、财务负责人看板和三方汇率编辑/全局同步。 ### 运营专员 @@ -357,6 +373,7 @@ `operations-specialist` - 可执行用户、团队结构、房间、资源和常规运营动作。 +- 可执行用户提现运营初审,不拥有用户提现财务终审权限。 - 活动配置和游戏列表/自研游戏只读;可管理全站机器人和房内猜拳配置。 ### 产品负责人 @@ -377,13 +394,13 @@ `finance-lead` -- 只进入财务看板、充值对账、提现审核和房内猜拳订单。 +- 只进入财务看板、充值对账、用户提现财务终审和房内猜拳订单;不参与运营初审。 ### 财务专员 `finance-specialist` -- 当前与财务负责人使用同一权限矩阵;保留独立角色用于人员分工和后续数据范围配置。 +- 当前与财务负责人使用同一权限矩阵,负责用户提现财务终审且不参与运营初审;保留独立角色用于人员分工和后续数据范围配置。 固定岗位执行“同步权限”或显式 bootstrap 时按上述矩阵精确重建,清除历史跨模块绑定。历史 `auditor`、`readonly` 和用户自建角色不会被删除或重置。 diff --git a/server/admin/internal/cache/redis.go b/server/admin/internal/cache/redis.go index 94614641..841b8278 100644 --- a/server/admin/internal/cache/redis.go +++ b/server/admin/internal/cache/redis.go @@ -3,6 +3,8 @@ package cache import ( "context" "errors" + "fmt" + "strconv" "strings" "time" @@ -18,14 +20,54 @@ type Redis struct { type UnlockFunc func(context.Context) error +var ErrRedisUnavailable = errors.New("redis is unavailable") + +type FixedWindowRule struct { + Key string + Limit uint64 +} + +type FixedWindowDecision struct { + Allowed bool + RetryAfter time.Duration +} + +// fixedWindowScript consumes every rule in one Redis-side operation. All rate-limit +// keys use one Cluster hash tag at the caller, so EVAL remains atomic without CROSSSLOT. +// Rejected attempts still increment every layer; expiry is assigned only on the first +// increment and is never renewed, preserving true fixed-window behavior. +const fixedWindowScript = ` +local allowed = 1 +local retry_ms = 0 +local window_ms = tonumber(ARGV[1]) +for i = 1, #KEYS do + local count = redis.call("INCR", KEYS[i]) + if count == 1 then + redis.call("PEXPIRE", KEYS[i], window_ms) + end + local limit = tonumber(ARGV[i + 1]) + if count > limit then + allowed = 0 + local ttl = redis.call("PTTL", KEYS[i]) + if ttl > retry_ms then + retry_ms = ttl + end + end +end +if allowed == 0 and retry_ms <= 0 then + retry_ms = window_ms +end +return {allowed, retry_ms}` + func NewRedis(ctx context.Context, cfg config.RedisConfig) (*Redis, error) { if !cfg.Enabled { return nil, nil } client := redis.NewClient(&redis.Options{ - Addr: cfg.Addr, - Password: cfg.Password, - DB: cfg.DB, + Addr: cfg.Addr, + Password: cfg.Password, + DB: cfg.DB, + ContextTimeoutEnabled: true, }) if err := client.Ping(ctx).Err(); err != nil { _ = client.Close() @@ -88,6 +130,48 @@ return 0` return result == 1, err } +// ConsumeFixedWindow atomically increments all supplied counters and decides whether +// every limit still allows the request. A nil/disabled Redis is an availability error, +// not an implicit allow: security callers must fail closed instead of falling back to +// per-process memory that attackers could bypass by switching replicas. +func (r *Redis) ConsumeFixedWindow(ctx context.Context, window time.Duration, rules []FixedWindowRule) (FixedWindowDecision, error) { + if r == nil || r.client == nil { + return FixedWindowDecision{}, ErrRedisUnavailable + } + if window < time.Millisecond || len(rules) == 0 { + return FixedWindowDecision{}, errors.New("positive fixed window and at least one rule are required") + } + keys := make([]string, 0, len(rules)) + args := make([]any, 0, len(rules)+1) + args = append(args, window.Milliseconds()) + seen := make(map[string]struct{}, len(rules)) + for _, rule := range rules { + key := strings.TrimSpace(rule.Key) + if key == "" || rule.Limit == 0 { + return FixedWindowDecision{}, errors.New("fixed-window keys and limits must be non-empty") + } + key = r.key(key) + if _, exists := seen[key]; exists { + return FixedWindowDecision{}, fmt.Errorf("duplicate fixed-window key %q", key) + } + seen[key] = struct{}{} + keys = append(keys, key) + args = append(args, strconv.FormatUint(rule.Limit, 10)) + } + result, err := r.client.Eval(ctx, fixedWindowScript, keys, args...).Int64Slice() + if err != nil { + return FixedWindowDecision{}, fmt.Errorf("%w: %v", ErrRedisUnavailable, err) + } + if len(result) != 2 || (result[0] != 0 && result[0] != 1) { + return FixedWindowDecision{}, fmt.Errorf("%w: invalid fixed-window response", ErrRedisUnavailable) + } + retryAfter := time.Duration(result[1]) * time.Millisecond + if result[0] == 0 && retryAfter <= 0 { + retryAfter = window + } + return FixedWindowDecision{Allowed: result[0] == 1, RetryAfter: retryAfter}, nil +} + func (r *Redis) key(key string) string { if r.prefix == "" { return key diff --git a/server/admin/internal/cache/redis_fixed_window_test.go b/server/admin/internal/cache/redis_fixed_window_test.go new file mode 100644 index 00000000..aa2cf26f --- /dev/null +++ b/server/admin/internal/cache/redis_fixed_window_test.go @@ -0,0 +1,34 @@ +package cache + +import ( + "context" + "errors" + "strings" + "testing" + "time" +) + +func TestConsumeFixedWindowFailsClosedWithoutRedis(t *testing.T) { + _, err := (*Redis)(nil).ConsumeFixedWindow(context.Background(), time.Minute, []FixedWindowRule{{Key: "rate:{external-login}:system", Limit: 300}}) + if !errors.Is(err, ErrRedisUnavailable) { + t.Fatalf("error = %v, want ErrRedisUnavailable", err) + } +} + +func TestFixedWindowLuaConsumesAllKeysWithoutRenewingExistingTTL(t *testing.T) { + // These source-level invariants protect the security semantics even when unit + // tests run without a Redis daemon: all keys increment before the one final + // return, and PEXPIRE remains inside count==1 so rejected requests never slide TTL. + if strings.Count(fixedWindowScript, `redis.call("INCR"`) != 1 { + t.Fatalf("fixed-window script must increment through one loop: %s", fixedWindowScript) + } + if !strings.Contains(fixedWindowScript, `if count == 1 then`) || !strings.Contains(fixedWindowScript, `redis.call("PEXPIRE"`) { + t.Fatal("fixed-window script must assign expiry only on first increment") + } + if strings.Count(fixedWindowScript, "return {") != 1 { + t.Fatal("fixed-window script must not return early before consuming all keys") + } + if strings.Index(fixedWindowScript, `redis.call("INCR"`) > strings.Index(fixedWindowScript, `if count > limit then`) { + t.Fatal("fixed-window script must increment before deciding") + } +} diff --git a/server/admin/internal/config/config.go b/server/admin/internal/config/config.go index 3b2dcd1d..c3eb684c 100644 --- a/server/admin/internal/config/config.go +++ b/server/admin/internal/config/config.go @@ -3,6 +3,7 @@ package config import ( "errors" "fmt" + "net" "os" "strings" "time" @@ -18,6 +19,7 @@ type Config struct { Environment string `yaml:"environment"` Log logging.Config `yaml:"log"` HTTPAddr string `yaml:"http_addr"` + TrustedProxies []string `yaml:"trusted_proxies"` MySQLDSN string `yaml:"mysql_dsn"` UserMySQLDSN string `yaml:"user_mysql_dsn"` WalletMySQLDSN string `yaml:"wallet_mysql_dsn"` @@ -34,6 +36,7 @@ type Config struct { CORSAllowedOrigins []string `yaml:"cors_allowed_origins"` RefreshCookieSecure bool `yaml:"refresh_cookie_secure"` RefreshCookieSameSite string `yaml:"refresh_cookie_same_site"` + ExternalAdmin ExternalAdminConfig `yaml:"external_admin"` Bootstrap BootstrapConfig `yaml:"bootstrap"` BootstrapPassword string `yaml:"bootstrap_password"` UserService UserServiceConfig `yaml:"user_service"` @@ -57,6 +60,21 @@ type MigrationConfig struct { AllowChecksumRepair bool `yaml:"allow_checksum_repair"` } +type ExternalAdminConfig struct { + SessionTTL time.Duration `yaml:"session_ttl"` + MaxLoginFailures uint `yaml:"max_login_failures"` + LockDuration time.Duration `yaml:"lock_duration"` + LoginRateLimit ExternalAdminLoginRateLimitConfig `yaml:"login_rate_limit"` +} + +type ExternalAdminLoginRateLimitConfig struct { + Window time.Duration `yaml:"window"` + SystemLimit uint64 `yaml:"system_limit"` + AppLimit uint64 `yaml:"app_limit"` + IPLimit uint64 `yaml:"ip_limit"` + IdentityLimit uint64 `yaml:"identity_limit"` +} + type UserServiceConfig struct { Addr string `yaml:"addr"` RequestTimeout time.Duration `yaml:"request_timeout"` @@ -214,6 +232,7 @@ func Default() Config { Environment: "local", Log: logging.DefaultConfig(), HTTPAddr: ":13100", + TrustedProxies: []string{"127.0.0.0/8", "::1"}, MySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_admin?parseTime=true&charset=utf8mb4&loc=UTC", UserMySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_user?parseTime=true&charset=utf8mb4&loc=UTC", WalletMySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=UTC", @@ -280,6 +299,14 @@ func Default() Config { }, RefreshCookieSecure: false, RefreshCookieSameSite: "lax", + ExternalAdmin: ExternalAdminConfig{ + SessionTTL: 12 * time.Hour, + MaxLoginFailures: 5, + LockDuration: 15 * time.Minute, + LoginRateLimit: ExternalAdminLoginRateLimitConfig{ + Window: 60 * time.Second, SystemLimit: 300, AppLimit: 120, IPLimit: 30, IdentityLimit: 10, + }, + }, Bootstrap: BootstrapConfig{ Enabled: true, SeedDemoData: true, @@ -420,10 +447,51 @@ func (cfg *Config) Normalize() { if cfg.Log.MaxPayloadBytes <= 0 { cfg.Log.MaxPayloadBytes = 2048 } + // Gin must never retain its trust-all proxy default: a forged X-Forwarded-For + // would otherwise bypass IP login limits and corrupt every audit record. Keep + // only explicit ingress hops and preserve an empty list as "trust no proxy". + trustedProxies := make([]string, 0, len(cfg.TrustedProxies)) + seenTrustedProxy := make(map[string]struct{}, len(cfg.TrustedProxies)) + for _, proxy := range cfg.TrustedProxies { + proxy = strings.TrimSpace(proxy) + if proxy == "" { + continue + } + if _, exists := seenTrustedProxy[proxy]; exists { + continue + } + seenTrustedProxy[proxy] = struct{}{} + trustedProxies = append(trustedProxies, proxy) + } + cfg.TrustedProxies = trustedProxies cfg.RefreshCookieSameSite = strings.ToLower(strings.TrimSpace(cfg.RefreshCookieSameSite)) if cfg.RefreshCookieSameSite == "" { cfg.RefreshCookieSameSite = "lax" } + if cfg.ExternalAdmin.SessionTTL <= 0 { + cfg.ExternalAdmin.SessionTTL = 12 * time.Hour + } + if cfg.ExternalAdmin.MaxLoginFailures == 0 { + cfg.ExternalAdmin.MaxLoginFailures = 5 + } + if cfg.ExternalAdmin.LockDuration <= 0 { + cfg.ExternalAdmin.LockDuration = 15 * time.Minute + } + if cfg.ExternalAdmin.LoginRateLimit.Window <= 0 { + cfg.ExternalAdmin.LoginRateLimit.Window = 60 * time.Second + } + if cfg.ExternalAdmin.LoginRateLimit.SystemLimit == 0 { + cfg.ExternalAdmin.LoginRateLimit.SystemLimit = 300 + } + if cfg.ExternalAdmin.LoginRateLimit.AppLimit == 0 { + cfg.ExternalAdmin.LoginRateLimit.AppLimit = 120 + } + if cfg.ExternalAdmin.LoginRateLimit.IPLimit == 0 { + cfg.ExternalAdmin.LoginRateLimit.IPLimit = 30 + } + if cfg.ExternalAdmin.LoginRateLimit.IdentityLimit == 0 { + cfg.ExternalAdmin.LoginRateLimit.IdentityLimit = 10 + } cfg.ServiceName = strings.TrimSpace(cfg.ServiceName) cfg.NodeID = strings.TrimSpace(cfg.NodeID) if cfg.NodeID == "" { @@ -642,6 +710,14 @@ func (cfg Config) Validate() error { if strings.TrimSpace(cfg.HTTPAddr) == "" { return errors.New("http_addr is required") } + for _, proxy := range cfg.TrustedProxies { + if net.ParseIP(proxy) != nil { + continue + } + if _, _, err := net.ParseCIDR(proxy); err != nil { + return fmt.Errorf("trusted_proxies contains invalid IP or CIDR %q", proxy) + } + } if strings.TrimSpace(cfg.MySQLDSN) == "" { return errors.New("mysql_dsn is required") } @@ -666,6 +742,27 @@ func (cfg Config) Validate() error { if cfg.RefreshTokenTTL <= 0 { return errors.New("refresh_token_ttl must be greater than 0") } + if cfg.ExternalAdmin.SessionTTL <= 0 { + return errors.New("external_admin.session_ttl must be greater than 0") + } + if cfg.ExternalAdmin.MaxLoginFailures == 0 || cfg.ExternalAdmin.MaxLoginFailures > 20 { + return errors.New("external_admin.max_login_failures must be between 1 and 20") + } + if cfg.ExternalAdmin.LockDuration <= 0 { + return errors.New("external_admin.lock_duration must be greater than 0") + } + if cfg.ExternalAdmin.LoginRateLimit.Window < time.Second || cfg.ExternalAdmin.LoginRateLimit.Window > time.Hour { + return errors.New("external_admin.login_rate_limit.window must be between 1s and 1h") + } + if cfg.ExternalAdmin.LoginRateLimit.SystemLimit == 0 || cfg.ExternalAdmin.LoginRateLimit.AppLimit == 0 || cfg.ExternalAdmin.LoginRateLimit.IPLimit == 0 || cfg.ExternalAdmin.LoginRateLimit.IdentityLimit == 0 { + return errors.New("external_admin.login_rate_limit limits must be greater than 0") + } + if cfg.ExternalAdmin.LoginRateLimit.SystemLimit < cfg.ExternalAdmin.LoginRateLimit.AppLimit { + return errors.New("external_admin.login_rate_limit.system_limit must be greater than or equal to app_limit") + } + if cfg.ExternalAdmin.LoginRateLimit.AppLimit < cfg.ExternalAdmin.LoginRateLimit.IPLimit || cfg.ExternalAdmin.LoginRateLimit.AppLimit < cfg.ExternalAdmin.LoginRateLimit.IdentityLimit { + return errors.New("external_admin.login_rate_limit.app_limit must cover ip_limit and identity_limit") + } switch strings.ToLower(strings.TrimSpace(cfg.RefreshCookieSameSite)) { case "lax", "strict", "none": default: @@ -872,6 +969,9 @@ func (cfg Config) Validate() error { if cfg.Redis.Enabled && strings.TrimSpace(cfg.Redis.Addr) == "" { return errors.New("redis.addr is required when redis is enabled") } + if isLockedEnvironment(cfg.Environment) && !cfg.Redis.Enabled { + return errors.New("redis.enabled must be true outside local/dev for external login rate limiting") + } if cfg.Redis.DB < 0 { return fmt.Errorf("redis.db must be greater than or equal to 0") } diff --git a/server/admin/internal/config/config_test.go b/server/admin/internal/config/config_test.go index 0e2f1c05..e81c724e 100644 --- a/server/admin/internal/config/config_test.go +++ b/server/admin/internal/config/config_test.go @@ -16,6 +16,9 @@ func TestLoadConfigYAML(t *testing.T) { if cfg.HTTPAddr != ":13100" { t.Fatalf("HTTPAddr = %q", cfg.HTTPAddr) } + if !reflect.DeepEqual(cfg.TrustedProxies, []string{"127.0.0.0/8", "::1"}) { + t.Fatalf("TrustedProxies = %#v", cfg.TrustedProxies) + } if cfg.MySQLDSN != "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_admin?parseTime=true&charset=utf8mb4&loc=UTC" { t.Fatalf("MySQLDSN = %q", cfg.MySQLDSN) } @@ -28,6 +31,12 @@ func TestLoadConfigYAML(t *testing.T) { if cfg.RefreshTokenTTL != 7*24*time.Hour { t.Fatalf("RefreshTokenTTL = %s", cfg.RefreshTokenTTL) } + if cfg.ExternalAdmin.SessionTTL != 12*time.Hour || cfg.ExternalAdmin.MaxLoginFailures != 5 || cfg.ExternalAdmin.LockDuration != 15*time.Minute { + t.Fatalf("ExternalAdmin = %#v", cfg.ExternalAdmin) + } + if limit := cfg.ExternalAdmin.LoginRateLimit; limit.Window != time.Minute || limit.SystemLimit != 300 || limit.AppLimit != 120 || limit.IPLimit != 30 || limit.IdentityLimit != 10 { + t.Fatalf("ExternalAdmin.LoginRateLimit = %#v", limit) + } if !cfg.Migrations.AllowChecksumRepair { t.Fatalf("Migrations.AllowChecksumRepair = false, want true for local config") } @@ -36,6 +45,34 @@ func TestLoadConfigYAML(t *testing.T) { } } +func TestExternalAdminLoginRateLimitDefaultsAndValidation(t *testing.T) { + cfg := Default() + cfg.ExternalAdmin.LoginRateLimit = ExternalAdminLoginRateLimitConfig{} + cfg.Normalize() + if limit := cfg.ExternalAdmin.LoginRateLimit; limit.Window != time.Minute || limit.SystemLimit != 300 || limit.AppLimit != 120 || limit.IPLimit != 30 || limit.IdentityLimit != 10 { + t.Fatalf("normalized login rate limit = %#v", limit) + } + + cfg.ExternalAdmin.LoginRateLimit.AppLimit = 301 + if err := cfg.Validate(); err == nil || !strings.Contains(err.Error(), "system_limit") { + t.Fatalf("Validate() error = %v, want system/app hierarchy error", err) + } +} + +func TestProductionRequiresRedisForExternalLoginRateLimit(t *testing.T) { + cfg := Default() + cfg.Environment = "prod" + cfg.JWTSecret = strings.Repeat("s", 32) + cfg.MySQLAutoMigrate = false + cfg.Migrations.AllowChecksumRepair = false + cfg.Bootstrap.Enabled = false + cfg.RobotProfileSource.MySQLDSN = "robot:test@tcp(example:3306)/robot?parseTime=true" + cfg.Redis.Enabled = false + if err := cfg.Validate(); err == nil || !strings.Contains(err.Error(), "redis.enabled") { + t.Fatalf("Validate() error = %v, want production Redis requirement", err) + } +} + func TestLoadEmptyPathUsesDefault(t *testing.T) { cfg, err := Load("") if err != nil { @@ -47,6 +84,14 @@ func TestLoadEmptyPathUsesDefault(t *testing.T) { } } +func TestValidateRejectsInvalidTrustedProxy(t *testing.T) { + cfg := Default() + cfg.TrustedProxies = []string{"not-a-proxy-range"} + if err := cfg.Validate(); err == nil || !strings.Contains(err.Error(), "trusted_proxies") { + t.Fatalf("Validate() error = %v, want trusted_proxies error", err) + } +} + func TestAslanMongoEnvOverride(t *testing.T) { t.Setenv("HYAPP_ADMIN_ASLAN_MONGO_URI", "mongodb://mongouser:secret@example:27017/test?authSource=admin") t.Setenv("HYAPP_ADMIN_ASLAN_DASHBOARD_MONGO_DATABASE", "test_dashboard") diff --git a/server/admin/internal/integration/walletclient/client.go b/server/admin/internal/integration/walletclient/client.go index bbb5bb10..88ad2839 100644 --- a/server/admin/internal/integration/walletclient/client.go +++ b/server/admin/internal/integration/walletclient/client.go @@ -33,6 +33,7 @@ type Client interface { GrantResource(ctx context.Context, req *walletv1.GrantResourceRequest) (*walletv1.ResourceGrantResponse, error) GrantResourceGroup(ctx context.Context, req *walletv1.GrantResourceGroupRequest) (*walletv1.ResourceGrantResponse, error) RevokeResourceGrant(ctx context.Context, req *walletv1.RevokeResourceGrantRequest) (*walletv1.ResourceGrantResponse, error) + RevokeUserResource(ctx context.Context, req *walletv1.RevokeUserResourceRequest) (*walletv1.RevokeUserResourceResponse, error) EquipUserResource(ctx context.Context, req *walletv1.EquipUserResourceRequest) (*walletv1.EquipUserResourceResponse, error) ListResourceGrants(ctx context.Context, req *walletv1.ListResourceGrantsRequest) (*walletv1.ListResourceGrantsResponse, error) ListResourceShopItems(ctx context.Context, req *walletv1.ListResourceShopItemsRequest) (*walletv1.ListResourceShopItemsResponse, error) @@ -173,6 +174,10 @@ func (c *GRPCClient) RevokeResourceGrant(ctx context.Context, req *walletv1.Revo return c.client.RevokeResourceGrant(ctx, req) } +func (c *GRPCClient) RevokeUserResource(ctx context.Context, req *walletv1.RevokeUserResourceRequest) (*walletv1.RevokeUserResourceResponse, error) { + return c.client.RevokeUserResource(ctx, req) +} + func (c *GRPCClient) EquipUserResource(ctx context.Context, req *walletv1.EquipUserResourceRequest) (*walletv1.EquipUserResourceResponse, error) { return c.client.EquipUserResource(ctx, req) } diff --git a/server/admin/internal/middleware/app_scope_test.go b/server/admin/internal/middleware/app_scope_test.go index 9c0d4f4d..832311df 100644 --- a/server/admin/internal/middleware/app_scope_test.go +++ b/server/admin/internal/middleware/app_scope_test.go @@ -1,12 +1,15 @@ package middleware import ( + "errors" "net/http" "net/http/httptest" "testing" + "time" "hyapp-admin-server/internal/model" "hyapp-admin-server/internal/repository" + "hyapp-admin-server/internal/service" "github.com/gin-gonic/gin" ) @@ -15,6 +18,15 @@ type fakeAppAccessStore struct { access repository.AppAccess } +type fakeAuthorizationStore struct { + authorization repository.UserAuthorization + err error +} + +func (store fakeAuthorizationStore) CurrentAuthorizationForUser(uint) (repository.UserAuthorization, error) { + return store.authorization, store.err +} + func (store fakeAppAccessStore) AppAccessForUser(uint) (repository.AppAccess, error) { return store.access, nil } @@ -50,3 +62,67 @@ func TestRequireAppScopeAllowsOnlySelectedApp(t *testing.T) { } } } + +func TestAuthRequiredUsesCurrentPermissionsInsteadOfJWTClaim(t *testing.T) { + gin.SetMode(gin.TestMode) + auth := service.NewAuthService("live-authorization-test-secret", time.Hour) + // This models an access token issued before a role migration: finance audit + // existed in the claim, while operations audit was absent at issue time. + token, _, err := auth.GenerateAccessToken(7, "stale-name", []string{"finance-withdrawal:audit"}) + if err != nil { + t.Fatalf("generate access token: %v", err) + } + + router := gin.New() + router.Use(AuthRequired(auth, fakeAuthorizationStore{authorization: repository.UserAuthorization{ + Username: "current-name", + Status: model.UserStatusActive, + Permissions: []string{"operations-withdrawal:audit"}, + }})) + router.GET("/finance", RequirePermission("finance-withdrawal:audit"), func(c *gin.Context) { + c.Status(http.StatusNoContent) + }) + router.GET("/operations", RequirePermission("operations-withdrawal:audit"), func(c *gin.Context) { + if CurrentUsername(c) != "current-name" { + c.Status(http.StatusInternalServerError) + return + } + c.Status(http.StatusNoContent) + }) + + financeRequest := httptest.NewRequest(http.MethodGet, "/finance", nil) + financeRequest.Header.Set("Authorization", "Bearer "+token) + financeResponse := httptest.NewRecorder() + router.ServeHTTP(financeResponse, financeRequest) + if financeResponse.Code != http.StatusForbidden { + t.Fatalf("removed JWT permission status = %d body=%s", financeResponse.Code, financeResponse.Body.String()) + } + + operationsRequest := httptest.NewRequest(http.MethodGet, "/operations", nil) + operationsRequest.Header.Set("Authorization", "Bearer "+token) + operationsResponse := httptest.NewRecorder() + router.ServeHTTP(operationsResponse, operationsRequest) + if operationsResponse.Code != http.StatusNoContent { + t.Fatalf("current database permission status = %d body=%s", operationsResponse.Code, operationsResponse.Body.String()) + } +} + +func TestAuthRequiredFailsClosedWhenAuthorizationCannotBeResolved(t *testing.T) { + gin.SetMode(gin.TestMode) + auth := service.NewAuthService("authorization-failure-test-secret", time.Hour) + token, _, err := auth.GenerateAccessToken(7, "admin", []string{"role:manage"}) + if err != nil { + t.Fatalf("generate access token: %v", err) + } + + router := gin.New() + router.Use(AuthRequired(auth, fakeAuthorizationStore{err: errors.New("database unavailable")})) + router.GET("/protected", func(c *gin.Context) { c.Status(http.StatusNoContent) }) + request := httptest.NewRequest(http.MethodGet, "/protected", nil) + request.Header.Set("Authorization", "Bearer "+token) + response := httptest.NewRecorder() + router.ServeHTTP(response, request) + if response.Code != http.StatusInternalServerError { + t.Fatalf("authorization database failure status = %d body=%s", response.Code, response.Body.String()) + } +} diff --git a/server/admin/internal/middleware/cors_external_test.go b/server/admin/internal/middleware/cors_external_test.go new file mode 100644 index 00000000..e92c6dcb --- /dev/null +++ b/server/admin/internal/middleware/cors_external_test.go @@ -0,0 +1,37 @@ +package middleware + +import ( + "net/http" + "net/http/httptest" + "strings" + "testing" + + "hyapp-admin-server/internal/config" + + "github.com/gin-gonic/gin" +) + +func TestCORSAllowsAndExposesExternalCSRFHeader(t *testing.T) { + gin.SetMode(gin.TestMode) + engine := gin.New() + engine.Use(CORS(config.Config{CORSAllowedOrigins: []string{"https://admin.example.com"}})) + engine.GET("/api/v1/external/auth/me", func(c *gin.Context) { c.Status(http.StatusNoContent) }) + + request := httptest.NewRequest(http.MethodOptions, "/api/v1/external/auth/me", nil) + request.Header.Set("Origin", "https://admin.example.com") + response := httptest.NewRecorder() + engine.ServeHTTP(response, request) + + if response.Code != http.StatusNoContent { + t.Fatalf("preflight status = %d", response.Code) + } + if !strings.Contains(response.Header().Get("Access-Control-Allow-Headers"), "X-CSRF-Token") { + t.Fatalf("allow headers = %q", response.Header().Get("Access-Control-Allow-Headers")) + } + if !strings.Contains(response.Header().Get("Access-Control-Expose-Headers"), "X-CSRF-Token") { + t.Fatalf("expose headers = %q", response.Header().Get("Access-Control-Expose-Headers")) + } + if response.Header().Get("Access-Control-Allow-Credentials") != "true" { + t.Fatal("credentialed external session must be allowed") + } +} diff --git a/server/admin/internal/middleware/middleware.go b/server/admin/internal/middleware/middleware.go index 9e6314de..41a606a5 100644 --- a/server/admin/internal/middleware/middleware.go +++ b/server/admin/internal/middleware/middleware.go @@ -8,6 +8,7 @@ import ( "hyapp-admin-server/internal/appctx" "hyapp-admin-server/internal/config" + "hyapp-admin-server/internal/model" "hyapp-admin-server/internal/repository" "hyapp-admin-server/internal/response" "hyapp-admin-server/internal/service" @@ -20,6 +21,10 @@ type AppAccessStore interface { AppAccessForUser(userID uint) (repository.AppAccess, error) } +type AuthorizationStore interface { + CurrentAuthorizationForUser(userID uint) (repository.UserAuthorization, error) +} + const ( ContextUserID = "userID" ContextUsername = "username" @@ -38,8 +43,8 @@ func CORS(cfg config.Config) gin.HandlerFunc { c.Header("Access-Control-Allow-Origin", origin) c.Header("Vary", "Origin") c.Header("Access-Control-Allow-Credentials", "true") - c.Header("Access-Control-Allow-Headers", "Authorization, Content-Type, X-Request-ID, "+appctx.HeaderAppCode) - c.Header("Access-Control-Expose-Headers", "X-Request-ID") + c.Header("Access-Control-Allow-Headers", "Authorization, Content-Type, X-Request-ID, "+appctx.HeaderAppCode+", X-CSRF-Token") + c.Header("Access-Control-Expose-Headers", "X-Request-ID, X-CSRF-Token") c.Header("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS") } @@ -61,7 +66,7 @@ func AppCode() gin.HandlerFunc { } } -func AuthRequired(auth *service.AuthService) gin.HandlerFunc { +func AuthRequired(auth *service.AuthService, store AuthorizationStore) gin.HandlerFunc { return func(c *gin.Context) { header := c.GetHeader("Authorization") if !strings.HasPrefix(header, "Bearer ") { @@ -70,6 +75,13 @@ func AuthRequired(auth *service.AuthService) gin.HandlerFunc { return } + if auth == nil || store == nil { + // Authorization cannot safely fall back to claims.Permissions: doing so + // would restore removed privileges until the access token expires. + response.ServerError(c, "认证权限服务不可用") + c.Abort() + return + } claims, err := auth.ParseAccessToken(strings.TrimPrefix(header, "Bearer ")) if err != nil { response.Unauthorized(c, "访问凭证已失效") @@ -77,9 +89,27 @@ func AuthRequired(auth *service.AuthService) gin.HandlerFunc { return } + authorization, err := store.CurrentAuthorizationForUser(claims.UserID) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + response.Unauthorized(c, "用户不存在") + } else { + // Database errors fail closed. A stale JWT permission snapshot is not + // an acceptable availability fallback for privileged admin actions. + response.ServerError(c, "校验登录权限失败") + } + c.Abort() + return + } + if authorization.Status != model.UserStatusActive { + response.Unauthorized(c, "账号不可登录") + c.Abort() + return + } + c.Set(ContextUserID, claims.UserID) - c.Set(ContextUsername, claims.Username) - c.Set(ContextPermissions, claims.Permissions) + c.Set(ContextUsername, authorization.Username) + c.Set(ContextPermissions, authorization.Permissions) c.Next() } } @@ -154,8 +184,9 @@ func HasAnyPermission(c *gin.Context, codes ...string) bool { return false } -// HasPermission reads only the JWT-derived permission list. Database state is -// refreshed by login/refresh, so every request uses one consistent permission snapshot. +// HasPermission reads the request-scoped permission list resolved by +// AuthRequired from current database state. JWT permission claims are retained +// for wire compatibility only and are never trusted for server authorization. func HasPermission(c *gin.Context, code string) bool { return slices.Contains(CurrentPermissions(c), code) } diff --git a/server/admin/internal/migration/migration.go b/server/admin/internal/migration/migration.go index d63a562b..3317b8ba 100644 --- a/server/admin/internal/migration/migration.go +++ b/server/admin/internal/migration/migration.go @@ -148,9 +148,16 @@ func applyFile(ctx context.Context, db *sql.DB, version string, file string) err return err } sum := checksum(body) + // 迁移文件会用 MySQL 会话变量在多条语句之间传递 DDL 决策。database/sql 不保证连续 Exec + // 复用同一底层连接,因此整个文件必须绑定 *sql.Conn,否则 @ddl/@checkpoint 可能在 PREPARE 前丢失。 + conn, err := db.Conn(ctx) + if err != nil { + return err + } + defer conn.Close() var existing migrationRow - err = db.QueryRowContext(ctx, "SELECT version, checksum, dirty FROM schema_migrations WHERE version = ?", version).Scan(&existing.Version, &existing.Checksum, &existing.Dirty) + err = conn.QueryRowContext(ctx, "SELECT version, checksum, dirty FROM schema_migrations WHERE version = ?", version).Scan(&existing.Version, &existing.Checksum, &existing.Dirty) if err == nil { if existing.Dirty { return fmt.Errorf("migration %s is dirty; repair it before continuing", version) @@ -164,16 +171,16 @@ func applyFile(ctx context.Context, db *sql.DB, version string, file string) err return err } - if _, err := db.ExecContext(ctx, "INSERT INTO schema_migrations(version, checksum, dirty) VALUES (?, ?, TRUE)", version, sum); err != nil { + if _, err := conn.ExecContext(ctx, "INSERT INTO schema_migrations(version, checksum, dirty) VALUES (?, ?, TRUE)", version, sum); err != nil { return err } for _, statement := range splitSQL(string(body)) { - if _, err := db.ExecContext(ctx, statement); err != nil { + if _, err := conn.ExecContext(ctx, statement); err != nil { return fmt.Errorf("apply migration %s: %w", version, err) } } - if _, err := db.ExecContext(ctx, "UPDATE schema_migrations SET dirty = FALSE, checksum = ?, applied_at_ms = ? WHERE version = ?", sum, time.Now().UTC().UnixMilli(), version); err != nil { + if _, err := conn.ExecContext(ctx, "UPDATE schema_migrations SET dirty = FALSE, checksum = ?, applied_at_ms = ? WHERE version = ?", sum, time.Now().UTC().UnixMilli(), version); err != nil { return err } return nil diff --git a/server/admin/internal/model/models.go b/server/admin/internal/model/models.go index 38c73f63..a8ac7a21 100644 --- a/server/admin/internal/model/models.go +++ b/server/admin/internal/model/models.go @@ -37,8 +37,94 @@ const ( WithdrawalApplicationStatusPending = "pending" WithdrawalApplicationStatusApproved = "approved" WithdrawalApplicationStatusRejected = "rejected" + + WithdrawalOperationsStatusSkipped = "skipped" + WithdrawalOperationsStatusPending = "pending" + WithdrawalOperationsStatusRejecting = "rejecting" + WithdrawalOperationsStatusApproved = "approved" + WithdrawalOperationsStatusRejected = "rejected" + + ExternalAdminStatusActive = "active" + ExternalAdminStatusDisabled = "disabled" ) +// ExternalAdminAccount is intentionally not related to admin_users. External operators +// use an isolated credential lifecycle and can never exchange this row for a main-admin JWT. +type ExternalAdminAccount struct { + ID uint64 `gorm:"primaryKey" json:"id"` + AppCode string `gorm:"size:32;uniqueIndex:uk_external_admin_accounts_app_linked_user;index:idx_external_admin_accounts_app_status_updated,priority:1;not null" json:"appCode"` + LinkedAppUserID int64 `gorm:"column:linked_app_user_id;uniqueIndex:uk_external_admin_accounts_app_linked_user;not null" json:"-"` + Username string `gorm:"size:64;uniqueIndex:uk_external_admin_accounts_username;not null" json:"username"` + PasswordHash string `gorm:"size:255;not null" json:"-"` + PermissionsJSON string `gorm:"column:permissions_json;type:json;not null" json:"-"` + PermissionRevision uint64 `gorm:"column:permission_revision;not null;default:1" json:"permissionRevision"` + Status string `gorm:"size:24;index:idx_external_admin_accounts_app_status_updated,priority:2;not null;default:active" json:"status"` + PasswordChangeRequired bool `gorm:"not null;default:true" json:"passwordChangeRequired"` + FailedLoginCount uint `gorm:"not null;default:0" json:"-"` + LockedUntilMS int64 `gorm:"column:locked_until_ms;not null;default:0" json:"-"` + LastLoginAtMS *int64 `gorm:"column:last_login_at_ms" json:"lastLoginAtMs"` + CreatedByAdminID uint `gorm:"column:created_by_admin_id;index;not null" json:"createdByAdminId"` + CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` + UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli;index:idx_external_admin_accounts_app_status_updated,priority:3" json:"updatedAtMs"` +} + +func (ExternalAdminAccount) TableName() string { return "external_admin_accounts" } + +// ExternalAdminSession stores only hashes of the session and CSRF secrets. The browser +// receives the opaque values, so a read-only database leak cannot be replayed as a session. +type ExternalAdminSession struct { + ID uint64 `gorm:"primaryKey"` + AccountID uint64 `gorm:"column:account_id;index:idx_external_admin_sessions_account_active,priority:1;not null"` + Account ExternalAdminAccount `gorm:"foreignKey:AccountID;references:ID"` + AppCode string `gorm:"size:32;index:idx_external_admin_sessions_app_expiry,priority:1;not null"` + TokenHash string `gorm:"size:64;uniqueIndex:uk_external_admin_sessions_token_hash;not null"` + CSRFTokenHash string `gorm:"column:csrf_token_hash;size:64;not null"` + IP string `gorm:"size:64;not null;default:''"` + UserAgent string `gorm:"size:512;not null;default:''"` + ExpiresAtMS int64 `gorm:"column:expires_at_ms;index:idx_external_admin_sessions_account_active,priority:3;index:idx_external_admin_sessions_app_expiry,priority:2;not null"` + LastSeenAtMS int64 `gorm:"column:last_seen_at_ms;not null"` + RevokedAtMS int64 `gorm:"column:revoked_at_ms;index:idx_external_admin_sessions_account_active,priority:2;not null;default:0"` + RevokeReason string `gorm:"size:64;not null;default:''"` + CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli"` +} + +func (ExternalAdminSession) TableName() string { return "external_admin_sessions" } + +type ExternalAdminLoginLog struct { + ID uint64 `gorm:"primaryKey"` + AccountID *uint64 `gorm:"column:account_id;index:idx_external_admin_login_logs_account_time,priority:1"` + AppCode string `gorm:"size:32;index:idx_external_admin_login_logs_app_username_time,priority:1;not null"` + Username string `gorm:"size:64;index:idx_external_admin_login_logs_app_username_time,priority:2;not null"` + IP string `gorm:"size:64;not null;default:''"` + UserAgent string `gorm:"size:512;not null;default:''"` + Status string `gorm:"size:24;index:idx_external_admin_login_logs_status_time,priority:1;not null"` + Message string `gorm:"size:128;not null;default:''"` + CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli;index:idx_external_admin_login_logs_app_username_time,priority:3;index:idx_external_admin_login_logs_account_time,priority:2;index:idx_external_admin_login_logs_status_time,priority:2"` +} + +func (ExternalAdminLoginLog) TableName() string { return "external_admin_login_logs" } + +type ExternalAdminOperationLog struct { + ID uint64 `gorm:"primaryKey"` + AccountID uint64 `gorm:"column:account_id;index:idx_external_admin_operation_logs_account_time,priority:1;not null"` + AppCode string `gorm:"size:32;index:idx_external_admin_operation_logs_app_time,priority:1;not null"` + Username string `gorm:"size:64;not null"` + RequestID string `gorm:"size:64;index:idx_external_admin_operation_logs_request;not null;default:''"` + Action string `gorm:"size:160;not null"` + Resource string `gorm:"size:120;not null;default:''"` + ResourceID string `gorm:"size:128;not null;default:''"` + Method string `gorm:"size:12;not null"` + Path string `gorm:"size:255;not null"` + IP string `gorm:"size:64;not null;default:''"` + UserAgent string `gorm:"size:512;not null;default:''"` + Status string `gorm:"size:24;not null"` + HTTPStatus int `gorm:"not null"` + LatencyMS int64 `gorm:"not null;default:0"` + CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli;index:idx_external_admin_operation_logs_account_time,priority:2;index:idx_external_admin_operation_logs_app_time,priority:2"` +} + +func (ExternalAdminOperationLog) TableName() string { return "external_admin_operation_logs" } + type User struct { ID uint `gorm:"primaryKey" json:"id"` Username string `gorm:"size:64;uniqueIndex;not null" json:"account"` @@ -640,31 +726,38 @@ func (order CoinSellerRechargeOrder) BusinessTimeMS() int64 { } type UserWithdrawalApplication struct { - ID uint `gorm:"primaryKey" json:"id"` - AppCode string `gorm:"size:32;index:idx_admin_withdrawal_app_status_time;not null" json:"appCode"` - UserID string `gorm:"size:64;index:idx_admin_withdrawal_user;not null" json:"userId"` - SalaryAssetType string `gorm:"size:64;not null;default:''" json:"salaryAssetType"` - WithdrawAmount string `gorm:"type:decimal(18,2);not null;default:0.00" json:"withdrawAmount"` - WithdrawAmountMinor int64 `gorm:"not null;default:0" json:"withdrawAmountMinor"` - PointFeeAmount int64 `gorm:"not null;default:0" json:"pointFeeAmount"` - PointNetAmount int64 `gorm:"not null;default:0" json:"pointNetAmount"` - PointsPerUSD int64 `gorm:"not null;default:100000" json:"pointsPerUsd"` - PointFeeBPS int32 `gorm:"not null;default:500" json:"pointFeeBps"` - PointPolicyInstance string `gorm:"column:point_policy_instance_code;size:96;not null;default:''" json:"pointPolicyInstanceCode"` - WithdrawMethod string `gorm:"size:64;index:idx_admin_withdrawal_method;not null;default:''" json:"withdrawMethod"` - WithdrawAddress string `gorm:"size:255;not null;default:''" json:"withdrawAddress"` - FreezeCommandID string `gorm:"size:128;not null;default:''" json:"freezeCommandId"` - FreezeTransactionID string `gorm:"size:128;not null;default:''" json:"freezeTransactionId"` - AuditCommandID string `gorm:"size:128;not null;default:''" json:"auditCommandId"` - AuditTransactionID string `gorm:"size:128;not null;default:''" json:"auditTransactionId"` - Status string `gorm:"size:32;index:idx_admin_withdrawal_app_status_time;not null;default:pending" json:"status"` - ApproverUserID *uint `gorm:"index:idx_admin_withdrawal_approver" json:"approverUserId"` - ApproverName string `gorm:"size:64;not null;default:''" json:"approverName"` - AuditRemark string `gorm:"type:text" json:"auditRemark"` - AuditImageURL string `gorm:"column:audit_image_url;size:1024;not null;default:''" json:"auditImageUrl"` - ApprovedAtMS *int64 `gorm:"column:approved_at_ms" json:"approvedAtMs"` - CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli;index:idx_admin_withdrawal_app_status_time" json:"createdAtMs"` - UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` + ID uint `gorm:"primaryKey;index:idx_admin_withdrawal_app_operations_status_time,priority:4" json:"id"` + AppCode string `gorm:"size:32;index:idx_admin_withdrawal_app_status_time;index:idx_admin_withdrawal_app_operations_status_time,priority:1;not null" json:"appCode"` + UserID string `gorm:"size:64;index:idx_admin_withdrawal_user;not null" json:"userId"` + SalaryAssetType string `gorm:"size:64;not null;default:''" json:"salaryAssetType"` + WithdrawAmount string `gorm:"type:decimal(18,2);not null;default:0.00" json:"withdrawAmount"` + WithdrawAmountMinor int64 `gorm:"not null;default:0" json:"withdrawAmountMinor"` + PointFeeAmount int64 `gorm:"not null;default:0" json:"pointFeeAmount"` + PointNetAmount int64 `gorm:"not null;default:0" json:"pointNetAmount"` + PointsPerUSD int64 `gorm:"not null;default:100000" json:"pointsPerUsd"` + PointFeeBPS int32 `gorm:"not null;default:500" json:"pointFeeBps"` + PointPolicyInstance string `gorm:"column:point_policy_instance_code;size:96;not null;default:''" json:"pointPolicyInstanceCode"` + WithdrawMethod string `gorm:"size:64;index:idx_admin_withdrawal_method;not null;default:''" json:"withdrawMethod"` + WithdrawAddress string `gorm:"size:255;not null;default:''" json:"withdrawAddress"` + FreezeCommandID string `gorm:"size:128;not null;default:''" json:"freezeCommandId"` + FreezeTransactionID string `gorm:"size:128;not null;default:''" json:"freezeTransactionId"` + AuditCommandID string `gorm:"size:128;not null;default:''" json:"auditCommandId"` + AuditTransactionID string `gorm:"size:128;not null;default:''" json:"auditTransactionId"` + Status string `gorm:"size:32;index:idx_admin_withdrawal_app_status_time;not null;default:pending" json:"status"` + ApproverUserID *uint `gorm:"index:idx_admin_withdrawal_approver" json:"approverUserId"` + ApproverName string `gorm:"size:64;not null;default:''" json:"approverName"` + AuditRemark string `gorm:"type:text" json:"auditRemark"` + AuditImageURL string `gorm:"column:audit_image_url;size:1024;not null;default:''" json:"auditImageUrl"` + ApprovedAtMS *int64 `gorm:"column:approved_at_ms" json:"approvedAtMs"` + OperationsStatus string `gorm:"column:operations_status;size:32;not null;default:pending;index:idx_admin_withdrawal_app_operations_status_time,priority:2" json:"operationsStatus"` + OperationsReviewerUserID *uint `gorm:"column:operations_reviewer_user_id" json:"operationsReviewerUserId"` + OperationsReviewerName string `gorm:"column:operations_reviewer_name;size:64;not null;default:''" json:"operationsReviewerName"` + OperationsAuditRemark string `gorm:"column:operations_audit_remark;type:text" json:"operationsAuditRemark"` + OperationsAuditCommandID string `gorm:"column:operations_audit_command_id;size:128;not null;default:''" json:"operationsAuditCommandId"` + OperationsAuditTransactionID string `gorm:"column:operations_audit_transaction_id;size:128;not null;default:''" json:"operationsAuditTransactionId"` + OperationsReviewedAtMS *int64 `gorm:"column:operations_reviewed_at_ms" json:"operationsReviewedAtMs"` + CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli;index:idx_admin_withdrawal_app_status_time;index:idx_admin_withdrawal_app_operations_status_time,priority:3" json:"createdAtMs"` + UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (UserWithdrawalApplication) TableName() string { diff --git a/server/admin/internal/modules/dashboard/aslan_mongo_dashboard.go b/server/admin/internal/modules/dashboard/aslan_mongo_dashboard.go index 56a83e93..97da66bb 100644 --- a/server/admin/internal/modules/dashboard/aslan_mongo_dashboard.go +++ b/server/admin/internal/modules/dashboard/aslan_mongo_dashboard.go @@ -27,8 +27,8 @@ const ( aslanMongoGoldWaterCollection = "user_gold_running_water_v2" aslanMongoChunkSize = 800 - // likei GoldOrigin 枚举以 code 形式落在 user_gold_running_water_v2.origin; - // 历史上部分 code 带数字后缀(如 HOT_GAME_200),所以统一用前缀匹配。 + // 幸运礼物返奖和币商出货各自拥有稳定、单一语义的 origin 前缀,因此这两类可按前缀聚合; + // 游戏命名空间混有排行榜/活动奖励,游戏流水必须走下方 exact code 白名单,不能复用此前缀策略。 aslanMongoLuckyGiftPayoutOriginPrefix = "LUCKY_GIFT_GOLD_REWARD" aslanMongoSellerAgentOriginPrefix = "SELLER_AGENT" ) @@ -36,6 +36,41 @@ const ( var ( aslanMongoFreightCommodityTypes = bson.A{"FREIGHT_GOLD", "FREIGHT_GOLD_SUPER"} aslanMongoFreightCommodityFields = []string{"trackCommodityType", "products.code", "products.name", "products.content"} + + // 游戏流水只能消费 likei 已确认的具体 GoldOrigin code,不能用 *_GAME_% 前缀兜底: + // 同一命名空间里已经存在 HOT_GAME_200 排行榜奖励和 BAISHUN_GAME_1085 活动奖励, + // 前缀匹配会把平台发奖误算成游戏返奖。新增游戏必须先在 likei 的游戏配置中确认业务语义, + // 再显式追加到这里,确保 Databi 历史口径不会随着第三方传入任意 gameUid 静默漂移。 + aslanLegacyGameEventTypes = []string{ + "HOT_GAME_201", "HOT_GAME_202", "HOT_GAME_203", "HOT_GAME_204", + "HOT_GAME_205", "HOT_GAME_206", "HOT_GAME_207", "HOT_GAME_208", + "HOT_GAME_209", "HOT_GAME_210", "HOT_GAME_211", "HOT_GAME_212", + "HOT_GAME_213", "HOT_GAME_214", "HOT_GAME_215", "HOT_GAME_220", + "HKYS_GAME_101", "HKYS_GAME_102", "HKYS_GAME_103", "HKYS_GAME_104", + "HKYS_GAME_105", "HKYS_GAME_106", "HKYS_GAME_107", "HKYS_GAME_108", + "HKYS_GAME_109", "HKYS_GAME_110", "HKYS_GAME_111", "HKYS_GAME_112", + "HKYS_GAME_113", "HKYS_GAME_114", "HKYS_GAME_115", "HKYS_GAME_116", + "HKYS_GAME_201", "HKYS_GAME_202", "HKYS_GAME_203", "HKYS_GAME_204", + "HKYS_GAME_205", "HKYS_GAME_206", "HKYS_GAME_207", "HKYS_GAME_208", + "HKYS_GAME_209", "HKYS_GAME_210", "HKYS_GAME_211", "HKYS_GAME_212", + "HKYS_GAME_213", "HKYS_GAME_214", "HKYS_GAME_215", "HKYS_GAME_216", + "BAISHUN_GAME_1001", "BAISHUN_GAME_1004", "BAISHUN_GAME_1005", "BAISHUN_GAME_1006", + "BAISHUN_GAME_1007", "BAISHUN_GAME_1008", "BAISHUN_GAME_1009", "BAISHUN_GAME_1010", + "BAISHUN_GAME_1012", "BAISHUN_GAME_1013", "BAISHUN_GAME_1014", "BAISHUN_GAME_1015", + "BAISHUN_GAME_1016", "BAISHUN_GAME_1017", "BAISHUN_GAME_1018", "BAISHUN_GAME_1019", + "BAISHUN_GAME_1020", "BAISHUN_GAME_1021", "BAISHUN_GAME_1022", "BAISHUN_GAME_1023", + "BAISHUN_GAME_1024", "BAISHUN_GAME_1026", "BAISHUN_GAME_1031", "BAISHUN_GAME_1032", + "BAISHUN_GAME_1035", "BAISHUN_GAME_1037", "BAISHUN_GAME_1040", "BAISHUN_GAME_1041", + "BAISHUN_GAME_1043", "BAISHUN_GAME_1044", "BAISHUN_GAME_1048", "BAISHUN_GAME_1051", + "BAISHUN_GAME_1053", "BAISHUN_GAME_1055", "BAISHUN_GAME_1068", "BAISHUN_GAME_1069", + "BAISHUN_GAME_1075", "BAISHUN_GAME_1078", "BAISHUN_GAME_1083", "BAISHUN_GAME_1084", + "BAISHUN_GAME_1090", "BAISHUN_GAME_1100", "BAISHUN_GAME_1107", "BAISHUN_GAME_1114", + "BAISHUN_GAME_1130", "BAISHUN_GAME_1172", "BAISHUN_GAME_1182", + // Yomi 的 gameUid 由第三方动态下发,代码仓库没有静态枚举;以下 8 个值来自 ATYOU + // wallet_gold_count 近 30 天已出现且经游戏回调链路确认的集合,未知 gameUid 默认不纳入口径。 + "YOMI_GAME_274", "YOMI_GAME_275", "YOMI_GAME_276", "YOMI_GAME_277", + "YOMI_GAME_278", "YOMI_GAME_279", "YOMI_GAME_281", "YOMI_GAME_282", + } ) type AslanMongoDashboardSource struct { @@ -145,6 +180,12 @@ func (s *AslanMongoDashboardSource) AppCode() string { return s.appCode } +func (s *AslanMongoDashboardSource) legacyGameTotalsAvailable(countryFilter externalDashboardCountryFilter) bool { + // wallet_gold_count 只有 App×日×事件类型,没有用户或国家键;区域筛选必须显式关闭该口径, + // 否则区域卡片会混入全 App 游戏流水,数值虽非零却属于错误的数据权限和统计语义。 + return s.legacyDB != nil && strings.TrimSpace(s.legacyWalletDatabase) != "" && !countryFilter.Applied +} + func (s *AslanMongoDashboardSource) StatisticsOverview(ctx context.Context, query StatisticsQuery) (map[string]any, error) { if s == nil || s.db == nil { return nil, fmt.Errorf("aslan mongo dashboard source is not configured") @@ -200,12 +241,14 @@ func (s *AslanMongoDashboardSource) StatisticsOverview(ctx context.Context, quer response["country_breakdown"] = current.CountryBreakdown response["daily_country_breakdown"] = current.DailyCountryBreakdown goldWater := s.hasGoldWater(ctx) + legacyGameTotals := s.legacyGameTotalsAvailable(countryFilter) response["retention"] = current.Total.retentionMap() - response["report_metric_sources"] = aslanMongoDashboardMetricSources(goldWater, s.legacyDB != nil) + response["report_metric_sources"] = aslanMongoDashboardMetricSources(goldWater, s.legacyDB != nil, legacyGameTotals, countryFilter.Applied) response["updated_at_ms"] = time.Now().UTC().UnixMilli() applyExternalDashboardDeltas(response, current.Total, previous.Total) response["salary_delta_rate"] = deltaRate(nullableMetricInt64(current.Total.SalaryUSDMinor), nullableMetricInt64(previous.Total.SalaryUSDMinor)) applyAslanMongoUnavailableFields(response) + applyAslanMongoGlobalGameOverview(response, current.Total, previous.Total, legacyGameTotals) applyAslanMongoLegacyUnavailableFields(response, s.legacyDB != nil) if !goldWater { applyAslanMongoGoldWaterUnavailable(response) @@ -296,6 +339,13 @@ type legacyMongoCoinFlow struct { OutputCoin int64 } +// legacyMongoGameFlow 是 wallet_gold_count 已预聚合的全 App 游戏日快照。 +// 该表没有 user_id/国家维度,因此它只能进入总览与每日趋势,绝不能回填到国家或区域行。 +type legacyMongoGameFlow struct { + Turnover int64 + Payout int64 +} + func (m *legacyMongoMetric) toExternal(coinFlow *legacyMongoCoinFlow) externalDashboardMetric { userRecharge := m.RechargeUSDMinor - m.CoinSellerRechargeUSDMinor metric := externalDashboardMetric{ @@ -332,11 +382,24 @@ func (m *legacyMongoMetric) toExternal(coinFlow *legacyMongoCoinFlow) externalDa return metric } +func (m *legacyMongoMetric) toExternalWithGlobalFlows(coinFlow *legacyMongoCoinFlow, gameFlow *legacyMongoGameFlow) externalDashboardMetric { + metric := m.toExternal(coinFlow) + if gameFlow == nil { + return metric + } + metric.GameTurnover = gameFlow.Turnover + metric.GamePayout = gameFlow.Payout + // 游戏利润和利润率属于投注/返奖的派生口径;在同一个 finalize 入口重算,避免总览与 Databi 二次汇总出现公式分叉。 + metric.finalize() + return metric +} + type legacyMongoGrid struct { days []string daySet map[string]struct{} metrics map[string]map[string]*legacyMongoMetric coinFlows map[string]*legacyMongoCoinFlow + gameFlows map[string]*legacyMongoGameFlow rechargeUsers map[string]map[string]struct{} // 各 loader 并行写入:map 结构由锁保护;不同 loader 写 metric 的不同字段,无字段级竞争。 mu sync.Mutex @@ -347,6 +410,7 @@ func newLegacyMongoGrid(startDate time.Time, endDate time.Time) *legacyMongoGrid daySet: map[string]struct{}{}, metrics: map[string]map[string]*legacyMongoMetric{}, coinFlows: map[string]*legacyMongoCoinFlow{}, + gameFlows: map[string]*legacyMongoGameFlow{}, rechargeUsers: map[string]map[string]struct{}{}, } for day := startDate; day.Before(endDate); day = day.AddDate(0, 0, 1) { @@ -432,6 +496,12 @@ func (s *AslanMongoDashboardSource) loadRange(ctx context.Context, startDate tim func() error { return s.loadCoinFlows(ctx, startDate, endDate, grid) }, ) } + legacyGameTotals := s.legacyGameTotalsAvailable(countryFilter) + if legacyGameTotals { + // wallet_gold_count 已由 likei wallet-service 按日聚合,区间查询只扫描唯一键范围内的小量日快照; + // 这里不回查账变明细,避免 Databi 请求把在线钱包库变成临时报表引擎。 + tasks = append(tasks, func() error { return s.loadLegacyGameFlows(ctx, startDate, endDate, grid) }) + } if includeRetention { tasks = append(tasks, func() error { return s.applyRetention(ctx, startDate, countryFilter, cohorts, grid) }) } @@ -445,14 +515,15 @@ func (s *AslanMongoDashboardSource) loadRange(ctx context.Context, startDate tim } } - return s.assembleRange(grid, countryFilter, goldWater, s.legacyDB != nil), nil + return s.assembleRange(grid, countryFilter, goldWater, s.legacyDB != nil, legacyGameTotals), nil } -func (s *AslanMongoDashboardSource) assembleRange(grid *legacyMongoGrid, countryFilter externalDashboardCountryFilter, goldWater bool, legacyRecharge bool) aslanRangeOverview { +func (s *AslanMongoDashboardSource) assembleRange(grid *legacyMongoGrid, countryFilter externalDashboardCountryFilter, goldWater bool, legacyRecharge bool, legacyGameTotals bool) aslanRangeOverview { dailySeries := []map[string]any{} dailyCountries := []map[string]any{} totalFlow := legacyMongoMetric{} totalCoinFlow := legacyMongoCoinFlow{} + totalGameFlow := legacyMongoGameFlow{} countryTotals := map[string]*legacyMongoMetric{} for _, day := range grid.days { @@ -497,6 +568,11 @@ func (s *AslanMongoDashboardSource) assembleRange(grid *legacyMongoGrid, country totalCoinFlow.ConsumedCoin += coinFlow.ConsumedCoin totalCoinFlow.OutputCoin += coinFlow.OutputCoin } + gameFlow := grid.gameFlows[day] + if gameFlow != nil { + totalGameFlow.Turnover += gameFlow.Turnover + totalGameFlow.Payout += gameFlow.Payout + } // 工资余额是快照:日行取当日各国快照之和,区间合计不能跨天累加。 daySalary := dayFlow.SalaryUSDMinor if dayRechargeUsers := grid.rechargeUsers[day]; len(dayRechargeUsers) > 0 { @@ -506,10 +582,11 @@ func (s *AslanMongoDashboardSource) assembleRange(grid *legacyMongoGrid, country totalFlow.add(&dayFlow) totalFlow.SalaryUSDMinor = daySalary - dayRow := dayFlow.toExternal(coinFlow).toMap() + dayRow := dayFlow.toExternalWithGlobalFlows(coinFlow, gameFlow).toMap() dayRow["label"] = day dayRow["stat_day"] = day applyAslanMongoUnavailableFields(dayRow) + applyAslanMongoGlobalGameFields(dayRow, gameFlow, legacyGameTotals) applyAslanMongoLegacyUnavailableFields(dayRow, legacyRecharge) if !goldWater { applyAslanMongoGoldWaterUnavailable(dayRow) @@ -548,8 +625,13 @@ func (s *AslanMongoDashboardSource) assembleRange(grid *legacyMongoGrid, country return left > right }) + var gameTotal *legacyMongoGameFlow + if legacyGameTotals { + // 可用口径即使区间内没有流水也应返回真实 0;nil 只表示数据源或筛选维度不支持。 + gameTotal = &totalGameFlow + } return aslanRangeOverview{ - Total: totalFlow.toExternal(&totalCoinFlow), + Total: totalFlow.toExternalWithGlobalFlows(&totalCoinFlow, gameTotal), DailySeries: dailySeries, CountryBreakdown: countryRows, DailyCountryBreakdown: dailyCountries, @@ -632,6 +714,71 @@ func (s *AslanMongoDashboardSource) loadActiveCounts(ctx context.Context, startD return nil } +// loadLegacyGameFlows 读取 likei wallet-service 已持久化的 App×日×事件累计快照。 +// group_num 的日界线由 likei 固定按 Asia/Riyadh 生成;这里按 [start,end) 的日期号查询并原样映射, +// 不使用 MySQL session 时区做二次转换,避免同一自然日被移到相邻日期。 +func (s *AslanMongoDashboardSource) loadLegacyGameFlows(ctx context.Context, startDate time.Time, endDate time.Time, grid *legacyMongoGrid) error { + if s.legacyDB == nil || strings.TrimSpace(s.legacyWalletDatabase) == "" || len(aslanLegacyGameEventTypes) == 0 { + return nil + } + + // likei 新迁移的唯一键为 (sys_origin, group_num, type, event_type);固定 App、日期范围和 type 后 + // 只扫描目标日快照。event_type 使用 exact IN 白名单收口业务语义,不能改成 LIKE '*_GAME_%', + // 否则 HOT_GAME_200、BAISHUN_GAME_1085 等奖励 code 会被误计。 + placeholders := strings.TrimSuffix(strings.Repeat("?,", len(aslanLegacyGameEventTypes)), ",") + query := fmt.Sprintf(`SELECT group_num, type, COALESCE(SUM(amount), 0) +FROM %s.wallet_gold_count +WHERE sys_origin = ? + AND group_num >= ? + AND group_num < ? + AND type IN (0, 1) + AND event_type IN (%s) +GROUP BY group_num, type`, quoteMySQLIdentifier(s.legacyWalletDatabase), placeholders) + args := make([]any, 0, len(aslanLegacyGameEventTypes)+3) + args = append(args, s.sysOrigin, dashboardDateNumber(startDate), dashboardDateNumber(endDate)) + for _, eventType := range aslanLegacyGameEventTypes { + args = append(args, eventType) + } + + queryCtx, cancel := context.WithTimeout(ctx, s.requestTimeout) + defer cancel() + rows, err := s.legacyDB.QueryContext(queryCtx, query, args...) + if err != nil { + return fmt.Errorf("query legacy game day snapshots: %w", err) + } + defer rows.Close() + for rows.Next() { + var groupNum string + var receiptType int + var pennyAmount int64 + if err := rows.Scan(&groupNum, &receiptType, &pennyAmount); err != nil { + return fmt.Errorf("scan legacy game day snapshot: %w", err) + } + day, ok := dashboardDayFromNumber(groupNum) + if !ok || !grid.hasDay(day) { + continue + } + flow := grid.gameFlows[day] + if flow == nil { + flow = &legacyMongoGameFlow{} + grid.gameFlows[day] = flow + } + // GoldReceiptCmd 以 PennyAmount 写入统计缓存,wallet_gold_count.amount 因此是 1/100 金币; + // 先在数据库按日汇总再统一四舍五入,避免逐 event_type 除法造成累计舍入误差。 + amount := roundMinorToWhole(pennyAmount) + switch receiptType { + case 1: + flow.Turnover += amount + case 0: + flow.Payout += amount + } + } + if err := rows.Err(); err != nil { + return fmt.Errorf("iterate legacy game day snapshots: %w", err) + } + return nil +} + type aslanMongoDayCountryUsers struct { day string country string @@ -1306,7 +1453,7 @@ func (s *AslanMongoDashboardSource) loadCoinFlows(ctx context.Context, startDate // applyRetention 按“观察日回看”口径用注册 cohort × user_daily_active_log 推 D1/D7/D30: // 区间内每一天 D 的 DN 留存 = D-N 天注册的用户中 D 当天活跃的比例,计数归属观察日 D -//(与 Yumi 的 CDC 预聚合、statistics-service 口径一致)。cohort 日无注册时基数保持 0, +// (与 Yumi 的 CDC 预聚合、statistics-service 口径一致)。cohort 日无注册时基数保持 0, // 上层会把 0 基数转成 nil,避免把“无 cohort”展示成真实 0% 留存。 func (s *AslanMongoDashboardSource) applyRetention(ctx context.Context, startDate time.Time, countryFilter externalDashboardCountryFilter, cohorts map[string]map[string][]int64, grid *legacyMongoGrid) error { location, err := time.LoadLocation(s.statTimezone) @@ -1597,6 +1744,19 @@ func dashboardDateNumber(day time.Time) string { return day.Format("20060102") } +func dashboardDayFromNumber(value string) (string, bool) { + value = strings.TrimSpace(value) + if len(value) != 8 { + return "", false + } + // Parse 不只校验字符长度,还会拒绝 20260231 这类脏 group_num;输出固定 ISO 日期供 grid 精确匹配。 + day, err := time.Parse("20060102", value) + if err != nil { + return "", false + } + return day.Format("2006-01-02"), true +} + // aslanMongoDocument 把聚合结果里的嵌套文档统一转成 bson.M; // driver 默认把嵌套文档解码成 bson.D,直接断言 bson.M 会静默丢行(表现为全零无报错)。 func aslanMongoDocument(value any) bson.M { @@ -1763,8 +1923,9 @@ func aslanMongoInt64Chunks(values []int64, size int) [][]int64 { return out } -// aslanMongoUnavailableMetricFields 是 likei Mongo 事实集合仍给不出的口径; -// 游戏流水的 GoldOrigin code 枚举过杂(大量带后缀的游戏 code 与奖励类混在一起),未确认前不硬凑。 +// aslanMongoUnavailableMetricFields 是 likei Mongo 事实集合仍给不出的口径。 +// 游戏总量先置空,再由 applyAslanMongoGlobalGameFields 仅在“全 App + legacy 日快照可用”时恢复; +// 这样国家/区域行沿用同一序列化路径也不会意外泄漏全局游戏数据。 var aslanMongoUnavailableMetricFields = []string{ "coin_seller_stock_coin", "new_dealer_recharge_usd_minor", @@ -1797,6 +1958,33 @@ func applyAslanMongoUnavailableFields(row map[string]any) { } } +func applyAslanMongoGlobalGameFields(row map[string]any, flow *legacyMongoGameFlow, available bool) { + if !available { + return + } + if flow == nil { + flow = &legacyMongoGameFlow{} + } + profit := flow.Turnover - flow.Payout + row["game_turnover"] = flow.Turnover + row["game_payout"] = flow.Payout + row["game_profit"] = profit + row["game_profit_rate"] = ratioFloat64(profit, flow.Turnover) + // wallet_gold_count 没有 user_id,game_players 必须继续保持 nil,不能用事件类型数量冒充玩家数。 +} + +func applyAslanMongoGlobalGameOverview(row map[string]any, current externalDashboardMetric, previous externalDashboardMetric, available bool) { + if !available { + return + } + applyAslanMongoGlobalGameFields(row, &legacyMongoGameFlow{Turnover: current.GameTurnover, Payout: current.GamePayout}, true) + // 环比基于同一个 Riyadh 日快照口径计算;上一周期真实为 0 时 deltaRate 按公共规则返回 nil, + // 不伪造无穷增长率。 + row["game_turnover_delta_rate"] = deltaRate(current.GameTurnover, previous.GameTurnover) + row["game_payout_delta_rate"] = deltaRate(current.GamePayout, previous.GamePayout) + row["game_profit_delta_rate"] = deltaRate(current.GameProfit, previous.GameProfit) +} + var aslanMongoLegacyMetricFields = []string{ "coin_seller_recharge_usd_minor", } @@ -1830,7 +2018,7 @@ func applyAslanMongoGoldWaterUnavailable(row map[string]any) { } } -func aslanMongoDashboardMetricSources(goldWater bool, legacyRecharge bool) []map[string]any { +func aslanMongoDashboardMetricSources(goldWater bool, legacyRecharge bool, legacyGameTotals bool, countryFiltered bool) []map[string]any { goldWaterSources := []map[string]any{ {"field": "lucky_gift_payout", "available": true, "source": "likei Mongo user_gold_running_water_v2 origin=LUCKY_GIFT_GOLD_REWARD*"}, {"field": "coin_seller_transfer_coin", "available": true, "source": "likei Mongo user_gold_running_water_v2 origin=SELLER_AGENT*"}, @@ -1864,6 +2052,29 @@ func aslanMongoDashboardMetricSources(goldWater bool, legacyRecharge bool) []map mifaPaySource += " + legacy MySQL order_other_recharge amount" newUserRechargeSource += "/legacy 其他充值/legacy 币商充值" } + gameSources := []map[string]any{} + if legacyGameTotals { + gameSource := "likei legacy MySQL atyou_wallet.wallet_gold_count(Asia/Riyadh 日口径;exact game event_type 白名单;type=1 投注、type=0 返奖)" + gameSources = []map[string]any{ + {"field": "game_turnover", "available": true, "source": gameSource}, + {"field": "game_payout", "available": true, "source": gameSource}, + {"field": "game_profit", "available": true, "source": "game_turnover - game_payout"}, + {"field": "game_profit_rate", "available": true, "source": "game_profit / game_turnover"}, + {"field": "game_players", "available": false, "missing_reason": "wallet_gold_count 没有 user_id,不能从日金额快照推导游戏人数"}, + } + } else { + reason := "未配置 legacy MySQL 钱包库,无法读取 Aslan 游戏日快照" + if countryFiltered { + reason = "wallet_gold_count 只有全 App 日汇总,区域筛选时不能返回全局游戏值" + } + gameSources = []map[string]any{ + {"field": "game_turnover", "available": false, "missing_reason": reason}, + {"field": "game_payout", "available": false, "missing_reason": reason}, + {"field": "game_profit", "available": false, "missing_reason": reason}, + {"field": "game_profit_rate", "available": false, "missing_reason": reason}, + {"field": "game_players", "available": false, "missing_reason": "wallet_gold_count 没有 user_id,不能从日金额快照推导游戏人数"}, + } + } baseSources := []map[string]any{ {"field": "new_users", "available": true, "source": "likei Mongo user_run_profile createTime/countryCode"}, {"field": "active_users", "available": true, "source": "likei Mongo user_daily_active_log activeDate/registerCountryCode"}, @@ -1876,7 +2087,6 @@ func aslanMongoDashboardMetricSources(goldWater bool, legacyRecharge bool) []map {"field": "gift_coin_spent", "available": true, "source": "likei Mongo gift_give_running_water giftValue.actualAmount(含幸运礼物)"}, {"field": "lucky_gift_turnover", "available": true, "source": "likei Mongo gift_give_running_water luckyGift=true"}, {"field": "coin_seller_stock_coin", "available": false, "missing_reason": "likei Mongo 未确认币商进货金币口径"}, - {"field": "game_turnover", "available": false, "missing_reason": "likei GoldOrigin 游戏 code 枚举过多且与奖励类混排,未确认口径前不聚合"}, {"field": "super_lucky_gift_turnover", "available": false, "missing_reason": "likei 平台没有超级幸运礼物玩法"}, {"field": "coin_total", "available": false, "missing_reason": "likei Mongo 没有可按国家低成本汇总的金币余额快照"}, {"field": "platform_grant_coin", "available": false, "missing_reason": "likei Mongo 未确认平台发放金币来源枚举"}, @@ -1892,5 +2102,6 @@ func aslanMongoDashboardMetricSources(goldWater bool, legacyRecharge bool) []map {"field": "retention.day30_rate", "available": true, "source": "likei Mongo 注册 cohort × user_daily_active_log D+30"}, } out := append(baseSources, legacySources...) + out = append(out, gameSources...) return append(out, goldWaterSources...) } diff --git a/server/admin/internal/modules/dashboard/aslan_mongo_dashboard_test.go b/server/admin/internal/modules/dashboard/aslan_mongo_dashboard_test.go index 16d52b80..4ba17382 100644 --- a/server/admin/internal/modules/dashboard/aslan_mongo_dashboard_test.go +++ b/server/admin/internal/modules/dashboard/aslan_mongo_dashboard_test.go @@ -2,6 +2,7 @@ package dashboard import ( "context" + "database/sql/driver" "testing" "time" @@ -288,6 +289,94 @@ func TestAslanMongoListCoinSellerRechargeBills(t *testing.T) { } } +func TestAslanMongoLegacyGameFlowsUseSelectedDayNumberForRiyadhSnapshots(t *testing.T) { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("sqlmock: %v", err) + } + defer db.Close() + + // Social BI 仍按上海时区选择日期;wallet 游戏快照虽按 Riyadh 切日,但 group_num 是自然日号, + // 查询必须直接使用所选 yyyyMMdd,不能把请求时间点换区后再偏移日期。 + location, err := time.LoadLocation("Asia/Shanghai") + if err != nil { + t.Fatalf("load Shanghai location: %v", err) + } + start := time.Date(2026, 7, 5, 0, 0, 0, 0, location) + end := start.AddDate(0, 0, 1) + grid := newLegacyMongoGrid(start, end) + // 国家行存在时也不能继承全 App 游戏值;它只用于验证 assembleRange 的维度隔离。 + grid.at("2026-07-05", "SA").NewUsers = 1 + source := &AslanMongoDashboardSource{ + legacyDB: db, + legacyWalletDatabase: "atyou_wallet", + sysOrigin: "ATYOU", + requestTimeout: time.Second, + } + + arguments := []driver.Value{"ATYOU", "20260705", "20260706"} + for _, eventType := range aslanLegacyGameEventTypes { + arguments = append(arguments, eventType) + } + mock.ExpectQuery("FROM `atyou_wallet`\\.wallet_gold_count[\\s\\S]*sys_origin = \\?[\\s\\S]*event_type IN"). + WithArgs(arguments...). + WillReturnRows(sqlmock.NewRows([]string{"group_num", "type", "amount"}). + AddRow(20260705, 1, int64(12_345)). + AddRow(20260705, 0, int64(2_345))) + + if err := source.loadLegacyGameFlows(context.Background(), start, end, grid); err != nil { + t.Fatalf("loadLegacyGameFlows: %v", err) + } + flow := grid.gameFlows["2026-07-05"] + if flow == nil || flow.Turnover != 123 || flow.Payout != 23 { + t.Fatalf("legacy game flow mismatch: %+v", flow) + } + + overview := source.assembleRange(grid, externalDashboardCountryFilter{}, false, true, true) + if overview.Total.GameTurnover != 123 || overview.Total.GamePayout != 23 || overview.Total.GameProfit != 100 { + t.Fatalf("legacy game overview mismatch: %+v", overview.Total) + } + assertInt64(t, overview.DailySeries[0]["game_turnover"], 123) + assertInt64(t, overview.DailySeries[0]["game_payout"], 23) + assertInt64(t, overview.DailySeries[0]["game_profit"], 100) + if overview.DailySeries[0]["game_players"] != nil { + t.Fatalf("game players must stay unavailable: %#v", overview.DailySeries[0]) + } + if len(overview.CountryBreakdown) != 1 || overview.CountryBreakdown[0]["game_turnover"] != nil { + t.Fatalf("country rows must not contain global game totals: %#v", overview.CountryBreakdown) + } + + // 即使 grid 中已有全局快照,区域筛选路径传入 unavailable 后也必须继续输出 nil,防止全局值泄漏。 + regionOverview := source.assembleRange(grid, externalDashboardCountryFilter{Applied: true, RegionID: 9}, false, true, false) + if regionOverview.DailySeries[0]["game_turnover"] != nil || regionOverview.Total.GameTurnover != 0 { + t.Fatalf("region overview must not expose global game totals: daily=%#v total=%+v", regionOverview.DailySeries, regionOverview.Total) + } + + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations: %v", err) + } +} + +func TestAslanMongoLegacyGameWhitelistExcludesRewardOrigins(t *testing.T) { + seen := make(map[string]struct{}, len(aslanLegacyGameEventTypes)) + for _, eventType := range aslanLegacyGameEventTypes { + if _, duplicated := seen[eventType]; duplicated { + t.Fatalf("duplicate game event type %s", eventType) + } + seen[eventType] = struct{}{} + } + for _, required := range []string{"HOT_GAME_201", "HKYS_GAME_101", "BAISHUN_GAME_1182", "YOMI_GAME_282"} { + if _, ok := seen[required]; !ok { + t.Fatalf("confirmed game event type %s missing from whitelist", required) + } + } + for _, reward := range []string{"HOT_GAME_200", "BAISHUN_GAME_1085"} { + if _, ok := seen[reward]; ok { + t.Fatalf("reward origin %s must not be counted as game flow", reward) + } + } +} + func TestAslanMongoRechargeMatchExcludesFreightGold(t *testing.T) { match := bson.M{} aslanMongoExcludeFreightGoldRecharge(match) @@ -340,11 +429,16 @@ func TestAslanMongoLegacyRechargeHandlesZeroAndDeductionAmount(t *testing.T) { } func TestAslanMongoCoinSellerRechargeSourceAvailability(t *testing.T) { - available := aslanMongoDashboardMetricSources(false, true) + available := aslanMongoDashboardMetricSources(false, true, true, false) assertMetricSourceAvailable(t, available, "coin_seller_recharge_usd_minor") + assertMetricSourceAvailable(t, available, "game_turnover") - unavailable := aslanMongoDashboardMetricSources(false, false) + unavailable := aslanMongoDashboardMetricSources(false, false, false, false) assertMetricSourceUnavailable(t, unavailable, "coin_seller_recharge_usd_minor") + assertMetricSourceUnavailable(t, unavailable, "game_turnover") + + regionFiltered := aslanMongoDashboardMetricSources(false, true, false, true) + assertMetricSourceUnavailable(t, regionFiltered, "game_turnover") } func TestAslanMongoDailyRechargeUsersDeduplicateAcrossCountries(t *testing.T) { @@ -358,7 +452,7 @@ func TestAslanMongoDailyRechargeUsersDeduplicateAcrossCountries(t *testing.T) { } applyAslanRechargeUserMetrics(nil, grid, distinctUsers, nil) - overview := (&AslanMongoDashboardSource{}).assembleRange(grid, externalDashboardCountryFilter{}, false, true) + overview := (&AslanMongoDashboardSource{}).assembleRange(grid, externalDashboardCountryFilter{}, false, true, false) if overview.Total.PaidUsers != 1 { t.Fatalf("total paid users = %d, want 1", overview.Total.PaidUsers) } @@ -409,11 +503,11 @@ func TestAslanMongoApplyRetentionAttributesToObservationDay(t *testing.T) { "2026-06-11": {"EG": {3}}, } earlier := map[string]map[string][]int64{ - "2026-06-09": {"SA": {10, 11}}, // 观察日 06-10 的 D1 cohort - "2026-06-03": {"SA": {20, 21, 22}}, // 观察日 06-10 的 D7 cohort - "2026-05-11": {"EG": {30}}, // 观察日 06-10 的 D30 cohort - "2026-06-04": {"EG": {40}}, // 观察日 06-11 的 D7 cohort - "2026-06-10": {"SA": {50}}, // 与主 cohorts 同日:合并成 {1,2,50} + "2026-06-09": {"SA": {10, 11}}, // 观察日 06-10 的 D1 cohort + "2026-06-03": {"SA": {20, 21, 22}}, // 观察日 06-10 的 D7 cohort + "2026-05-11": {"EG": {30}}, // 观察日 06-10 的 D30 cohort + "2026-06-04": {"EG": {40}}, // 观察日 06-11 的 D7 cohort + "2026-06-10": {"SA": {50}}, // 与主 cohorts 同日:合并成 {1,2,50} } activeByDay := map[string]map[int64]struct{}{ "2026-06-10": {10: {}, 20: {}, 30: {}}, diff --git a/server/admin/internal/modules/databi/service.go b/server/admin/internal/modules/databi/service.go index 4b33545f..fe91fb4d 100644 --- a/server/admin/internal/modules/databi/service.go +++ b/server/admin/internal/modules/databi/service.go @@ -20,8 +20,9 @@ import ( ) const ( - appKindHyapp = "hyapp" - appKindLegacy = "legacy" + appKindHyapp = "hyapp" + appKindLegacy = "legacy" + unknownCountryName = "未知国家" overviewConcurrency = 4 ) @@ -341,14 +342,18 @@ type RequirementsResult struct { // Overview 服务端并发聚合各 App 的统计总览:hyapp App 走 statistics-service, // legacy App 走 dashboard 外部源;国家行按区域目录卷积出大区行,并按用户数据范围裁剪。 func (s *Service) Overview(ctx context.Context, access repository.MoneyAccess, query OverviewQuery) (*OverviewResult, error) { - apps, err := s.listAllowedApps(ctx, query.AppCodes, access) + registeredApps, err := s.listApps(ctx) if err != nil { return nil, err } + apps := filterAllowedApps(registeredApps, query.AppCodes, access) catalog, err := s.regionCatalog(ctx, apps) if err != nil { return nil, err } + // 国家主数据属于 App 业务域;即使 country_id 是物理全局自增,也必须按当前可查询 App 建目录, + // 否则跨 App 污染会被另一个 App 的主数据包装成合法国家,掩盖上游事实错误。 + countryDirectories := s.countryDirectories(ctx, apps) results := make([]AppOverview, len(apps)) var wg sync.WaitGroup @@ -359,7 +364,7 @@ func (s *Service) Overview(ctx context.Context, access repository.MoneyAccess, q defer wg.Done() semaphore <- struct{}{} defer func() { <-semaphore }() - results[index] = s.appOverview(ctx, app, catalog[app.AppCode], access, query) + results[index] = s.appOverview(ctx, app, catalog[app.AppCode], countryDirectories[app.AppCode], access, query) }(index, app) } wg.Wait() @@ -600,7 +605,7 @@ func supportsAppTrackingFunnel(appCode string) bool { return ok } -func (s *Service) appOverview(ctx context.Context, app AppInfo, regions []RegionInfo, access repository.MoneyAccess, query OverviewQuery) AppOverview { +func (s *Service) appOverview(ctx context.Context, app AppInfo, regions []RegionInfo, countries map[int64]countryDirectoryEntry, access repository.MoneyAccess, query OverviewQuery) AppOverview { out := AppOverview{ AppCode: app.AppCode, AppName: app.AppName, @@ -652,8 +657,10 @@ func (s *Service) appOverview(ctx context.Context, app AppInfo, regions []Region return out } - countryRows := anyRowSlice(overview["country_breakdown"]) - dailyCountryRows := anyRowSlice(overview["daily_country_breakdown"]) + // statisticsOverview 会短时缓存并共享底层 map;补展示字段时必须复制行,避免并发请求互相改写缓存。 + preserveSourceNames := app.Kind == appKindLegacy + countryRows := enrichCountryRows(anyRowSlice(overview["country_breakdown"]), countries, preserveSourceNames) + dailyCountryRows := enrichCountryRows(anyRowSlice(overview["daily_country_breakdown"]), countries, preserveSourceNames) resolve := regionResolver(regions) restricted := !allowAll && query.RegionID == 0 && len(requestRegionIDs) == 0 @@ -1199,6 +1206,12 @@ func (s *Service) listAllowedApps(ctx context.Context, requested []string, acces if err != nil { return nil, err } + return filterAllowedApps(apps, requested, access), nil +} + +// filterAllowedApps 只裁剪可查询的 App,不改变 appregistry 给出的稳定顺序。 +// Overview 会保留裁剪前的注册 App 集合,供全局 country_id 展示目录使用。 +func filterAllowedApps(apps []AppInfo, requested []string, access repository.MoneyAccess) []AppInfo { requestedSet := map[string]struct{}{} for _, appCode := range requested { appCode = appctx.Normalize(appCode) @@ -1221,7 +1234,145 @@ func (s *Service) listAllowedApps(ctx context.Context, requested []string, acces } out = append(out, app) } - return out, nil + return out +} + +type countryDirectoryEntry struct { + AppCode string + ID int64 + Code string + Name string + DisplayName string + Flag string + Enabled bool +} + +// countryDirectories 按 app_code + country_id 汇总当前可查询 HyApp 的国家主数据。 +// country_id 虽是全局自增主键,但国家启停和归属仍受 app_code 隔离;目录不能跨 App 复用。 +func (s *Service) countryDirectories(ctx context.Context, apps []AppInfo) map[string]map[int64]countryDirectoryEntry { + byApp := make(map[string]map[int64]countryDirectoryEntry) + if s.user == nil { + return byApp + } + + // appregistry 当前按名称排序;改按 app_code 查询让下游调用顺序和日志保持稳定。 + hyappApps := make([]AppInfo, 0, len(apps)) + for _, app := range apps { + if app.Kind == appKindHyapp { + hyappApps = append(hyappApps, app) + } + } + sort.Slice(hyappApps, func(i, j int) bool { + return hyappApps[i].AppCode < hyappApps[j].AppCode + }) + + for _, app := range hyappApps { + // user-service 依赖 RequestMeta.app_code 选择 App 数据域;每次调用都必须显式覆盖请求上下文。 + appContext := appctx.WithContext(ctx, app.AppCode) + countries, err := s.user.ListCountries(appContext, userclient.ListCountriesRequest{ + Caller: "admin-server", + // nil 表示同时读取 enabled 与 disabled。已停用国家仍可能存在于历史统计事实中,不能从展示目录丢失。 + Enabled: nil, + }) + if err != nil { + // 国家目录只用于展示;单 App 故障时该 App 降级为未知,不能拖垮整个 Social BI Overview 接口。 + slog.Warn("databi_list_hyapp_countries_failed", "app_code", app.AppCode, "error", err) + continue + } + byID := make(map[int64]countryDirectoryEntry, len(countries)) + mergeCountryDirectory(byID, app.AppCode, countries) + byApp[app.AppCode] = byID + } + return byApp +} + +// mergeCountryDirectory 将一次 App 查询投影为 BI 展示字段;ID=0 是统计未知值,不伪造国家主数据。 +// 同一 App 返回重复 ID 时保留第一项,避免异常目录响应在同一次请求内反复覆盖展示语义。 +func mergeCountryDirectory(byID map[int64]countryDirectoryEntry, appCode string, countries []*userclient.Country) { + for _, country := range countries { + if country == nil || country.CountryID <= 0 { + continue + } + if _, exists := byID[country.CountryID]; exists { + continue + } + byID[country.CountryID] = countryDirectoryEntry{ + AppCode: appctx.Normalize(appCode), + ID: country.CountryID, + Code: strings.TrimSpace(country.CountryCode), + Name: strings.TrimSpace(country.CountryName), + DisplayName: strings.TrimSpace(country.CountryDisplayName), + Flag: strings.TrimSpace(country.Flag), + Enabled: country.Enabled, + } + } +} + +// enrichCountryRows 复制统计行后补展示字段,不能原地修改 statisticsOverview 的共享缓存。 +func enrichCountryRows(rows []map[string]any, countries map[int64]countryDirectoryEntry, preserveSourceNames bool) []map[string]any { + out := make([]map[string]any, 0, len(rows)) + for _, source := range rows { + row := make(map[string]any, len(source)+4) + for key, value := range source { + row[key] = value + } + enrichCountryRow(row, countries, preserveSourceNames) + out = append(out, row) + } + return out +} + +func enrichCountryRow(row map[string]any, countries map[int64]countryDirectoryEntry, preserveSourceNames bool) { + // 外接 legacy 源可能使用 country_name、country 或 country_code 标识国家;任一字段存在时都以源数据为准, + // 避免它携带的本地数字 ID 碰巧等于某个 HyApp 全局 ID 后被错误覆盖。 + if preserveSourceNames { + sourceDisplayName := rowString(row, "country_display_name") + sourceName := rowString(row, "country_name", "country") + sourceCode := rowString(row, "country_code") + if firstNonEmptyString(sourceDisplayName, sourceName, sourceCode) != "" { + row["country_name"] = firstNonEmptyString(sourceDisplayName, sourceName, sourceCode) + setCountryFieldIfEmpty(row, "country_code", "") + // 字段必须存在供前端统一读取,但不把 legacy 的英文名伪装成原始中文 display_name。 + setCountryFieldIfEmpty(row, "country_display_name", "") + setCountryFieldIfEmpty(row, "flag", "") + return + } + // legacy 的数字 ID 由外部数据源定义,不能碰巧命中 HyApp ID 后借用其名称; + // 源没有返回名称/国家码时明确保持未知,等待该源补齐自己的展示契约。 + row["country_name"] = unknownCountryName + setCountryFieldIfEmpty(row, "country_code", "") + setCountryFieldIfEmpty(row, "country_display_name", unknownCountryName) + setCountryFieldIfEmpty(row, "flag", "") + return + } + countryID, hasCountryID := rowInt64(row, "country_id") + country, found := countries[countryID] + if !hasCountryID || countryID <= 0 || !found { + // 0 和目录未命中都属于未知维度;保留原 country_id 便于继续追查事实来源,不伪造 ID 或国家码。 + setCountryFieldIfEmpty(row, "country_code", "") + row["country_name"] = unknownCountryName + setCountryFieldIfEmpty(row, "country_display_name", unknownCountryName) + setCountryFieldIfEmpty(row, "flag", "") + return + } + + row["country_code"] = country.Code + // HyApp 数字统计行以 country_id 对应的主数据为准;country_display_name 保持原始字段, + // country_name 则按中文展示名、英文名、国家码依次 fallback,供现有前端直接渲染。 + row["country_display_name"] = country.DisplayName + row["flag"] = country.Flag + row["country_name"] = firstNonEmptyString( + country.DisplayName, + country.Name, + country.Code, + unknownCountryName, + ) +} + +func setCountryFieldIfEmpty(row map[string]any, key string, fallback string) { + if rowString(row, key) == "" { + row[key] = fallback + } } // regionCatalog 汇总每个 App 的区域目录:hyapp App 共用 user-service 的区域主数据, diff --git a/server/admin/internal/modules/databi/service_test.go b/server/admin/internal/modules/databi/service_test.go index f28e36ca..8f8c7f45 100644 --- a/server/admin/internal/modules/databi/service_test.go +++ b/server/admin/internal/modules/databi/service_test.go @@ -2,9 +2,13 @@ package databi import ( "context" + "errors" + "reflect" "testing" "time" + "hyapp-admin-server/internal/appctx" + "hyapp-admin-server/internal/integration/userclient" "hyapp-admin-server/internal/model" "hyapp-admin-server/internal/repository" ) @@ -102,3 +106,143 @@ func TestRegionDisplayToleratesRoundedIDs(t *testing.T) { t.Fatalf("expected rounded id to match catalog") } } + +func TestMergeAndEnrichCountryDirectory(t *testing.T) { + laluDirectory := map[int64]countryDirectoryEntry{} + mergeCountryDirectory(laluDirectory, "lalu", []*userclient.Country{ + {CountryID: 158, CountryCode: "PK", CountryName: "Pakistan", CountryDisplayName: "巴基斯坦", Flag: "🇵🇰", Enabled: true}, + // disabled 国家仍可能出现在历史统计中,必须进入目录。 + {CountryID: 157, CountryCode: "BS", CountryName: "Philippines", CountryDisplayName: "菲律宾", Enabled: false}, + // country_id=0 是未知维度,不允许目录把它伪装成真实国家。 + {CountryID: 0, CountryCode: "UNKNOWN", CountryName: "Unknown", Enabled: true}, + }) + famiDirectory := map[int64]countryDirectoryEntry{} + mergeCountryDirectory(famiDirectory, "fami", []*userclient.Country{ + {CountryID: 1163, CountryCode: "BD", CountryName: "Bangladesh", CountryDisplayName: "孟加拉国", Enabled: true}, + }) + huwaaDirectory := map[int64]countryDirectoryEntry{} + mergeCountryDirectory(huwaaDirectory, "huwaa", []*userclient.Country{ + {CountryID: 953, CountryCode: "IN", CountryName: "India", CountryDisplayName: "印度", Enabled: true}, + }) + + if len(laluDirectory) != 2 { + t.Fatalf("expected two lalu country ids, got %#v", laluDirectory) + } + if country := laluDirectory[158]; country.AppCode != "lalu" || country.Name != "Pakistan" { + t.Fatalf("expected lalu country retained, got %+v", country) + } + if country := laluDirectory[157]; country.Enabled { + t.Fatalf("expected disabled country retained, got %+v", country) + } + + sourceRows := []map[string]any{ + {"country_id": int64(158)}, + {"country_id": int64(1163)}, + {"country_id": int64(953)}, + {"country_id": int64(0)}, + {"country_id": int64(9999)}, + } + rows := enrichCountryRows(sourceRows, laluDirectory, false) + if got := rowString(rows[0], "country_name"); got != "巴基斯坦" { + t.Fatalf("expected display name to win for country 158, got %q", got) + } + for _, index := range []int{1, 2, 3, 4} { + if got := rowString(rows[index], "country_name"); got != unknownCountryName { + t.Fatalf("expected row %d to remain unknown in lalu scope, got %q", index, got) + } + if got := rowString(rows[index], "country_display_name"); got != unknownCountryName { + t.Fatalf("expected row %d unknown display name, got %q", index, got) + } + } + if got := rowString(enrichCountryRows([]map[string]any{{"country_id": int64(1163)}}, famiDirectory, false)[0], "country_name"); got != "孟加拉国" { + t.Fatalf("expected fami country resolved only in fami scope, got %q", got) + } + if got := rowString(enrichCountryRows([]map[string]any{{"country_id": int64(953)}}, huwaaDirectory, false)[0], "country_name"); got != "印度" { + t.Fatalf("expected huwaa country resolved only in huwaa scope, got %q", got) + } + if _, mutated := sourceRows[0]["country_name"]; mutated { + t.Fatalf("expected enrichment to copy shared statistics rows") + } + + legacyRows := enrichCountryRows([]map[string]any{ + { + "country_id": int64(158), + "country_code": "LEGACY-PK", + "country_name": "Legacy Pakistan", + }, + {"country_id": int64(158), "country": "Legacy country field"}, + {"country_id": int64(158), "country_code": "LEGACY-CODE"}, + {"country_id": int64(158)}, + }, laluDirectory, true) + if got := rowString(legacyRows[0], "country_name"); got != "Legacy Pakistan" { + t.Fatalf("expected legacy source name preserved, got %q", got) + } + if got := rowString(legacyRows[0], "country_code"); got != "LEGACY-PK" { + t.Fatalf("expected legacy source code preserved, got %q", got) + } + if got := rowString(legacyRows[1], "country_name"); got != "Legacy country field" { + t.Fatalf("expected legacy country field preserved, got %q", got) + } + if got := rowString(legacyRows[2], "country_name"); got != "LEGACY-CODE" { + t.Fatalf("expected legacy code used instead of colliding HyApp id, got %q", got) + } + if got := rowString(legacyRows[3], "country_name"); got != unknownCountryName { + t.Fatalf("legacy numeric id must not borrow HyApp country name, got %q", got) + } +} + +type countryDirectoryClientStub struct { + userclient.Client + countries map[string][]*userclient.Country + errors map[string]error + calls []string + filtered bool +} + +func (c *countryDirectoryClientStub) ListCountries(ctx context.Context, req userclient.ListCountriesRequest) ([]*userclient.Country, error) { + appCode := appctx.FromContext(ctx) + c.calls = append(c.calls, appCode) + if req.Enabled != nil { + c.filtered = true + } + if err := c.errors[appCode]; err != nil { + return nil, err + } + return c.countries[appCode], nil +} + +func TestCountryDirectoriesQueryEachAllowedHyappAndContinueAfterFailure(t *testing.T) { + client := &countryDirectoryClientStub{ + countries: map[string][]*userclient.Country{ + "fami": {{CountryID: 1163, CountryCode: "BD", CountryName: "Bangladesh", CountryDisplayName: "孟加拉国", Enabled: true}}, + "lalu": {{CountryID: 158, CountryCode: "PK", CountryName: "Pakistan", CountryDisplayName: "巴基斯坦", Enabled: true}}, + }, + errors: map[string]error{"huwaa": errors.New("temporary user-service failure")}, + } + service := NewService(nil, nil, nil, client) + directories := service.countryDirectories(context.Background(), []AppInfo{ + {AppCode: "lalu", Kind: appKindHyapp}, + {AppCode: "aslan", Kind: appKindLegacy}, + {AppCode: "huwaa", Kind: appKindHyapp}, + {AppCode: "fami", Kind: appKindHyapp}, + }) + + if want := []string{"fami", "huwaa", "lalu"}; !reflect.DeepEqual(client.calls, want) { + t.Fatalf("expected each HyApp queried with its own context, got %v want %v", client.calls, want) + } + if client.filtered { + t.Fatalf("expected enabled filter omitted so disabled history can resolve") + } + if _, ok := directories["fami"][1163]; !ok { + t.Fatalf("expected successful app before failure retained") + } + if _, ok := directories["lalu"][158]; !ok { + t.Fatalf("expected apps after failure still queried") + } + if _, ok := directories["huwaa"]; ok { + t.Fatalf("failed app must not receive another app's directory: %#v", directories) + } + if len(directories) != 2 { + t.Fatalf("unexpected directories after one app failure: %#v", directories) + } +} diff --git a/server/admin/internal/modules/externaladmin/account_security_test.go b/server/admin/internal/modules/externaladmin/account_security_test.go new file mode 100644 index 00000000..2f8d096c --- /dev/null +++ b/server/admin/internal/modules/externaladmin/account_security_test.go @@ -0,0 +1,110 @@ +package externaladmin + +import ( + "testing" + + "github.com/DATA-DOG/go-sqlmock" + "gorm.io/driver/mysql" + "gorm.io/gorm" +) + +func TestDisableAccountRevokesEveryActiveSession(t *testing.T) { + service, adminMock, userMock, cleanup := newAccountMutationFixture(t) + defer cleanup() + adminMock.ExpectBegin() + adminMock.ExpectQuery("SELECT \\* FROM `external_admin_accounts` WHERE id = \\? AND app_code = \\?"). + WithArgs(uint64(7), "fami", 1).WillReturnRows(externalAccountRows()) + adminMock.ExpectExec("UPDATE `external_admin_accounts` SET .*status.* WHERE `id` = \\?"). + WillReturnResult(sqlmock.NewResult(0, 1)) + // No session id predicate is allowed here: disabling an account must revoke + // every still-active session for that account, including other devices. + adminMock.ExpectExec("UPDATE `external_admin_sessions` SET .*revoke_reason.*revoked_at_ms.* WHERE account_id = \\? AND revoked_at_ms = 0"). + WithArgs("account_disabled", sqlmock.AnyArg(), uint64(7)). + WillReturnResult(sqlmock.NewResult(0, 3)) + adminMock.ExpectCommit() + expectReloadedAccountAndLinkedUser(adminMock, userMock) + + account, err := service.SetStatus(t.Context(), "fami", 7, "disabled") + if err != nil { + t.Fatalf("disable account: %v", err) + } + if account.Status != "disabled" { + t.Fatalf("status = %q", account.Status) + } + assertAccountMutationExpectations(t, adminMock, userMock) +} + +func TestResetPasswordRevokesEveryActiveSession(t *testing.T) { + service, adminMock, userMock, cleanup := newAccountMutationFixture(t) + defer cleanup() + adminMock.ExpectBegin() + adminMock.ExpectQuery("SELECT \\* FROM `external_admin_accounts` WHERE id = \\? AND app_code = \\?"). + WithArgs(uint64(7), "fami", 1).WillReturnRows(externalAccountRows()) + adminMock.ExpectExec("UPDATE `external_admin_accounts` SET .*password_change_required.*password_hash.* WHERE `id` = \\?"). + WillReturnResult(sqlmock.NewResult(0, 1)) + // A reset is an administrator credential replacement, so even the currently + // active browser must re-authenticate with the temporary password. + adminMock.ExpectExec("UPDATE `external_admin_sessions` SET .*revoke_reason.*revoked_at_ms.* WHERE account_id = \\? AND revoked_at_ms = 0"). + WithArgs("password_reset", sqlmock.AnyArg(), uint64(7)). + WillReturnResult(sqlmock.NewResult(0, 3)) + adminMock.ExpectCommit() + expectReloadedAccountAndLinkedUser(adminMock, userMock) + + account, err := service.ResetPassword(t.Context(), "fami", 7, "replacement-password") + if err != nil { + t.Fatalf("reset password: %v", err) + } + if account.LinkedUser.UserID != 9001 { + t.Fatalf("linked user = %d", account.LinkedUser.UserID) + } + assertAccountMutationExpectations(t, adminMock, userMock) +} + +func newAccountMutationFixture(t *testing.T) (*Service, sqlmock.Sqlmock, sqlmock.Sqlmock, func()) { + t.Helper() + adminSQL, adminMock, err := sqlmock.New() + if err != nil { + t.Fatalf("create admin sql mock: %v", err) + } + adminDB, err := gorm.Open(mysql.New(mysql.Config{Conn: adminSQL, SkipInitializeWithVersion: true}), &gorm.Config{}) + if err != nil { + adminSQL.Close() + t.Fatalf("create admin gorm: %v", err) + } + userDB, userMock, err := sqlmock.New() + if err != nil { + adminSQL.Close() + t.Fatalf("create user sql mock: %v", err) + } + return NewService(adminDB, userDB, Config{}), adminMock, userMock, func() { + _ = userDB.Close() + _ = adminSQL.Close() + } +} + +func externalAccountRows() *sqlmock.Rows { + return sqlmock.NewRows([]string{ + "id", "app_code", "linked_app_user_id", "username", "password_hash", "permissions_json", "status", + "password_change_required", "failed_login_count", "locked_until_ms", "created_by_admin_id", "created_at_ms", "updated_at_ms", + }).AddRow(7, "fami", 9001, "operator", "hash", `[]`, "disabled", true, 0, 0, 1, 1, 1) +} + +func expectReloadedAccountAndLinkedUser(adminMock sqlmock.Sqlmock, userMock sqlmock.Sqlmock) { + adminMock.ExpectQuery("SELECT \\* FROM `external_admin_accounts` WHERE id = \\?"). + WithArgs(uint64(7), uint64(7), 1).WillReturnRows(externalAccountRows()) + userMock.ExpectQuery("SELECT u.user_id,"). + WithArgs(sqlmock.AnyArg(), sqlmock.AnyArg(), "fami", int64(9001)). + WillReturnRows(sqlmock.NewRows([]string{ + "user_id", "current_display_user_id", "default_display_user_id", "pretty_display_user_id", "pretty_id", "username", "avatar", "status", + }).AddRow(9001, "123456", "654321", "8888", "8888", "linked-user", "avatar", "active")) +} + +func assertAccountMutationExpectations(t *testing.T, adminMock sqlmock.Sqlmock, userMock sqlmock.Sqlmock) { + t.Helper() + if err := adminMock.ExpectationsWereMet(); err != nil { + t.Fatalf("admin sql expectations: %v", err) + } + if err := userMock.ExpectationsWereMet(); err != nil { + t.Fatalf("user sql expectations: %v", err) + } +} diff --git a/server/admin/internal/modules/externaladmin/change_password_test.go b/server/admin/internal/modules/externaladmin/change_password_test.go new file mode 100644 index 00000000..e412b933 --- /dev/null +++ b/server/admin/internal/modules/externaladmin/change_password_test.go @@ -0,0 +1,206 @@ +package externaladmin + +import ( + "bytes" + "encoding/json" + "errors" + "net/http" + "net/http/httptest" + "testing" + + "hyapp-admin-server/internal/appctx" + adminmiddleware "hyapp-admin-server/internal/middleware" + "hyapp-admin-server/internal/security" + + "github.com/DATA-DOG/go-sqlmock" + "github.com/gin-gonic/gin" + "gorm.io/driver/mysql" + "gorm.io/gorm" +) + +func TestChangePasswordRejectsCurrentPasswordWithoutClearingGateOrRevokingSessions(t *testing.T) { + service, mock, cleanup := newPasswordReuseFixture(t, "initial-password") + defer cleanup() + + err := service.ChangePassword(t.Context(), SessionPrincipal{ + AccountID: 7, SessionID: 21, AppCode: "fami", + }, ChangePasswordInput{CurrentPassword: "initial-password", NewPassword: "initial-password"}) + if !errors.Is(err, ErrPasswordReused) { + t.Fatalf("change password error = %v, want ErrPasswordReused", err) + } + // The mock intentionally has no UPDATE expectation. Any attempt to clear + // password_change_required or revoke sessions makes the transaction/test fail. + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("password reuse performed a write: %v", err) + } +} + +func TestChangePasswordHandlerMapsPasswordReuseToExplicitBadRequest(t *testing.T) { + service, mock, cleanup := newPasswordReuseFixture(t, "initial-password") + defer cleanup() + handler := &Handler{service: service} + + gin.SetMode(gin.TestMode) + engine := gin.New() + engine.POST("/change-password", func(c *gin.Context) { + c.Set(contextPrincipal, SessionPrincipal{AccountID: 7, SessionID: 21, AppCode: "fami"}) + c.Next() + }, handler.ChangePassword) + body := bytes.NewBufferString(`{"currentPassword":"initial-password","newPassword":"initial-password"}`) + request := httptest.NewRequest(http.MethodPost, "/change-password", body) + request.Header.Set("Content-Type", "application/json") + responseRecorder := httptest.NewRecorder() + engine.ServeHTTP(responseRecorder, request) + + if responseRecorder.Code != http.StatusBadRequest { + t.Fatalf("status = %d body=%s", responseRecorder.Code, responseRecorder.Body.String()) + } + var responseBody struct { + Message string `json:"message"` + } + if err := json.Unmarshal(responseRecorder.Body.Bytes(), &responseBody); err != nil { + t.Fatalf("decode response: %v", err) + } + if responseBody.Message != "新密码不能与当前密码相同" { + t.Fatalf("message = %q", responseBody.Message) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("password reuse handler performed a write: %v", err) + } +} + +func TestAllPasswordWritersRejectWhitespaceOnlyCredential(t *testing.T) { + // A non-nil inert DB is enough because all three methods must reject the shared + // validation error before any App/user lookup or database write can run. + service := NewService(&gorm.DB{}, nil, Config{}) + tests := []struct { + name string + call func() error + }{ + { + name: "create", + call: func() error { + _, err := service.CreateAccount(t.Context(), CreateInput{ + AppCode: "fami", TargetUserID: "123456", Username: "operator", Password: " ", CreatedByAdminID: 1, + }) + return err + }, + }, + { + name: "reset", + call: func() error { + _, err := service.ResetPassword(t.Context(), "fami", 7, " ") + return err + }, + }, + { + name: "change", + call: func() error { + return service.ChangePassword(t.Context(), SessionPrincipal{AccountID: 7, SessionID: 21, AppCode: "fami"}, ChangePasswordInput{ + CurrentPassword: "initial-password", NewPassword: " ", + }) + }, + }, + } + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + if err := testCase.call(); !errors.Is(err, ErrPasswordBlank) { + t.Fatalf("error = %v, want ErrPasswordBlank", err) + } + }) + } +} + +func TestPasswordHandlersReturnExplicitWhitespaceValidationMessage(t *testing.T) { + tests := []struct { + name string + path string + body string + wantMessage string + register func(*gin.Engine, *Handler) + }{ + { + name: "create", path: "/create", wantMessage: "密码不能全部为空白字符", + body: `{"targetUserId":"123456","username":"operator","password":" "}`, + register: func(engine *gin.Engine, handler *Handler) { + engine.POST("/create", func(c *gin.Context) { + c.Set(adminmiddleware.ContextUserID, uint(1)) + c.Set(adminmiddleware.ContextPermissions, []string{"external-admin-user:permissions"}) + c.Request = c.Request.WithContext(appctx.WithContext(c.Request.Context(), "fami")) + c.Next() + }, handler.CreateAccount) + }, + }, + { + name: "reset", path: "/reset/7", wantMessage: "密码不能全部为空白字符", + body: `{"password":" "}`, + register: func(engine *gin.Engine, handler *Handler) { + engine.POST("/reset/:id", func(c *gin.Context) { + c.Request = c.Request.WithContext(appctx.WithContext(c.Request.Context(), "fami")) + c.Next() + }, handler.ResetPassword) + }, + }, + { + name: "change", path: "/change", wantMessage: "新密码不能全部为空白字符", + body: `{"currentPassword":"initial-password","newPassword":" "}`, + register: func(engine *gin.Engine, handler *Handler) { + engine.POST("/change", func(c *gin.Context) { + c.Set(contextPrincipal, SessionPrincipal{AccountID: 7, SessionID: 21, AppCode: "fami"}) + c.Next() + }, handler.ChangePassword) + }, + }, + } + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + gin.SetMode(gin.TestMode) + handler := &Handler{service: NewService(&gorm.DB{}, nil, Config{})} + engine := gin.New() + testCase.register(engine, handler) + request := httptest.NewRequest(http.MethodPost, testCase.path, bytes.NewBufferString(testCase.body)) + request.Header.Set("Content-Type", "application/json") + responseRecorder := httptest.NewRecorder() + engine.ServeHTTP(responseRecorder, request) + if responseRecorder.Code != http.StatusBadRequest { + t.Fatalf("status = %d body=%s", responseRecorder.Code, responseRecorder.Body.String()) + } + var responseBody struct { + Message string `json:"message"` + } + if err := json.Unmarshal(responseRecorder.Body.Bytes(), &responseBody); err != nil { + t.Fatalf("decode response: %v", err) + } + if responseBody.Message != testCase.wantMessage { + t.Fatalf("message = %q, want %q", responseBody.Message, testCase.wantMessage) + } + }) + } +} + +func newPasswordReuseFixture(t *testing.T, currentPassword string) (*Service, sqlmock.Sqlmock, func()) { + t.Helper() + sqlDB, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("create sql mock: %v", err) + } + adminDB, err := gorm.Open(mysql.New(mysql.Config{Conn: sqlDB, SkipInitializeWithVersion: true}), &gorm.Config{}) + if err != nil { + sqlDB.Close() + t.Fatalf("create gorm db: %v", err) + } + passwordHash, err := security.HashPassword(currentPassword) + if err != nil { + sqlDB.Close() + t.Fatalf("hash fixture password: %v", err) + } + mock.ExpectBegin() + mock.ExpectQuery("SELECT \\* FROM `external_admin_accounts` WHERE id = \\? AND app_code = \\?"). + WithArgs(uint64(7), "fami", 1). + WillReturnRows(sqlmock.NewRows([]string{ + "id", "app_code", "linked_app_user_id", "username", "password_hash", "permissions_json", "status", + "password_change_required", "failed_login_count", "locked_until_ms", "created_by_admin_id", "created_at_ms", "updated_at_ms", + }).AddRow(7, "fami", 9001, "operator", passwordHash, `[]`, "active", true, 0, 0, 1, 1, 1)) + mock.ExpectCommit() + return NewService(adminDB, nil, Config{}), mock, func() { _ = sqlDB.Close() } +} diff --git a/server/admin/internal/modules/externaladmin/global_username_test.go b/server/admin/internal/modules/externaladmin/global_username_test.go new file mode 100644 index 00000000..7b611f6e --- /dev/null +++ b/server/admin/internal/modules/externaladmin/global_username_test.go @@ -0,0 +1,123 @@ +package externaladmin + +import ( + "errors" + "net/http" + "net/http/httptest" + "os" + "strings" + "testing" + + adminmiddleware "hyapp-admin-server/internal/middleware" + + "github.com/DATA-DOG/go-sqlmock" + "github.com/gin-gonic/gin" + "gorm.io/driver/mysql" + "gorm.io/gorm" +) + +func TestCreateAccountRejectsUsernameAlreadyUsedByAnotherApp(t *testing.T) { + adminSQL, adminMock, err := sqlmock.New() + if err != nil { + t.Fatalf("create admin sql mock: %v", err) + } + defer adminSQL.Close() + adminDB, err := gorm.Open(mysql.New(mysql.Config{Conn: adminSQL, SkipInitializeWithVersion: true}), &gorm.Config{}) + if err != nil { + t.Fatalf("create admin gorm: %v", err) + } + userDB, userMock, err := sqlmock.New() + if err != nil { + t.Fatalf("create user sql mock: %v", err) + } + defer userDB.Close() + + // The check intentionally has no app_code predicate. It avoids owner-DB and + // bcrypt work for an obvious conflict; migration 100's unique index closes the + // concurrent-create race after this advisory check. + adminMock.ExpectQuery("SELECT `id` FROM `external_admin_accounts` WHERE username = \\? LIMIT \\?"). + WithArgs("shared-operator", 1). + WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(9)) + service := NewService(adminDB, userDB, Config{}) + _, err = service.CreateAccount(t.Context(), CreateInput{ + AppCode: "lalu", TargetUserID: "8888", Username: "Shared-Operator", + Password: "temporary-password", CreatedByAdminID: 1, + }) + if !errors.Is(err, ErrAccountConflict) { + t.Fatalf("create error = %v, want global username conflict", err) + } + if err := adminMock.ExpectationsWereMet(); err != nil { + t.Fatalf("admin sql expectations: %v", err) + } + if err := userMock.ExpectationsWereMet(); err != nil { + t.Fatalf("user DB must not be queried after global conflict: %v", err) + } +} + +func TestLoginIgnoresLegacyRequestAppAndAuditsUnknownAccountWithoutTenant(t *testing.T) { + adminSQL, adminMock, err := sqlmock.New() + if err != nil { + t.Fatalf("create admin sql mock: %v", err) + } + defer adminSQL.Close() + adminDB, err := gorm.Open(mysql.New(mysql.Config{Conn: adminSQL, SkipInitializeWithVersion: true}), &gorm.Config{}) + if err != nil { + t.Fatalf("create admin gorm: %v", err) + } + + adminMock.ExpectQuery("SELECT `id`,`app_code` FROM `external_admin_accounts` WHERE username = \\? LIMIT \\?"). + WithArgs("missing-operator", 1). + WillReturnRows(sqlmock.NewRows([]string{"id", "app_code"})) + // Unknown names use an empty app_code sentinel. The legacy request value "lalu" + // must not be copied into security audit data or used to select a tenant. + adminMock.ExpectBegin() + adminMock.ExpectExec("INSERT INTO `external_admin_login_logs`"). + WithArgs(nil, "", "missing-operator", "192.0.2.10", "", "failed", "invalid_credentials", sqlmock.AnyArg()). + WillReturnResult(sqlmock.NewResult(1, 1)) + adminMock.ExpectCommit() + + gin.SetMode(gin.TestMode) + engine := gin.New() + // Production installs the global App middleware before external routes. Login + // must remove its fallback "lalu" response header until credentials resolve. + engine.Use(adminmiddleware.AppCode()) + handler := New(adminDB, nil, Config{}, nil, WithLoginRateLimiter(allowFixedWindowLimiter{})) + RegisterExternalRoutes(engine.Group("/api/v1"), handler, BusinessHandlers{}) + request := httptest.NewRequest(http.MethodPost, "/api/v1/external/auth/login", strings.NewReader(`{"appCode":"lalu","account":"missing-operator","password":"wrong-password"}`)) + request.Header.Set("Content-Type", "application/json") + request.RemoteAddr = "192.0.2.10:12345" + responseRecorder := httptest.NewRecorder() + engine.ServeHTTP(responseRecorder, request) + if responseRecorder.Code != http.StatusUnauthorized { + t.Fatalf("status=%d body=%s", responseRecorder.Code, responseRecorder.Body.String()) + } + if got := responseRecorder.Header().Get("X-App-Code"); got != "" { + t.Fatalf("failed tenant-less login exposed default App header %q", got) + } + if !strings.Contains(responseRecorder.Body.String(), `"code":40100`) || strings.Contains(responseRecorder.Body.String(), "App") { + t.Fatalf("login response must expose only stable auth code and generic text: %s", responseRecorder.Body.String()) + } + if err := adminMock.ExpectationsWereMet(); err != nil { + t.Fatalf("admin sql expectations: %v", err) + } +} + +func TestGlobalUsernameMigrationIsOnlineAndFailClosed(t *testing.T) { + body, err := os.ReadFile("../../../migrations/100_external_admin_global_username.sql") + if err != nil { + t.Fatalf("read migration 100: %v", err) + } + sqlText := string(body) + for _, token := range []string{ + "ADD UNIQUE KEY uk_external_admin_accounts_username (username)", + "DROP INDEX uk_external_admin_accounts_app_username", + "ALGORITHM=INPLACE", "LOCK=NONE", + } { + if !strings.Contains(sqlText, token) { + t.Fatalf("migration 100 missing %q", token) + } + } + if strings.Contains(strings.ToUpper(sqlText), "UPDATE EXTERNAL_ADMIN_ACCOUNTS") || strings.Contains(strings.ToUpper(sqlText), "DELETE FROM EXTERNAL_ADMIN_ACCOUNTS") { + t.Fatal("migration must not silently rename or delete duplicate credentials") + } +} diff --git a/server/admin/internal/modules/externaladmin/handler.go b/server/admin/internal/modules/externaladmin/handler.go new file mode 100644 index 00000000..497f113e --- /dev/null +++ b/server/admin/internal/modules/externaladmin/handler.go @@ -0,0 +1,514 @@ +package externaladmin + +import ( + "context" + "database/sql" + "errors" + "fmt" + "net/http" + "strconv" + "strings" + "time" + + "hyapp-admin-server/internal/appctx" + "hyapp-admin-server/internal/middleware" + "hyapp-admin-server/internal/modules/shared" + "hyapp-admin-server/internal/response" + + "github.com/gin-gonic/gin" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "gorm.io/gorm" + userv1 "hyapp.local/api/proto/user/v1" +) + +type Handler struct { + service *Service + cfg Config + audit shared.OperationLogger + userHost userv1.UserHostServiceClient +} + +type HandlerOption func(*Handler) + +// WithUserHostClient enables only the external portal's explicitly whitelisted +// owner-service reads. The raw client is not exposed to generic proxy routing. +func WithUserHostClient(client userv1.UserHostServiceClient) HandlerOption { + return func(handler *Handler) { + handler.userHost = client + } +} + +func WithLoginRateLimiter(limiter FixedWindowLimiter) HandlerOption { + return func(handler *Handler) { + handler.service.limiter = limiter + } +} + +func New(db *gorm.DB, userDB *sql.DB, cfg Config, audit shared.OperationLogger, options ...HandlerOption) *Handler { + handler := &Handler{service: NewService(db, userDB, cfg), cfg: cfg, audit: audit} + for _, option := range options { + if option != nil { + option(handler) + } + } + return handler +} + +const ( + myTeamAgencyRPCPageSize = int32(5000) + myTeamAgencyRPCTimeout = 5 * time.Second + maxLoginBodyBytes = int64(8 << 10) +) + +type createAccountRequest struct { + TargetUserID FlexibleString `json:"targetUserId" binding:"required"` + Username string `json:"username" binding:"required"` + Password string `json:"password" binding:"required"` + Permissions optionalPermissionSelection `json:"permissions"` +} + +type statusRequest struct { + Status string `json:"status" binding:"required"` +} + +type passwordRequest struct { + Password string `json:"password" binding:"required"` +} + +type loginRequest struct { + Account string `json:"account"` + Username string `json:"username"` + Password string `json:"password"` +} + +type changePasswordRequest struct { + CurrentPassword string `json:"currentPassword"` + OldPassword string `json:"oldPassword"` + NewPassword string `json:"newPassword" binding:"required"` +} + +func (h *Handler) ListAccounts(c *gin.Context) { + page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) + pageSizeRaw := c.Query("pageSize") + if pageSizeRaw == "" { + pageSizeRaw = c.DefaultQuery("page_size", "20") + } + pageSize, _ := strconv.Atoi(pageSizeRaw) + result, err := h.service.ListAccounts(c.Request.Context(), ListInput{ + AppCode: appctx.FromContext(c.Request.Context()), Page: page, PageSize: pageSize, + Keyword: c.Query("keyword"), Status: c.Query("status"), + }) + if err != nil { + response.ServerError(c, "获取外管用户失败") + return + } + response.OK(c, result) +} + +func (h *Handler) ResolveTarget(c *gin.Context) { + target := strings.TrimSpace(c.Query("display_user_id")) + if target == "" { + target = strings.TrimSpace(c.Query("displayUserId")) + } + user, err := h.service.ResolveTarget(c.Request.Context(), appctx.FromContext(c.Request.Context()), target) + if errors.Is(err, ErrInvalidInput) { + response.BadRequest(c, "请输入用户短 ID") + return + } + if errors.Is(err, ErrTargetNotFound) { + response.NotFound(c, "当前 App 未找到该用户") + return + } + if err != nil { + response.ServerError(c, "查询用户失败") + return + } + existing, err := h.service.FindAccountByLinkedUser(c.Request.Context(), appctx.FromContext(c.Request.Context()), user) + if err != nil { + response.ServerError(c, "查询外管用户绑定失败") + return + } + response.OK(c, gin.H{"linkedUser": user, "existingExternalAdminUser": existing}) +} + +func (h *Handler) CreateAccount(c *gin.Context) { + var request createAccountRequest + if err := c.ShouldBindJSON(&request); err != nil { + response.BadRequest(c, "创建参数不正确") + return + } + // Every created account receives a permission snapshot, including the legacy + // omitted-field shape which expands to the full default. Recheck delegation here + // as defense in depth for direct handler mounting and future route refactors. + if !middleware.HasPermission(c, "external-admin-user:permissions") { + response.Forbidden(c, "没有配置外管用户权限的权限") + return + } + account, err := h.service.CreateAccount(c.Request.Context(), CreateInput{ + AppCode: appctx.FromContext(c.Request.Context()), TargetUserID: string(request.TargetUserID), + Username: request.Username, Password: request.Password, Permissions: request.Permissions.Value, + PermissionsSet: request.Permissions.Set, CreatedByAdminID: middleware.CurrentUserID(c), + }) + if errors.Is(err, ErrAccountConflict) { + response.Conflict(c, "外管账户名称已被使用,或当前 App 的绑定用户已存在") + return + } + if errors.Is(err, ErrTargetNotFound) { + response.NotFound(c, "当前 App 未找到该用户") + return + } + if errors.Is(err, ErrPasswordBlank) { + response.BadRequest(c, "密码不能全部为空白字符") + return + } + if errors.Is(err, ErrInvalidPermissions) { + response.BadRequest(c, permissionValidationMessage(err)) + return + } + if errors.Is(err, ErrInvalidInput) || strings.Contains(fmt.Sprint(err), "password length") { + response.BadRequest(c, "账户名称格式不正确,或密码超过 72 字节") + return + } + if err != nil { + response.ServerError(c, "创建外管用户失败") + return + } + shared.OperationLogWithResourceID(c, h.audit, "create-external-admin-user", "external_admin_accounts", strconv.FormatUint(account.ID, 10), "success", fmt.Sprintf("app_code=%s linked_user_id=%d username=%s permission_count=%d", account.AppCode, account.LinkedUser.UserID, account.Username, len(account.Permissions))) + response.Created(c, account) +} + +func (h *Handler) SetStatus(c *gin.Context) { + id, ok := parseUint64Param(c, "id") + if !ok { + return + } + var request statusRequest + if err := c.ShouldBindJSON(&request); err != nil { + response.BadRequest(c, "状态参数不正确") + return + } + account, err := h.service.SetStatus(c.Request.Context(), appctx.FromContext(c.Request.Context()), id, request.Status) + if errors.Is(err, ErrInvalidInput) { + response.BadRequest(c, "状态仅支持 active 或 disabled") + return + } + if errors.Is(err, ErrAccountNotFound) { + response.NotFound(c, "外管用户不存在") + return + } + if err != nil { + response.ServerError(c, "更新外管用户状态失败") + return + } + shared.OperationLogWithResourceID(c, h.audit, "update-external-admin-user-status", "external_admin_accounts", strconv.FormatUint(id, 10), "success", fmt.Sprintf("app_code=%s status=%s sessions_revoked=%t", account.AppCode, account.Status, account.Status == "disabled")) + response.OK(c, account) +} + +func (h *Handler) ResetPassword(c *gin.Context) { + id, ok := parseUint64Param(c, "id") + if !ok { + return + } + var request passwordRequest + if err := c.ShouldBindJSON(&request); err != nil { + response.BadRequest(c, "密码参数不正确") + return + } + account, err := h.service.ResetPassword(c.Request.Context(), appctx.FromContext(c.Request.Context()), id, request.Password) + if errors.Is(err, ErrPasswordBlank) { + response.BadRequest(c, "密码不能全部为空白字符") + return + } + if errors.Is(err, ErrInvalidInput) || strings.Contains(fmt.Sprint(err), "password length") { + response.BadRequest(c, "密码不能超过 72 字节") + return + } + if errors.Is(err, ErrAccountNotFound) { + response.NotFound(c, "外管用户不存在") + return + } + if err != nil { + response.ServerError(c, "重置外管用户密码失败") + return + } + shared.OperationLogWithResourceID(c, h.audit, "reset-external-admin-user-password", "external_admin_accounts", strconv.FormatUint(id, 10), "success", fmt.Sprintf("app_code=%s sessions_revoked=true", account.AppCode)) + response.OK(c, account) +} + +func (h *Handler) Login(c *gin.Context) { + // The global App middleware supplies the main-admin default before this anonymous + // route runs. No tenant is authoritative until a credential row resolves, so do + // not leak or imply that default on malformed, throttled or failed login responses. + c.Writer.Header().Del(appctx.HeaderAppCode) + // Limit parsing memory before decoding untrusted credentials. Binding tags are + // intentionally absent on loginRequest: every syntactically valid JSON attempt, + // including missing fields, must reach the distributed limiter before rejection. + c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, maxLoginBodyBytes) + var request loginRequest + if err := c.ShouldBindJSON(&request); err != nil { + var maxBytesErr *http.MaxBytesError + if errors.As(err, &maxBytesErr) { + response.PayloadTooLarge(c, "登录请求体不能超过 8 KiB") + return + } + response.BadRequest(c, "登录参数不正确") + return + } + username := strings.TrimSpace(request.Account) + if username == "" { + username = request.Username + } + result, err := h.service.Login(c.Request.Context(), LoginInput{ + Username: username, Password: request.Password, + IP: c.ClientIP(), UserAgent: c.Request.UserAgent(), + }) + var rateLimitErr *LoginRateLimitError + if errors.As(err, &rateLimitErr) { + retrySeconds := int64((rateLimitErr.RetryAfter + time.Second - 1) / time.Second) + if retrySeconds < 1 { + retrySeconds = 1 + } + c.Header("Retry-After", strconv.FormatInt(retrySeconds, 10)) + response.TooManyRequests(c, "登录尝试过于频繁,请稍后重试") + return + } + if errors.Is(err, ErrLoginLimiterFailed) { + response.ServiceUnavailable(c, "登录安全服务暂不可用") + return + } + if errors.Is(err, ErrInvalidCredentials) { + // App is deliberately absent from both input and error text. The account row is + // the only tenant authority, while the stable 401/40100 pair lets every locale + // render its own generic message without parsing this server-side fallback. + response.Unauthorized(c, "账号或密码错误") + return + } + if err != nil { + response.ServerError(c, "登录服务暂不可用") + return + } + // The global App middleware cannot know the tenant before authentication and + // therefore writes its generic default header. Replace it with the App resolved + // from the credential row so the successful response has one consistent tenant. + c.Header(appctx.HeaderAppCode, result.View.AppCode) + h.setSessionCookies(c, result.SessionToken, result.CSRFToken) + c.Header(CSRFHeaderName, result.CSRFToken) + response.OK(c, result.View) +} + +func (h *Handler) Me(c *gin.Context) { + principal, ok := CurrentPrincipal(c) + if !ok { + response.Unauthorized(c, "外管会话已失效") + return + } + csrfToken := CurrentCSRFToken(c) + view, err := h.service.Me(c.Request.Context(), principal, csrfToken) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) || errors.Is(err, sql.ErrNoRows) || errors.Is(err, ErrTargetNotFound) { + h.clearSessionCookies(c) + response.Unauthorized(c, "外管会话已失效") + } else { + response.ServerError(c, "获取外管会话失败") + } + return + } + if csrfToken != "" { + c.Header(CSRFHeaderName, csrfToken) + } + response.OK(c, view) +} + +func (h *Handler) Logout(c *gin.Context) { + principal, _ := CurrentPrincipal(c) + if err := h.service.RevokeSession(c.Request.Context(), principal.SessionID, "logout"); err != nil { + response.ServerError(c, "退出登录失败") + return + } + h.clearSessionCookies(c) + response.OK(c, gin.H{"loggedOut": true}) +} + +func (h *Handler) ChangePassword(c *gin.Context) { + principal, ok := CurrentPrincipal(c) + if !ok { + response.Unauthorized(c, "外管会话已失效") + return + } + var request changePasswordRequest + if err := c.ShouldBindJSON(&request); err != nil { + response.BadRequest(c, "密码参数不正确") + return + } + currentPassword := request.CurrentPassword + if strings.TrimSpace(currentPassword) == "" { + currentPassword = request.OldPassword + } + err := h.service.ChangePassword(c.Request.Context(), principal, ChangePasswordInput{CurrentPassword: currentPassword, NewPassword: request.NewPassword}) + if errors.Is(err, ErrInvalidCredentials) { + response.BadRequest(c, "当前密码不正确") + return + } + if errors.Is(err, ErrPasswordReused) { + response.BadRequest(c, "新密码不能与当前密码相同") + return + } + if errors.Is(err, ErrPasswordBlank) { + response.BadRequest(c, "新密码不能全部为空白字符") + return + } + if errors.Is(err, ErrInvalidInput) { + response.BadRequest(c, "新密码不能超过 72 字节") + return + } + if err != nil { + response.ServerError(c, "修改密码失败") + return + } + response.OK(c, gin.H{"passwordChanged": true}) +} + +// ListMyTeamAgencies returns only the team rooted at the App user bound to this +// external account. Deliberately do not read manager_user_id/user_id from query or +// path parameters: otherwise a valid external session could enumerate another +// manager's organization tree by changing one client-controlled value. +func (h *Handler) ListMyTeamAgencies(c *gin.Context) { + principal, ok := CurrentPrincipal(c) + if !ok || principal.LinkedAppUserID <= 0 { + response.Unauthorized(c, "外管会话已失效") + return + } + if h.userHost == nil { + response.ServerError(c, "团队服务暂不可用") + return + } + + page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) + pageSizeRaw := strings.TrimSpace(c.Query("pageSize")) + if pageSizeRaw == "" { + pageSizeRaw = c.DefaultQuery("page_size", "20") + } + pageSize, _ := strconv.Atoi(pageSizeRaw) + page, pageSize = normalizePage(page, pageSize) + + // The owner service resolves the complete active manager tree up to its + // defensive 5,000-row cap. Local slicing keeps total and pagination mutually + // consistent, while truncated explicitly tells clients when the owner cap hit. + ctx, cancel := context.WithTimeout(c.Request.Context(), myTeamAgencyRPCTimeout) + defer cancel() + result, err := h.userHost.ListManagerTeamAgencies(ctx, &userv1.ListManagerTeamAgenciesRequest{ + Meta: &userv1.RequestMeta{ + RequestId: middleware.CurrentRequestID(c), + Caller: "hyapp-admin-server-external", + SentAtMs: time.Now().UTC().UnixMilli(), + AppCode: principal.AppCode, + ClientIp: c.ClientIP(), + UserAgent: truncateText(c.Request.UserAgent(), 512), + }, + ManagerUserId: principal.LinkedAppUserID, + PageSize: myTeamAgencyRPCPageSize, + }) + if err != nil { + if status.Code(err) == codes.PermissionDenied { + response.Forbidden(c, "当前绑定用户不是有效的团队管理员") + return + } + response.ServerError(c, "获取我的团队失败") + return + } + + allItems := make([]MyTeamAgency, 0, len(result.GetAgencies())) + for _, agency := range result.GetAgencies() { + if agency == nil || agency.GetAgencyId() <= 0 { + continue + } + allItems = append(allItems, MyTeamAgency{ + AgencyID: agency.GetAgencyId(), OwnerUserID: agency.GetOwnerUserId(), + ParentBDUserID: agency.GetParentBdUserId(), Status: "active", + }) + } + // The owner RPC intentionally returns only relation IDs. Honor the UI's keyword + // without widening scope or scanning user tables: match only IDs already present + // in this session-scoped result, then calculate total and pagination from that set. + allItems = filterMyTeamAgencies(allItems, c.Query("keyword")) + items := paginateMyTeamAgencies(allItems, page, pageSize) + response.OK(c, MyTeamAgencyPage{ + Items: items, Page: page, PageSize: pageSize, Total: len(allItems), + TotalBDLeaders: result.GetTotalBdLeaders(), TotalBDs: result.GetTotalBds(), Truncated: result.GetTruncated(), + }) +} + +func filterMyTeamAgencies(items []MyTeamAgency, keyword string) []MyTeamAgency { + keyword = strings.TrimSpace(keyword) + if keyword == "" { + return items + } + filtered := make([]MyTeamAgency, 0, len(items)) + for _, item := range items { + if strings.Contains(strconv.FormatInt(item.AgencyID, 10), keyword) || + strings.Contains(strconv.FormatInt(item.OwnerUserID, 10), keyword) || + strings.Contains(strconv.FormatInt(item.ParentBDUserID, 10), keyword) { + filtered = append(filtered, item) + } + } + return filtered +} + +func paginateMyTeamAgencies(items []MyTeamAgency, page int, pageSize int) []MyTeamAgency { + if len(items) == 0 { + return []MyTeamAgency{} + } + lastPage := (len(items) + pageSize - 1) / pageSize + if page > lastPage { + return []MyTeamAgency{} + } + start := (page - 1) * pageSize + end := start + pageSize + if end > len(items) { + end = len(items) + } + return items[start:end] +} + +func (h *Handler) setSessionCookies(c *gin.Context, sessionToken string, csrfToken string) { + maxAge := int(h.cfg.SessionTTL.Seconds()) + if maxAge <= 0 { + maxAge = int((12 * time.Hour).Seconds()) + } + h.writeCookie(c, SessionCookieName, sessionToken, true, maxAge, time.Now().UTC().Add(time.Duration(maxAge)*time.Second)) + h.writeCookie(c, CSRFCookieName, csrfToken, false, maxAge, time.Now().UTC().Add(time.Duration(maxAge)*time.Second)) +} + +func (h *Handler) clearSessionCookies(c *gin.Context) { + expired := time.Unix(1, 0).UTC() + h.writeCookie(c, SessionCookieName, "", true, -1, expired) + h.writeCookie(c, CSRFCookieName, "", false, -1, expired) +} + +func (h *Handler) writeCookie(c *gin.Context, name string, value string, httpOnly bool, maxAge int, expires time.Time) { + http.SetCookie(c.Writer, &http.Cookie{ + Name: name, Value: value, Path: CookiePath, MaxAge: maxAge, Expires: expires, + HttpOnly: httpOnly, Secure: h.cfg.CookieSecure, SameSite: parseSameSite(h.cfg.CookieSameSite), + }) +} + +func parseSameSite(value string) http.SameSite { + switch strings.ToLower(strings.TrimSpace(value)) { + case "strict": + return http.SameSiteStrictMode + case "none": + return http.SameSiteNoneMode + default: + return http.SameSiteLaxMode + } +} + +func parseUint64Param(c *gin.Context, name string) (uint64, bool) { + id, err := strconv.ParseUint(c.Param(name), 10, 64) + if err != nil || id == 0 { + response.BadRequest(c, "ID 参数不正确") + return 0, false + } + return id, true +} diff --git a/server/admin/internal/modules/externaladmin/middleware.go b/server/admin/internal/modules/externaladmin/middleware.go new file mode 100644 index 00000000..e3e4b676 --- /dev/null +++ b/server/admin/internal/modules/externaladmin/middleware.go @@ -0,0 +1,194 @@ +package externaladmin + +import ( + "crypto/subtle" + "errors" + "net/http" + "strings" + "time" + + "hyapp-admin-server/internal/appctx" + adminmiddleware "hyapp-admin-server/internal/middleware" + "hyapp-admin-server/internal/model" + "hyapp-admin-server/internal/response" + "hyapp-admin-server/internal/security" + + "github.com/gin-gonic/gin" +) + +const ( + contextPrincipal = "externalAdminPrincipal" + contextCSRFToken = "externalAdminCSRFToken" +) + +func (h *Handler) AuthRequired() gin.HandlerFunc { + return func(c *gin.Context) { + cookie, err := c.Request.Cookie(SessionCookieName) + if err != nil || strings.TrimSpace(cookie.Value) == "" { + response.Unauthorized(c, "缺少外管会话") + c.Abort() + return + } + principal, err := h.service.Authenticate(c.Request.Context(), cookie.Value) + if err != nil { + if errors.Is(err, ErrInvalidSession) { + h.clearSessionCookies(c) + response.Unauthorized(c, "外管会话已失效") + } else { + response.ServerError(c, "外管会话服务暂不可用") + } + c.Abort() + return + } + + // The session is the tenant authority. A caller may omit X-App-Code, but it can never + // switch tenants by sending a header that differs from the App fixed at login. + headerAppCode := strings.ToLower(strings.TrimSpace(c.GetHeader(appctx.HeaderAppCode))) + if headerAppCode != "" && headerAppCode != principal.AppCode { + response.Forbidden(c, "请求 App 与外管会话不一致") + c.Abort() + return + } + c.Request = c.Request.WithContext(appctx.WithContext(c.Request.Context(), principal.AppCode)) + c.Header(appctx.HeaderAppCode, principal.AppCode) + c.Set(contextPrincipal, principal) + // Existing business handlers forward these generic actor fields to owner services. Use a + // collision-free synthetic identity there; the real account remains in the external audit log. + c.Set(adminmiddleware.ContextUserID, principal.OperatorID) + c.Set(adminmiddleware.ContextUsername, operatorUsername(principal.AppCode, principal.Username)) + c.Set(adminmiddleware.ContextPermissions, principal.Permissions) + + // The raw CSRF secret is never persisted server-side. Echo it only when the browser's + // double-submit cookie still matches the hash stored in this exact session. + if csrfCookie, cookieErr := c.Request.Cookie(CSRFCookieName); cookieErr == nil && secureEqualHash(csrfCookie.Value, principal.CSRFTokenHash) { + c.Set(contextCSRFToken, csrfCookie.Value) + } + c.Next() + } +} + +func (h *Handler) RequireCSRF() gin.HandlerFunc { + return func(c *gin.Context) { + if isSafeMethod(c.Request.Method) { + c.Next() + return + } + principal, ok := CurrentPrincipal(c) + if !ok { + response.Unauthorized(c, "外管会话已失效") + c.Abort() + return + } + csrfCookie, cookieErr := c.Request.Cookie(CSRFCookieName) + headerToken := strings.TrimSpace(c.GetHeader(CSRFHeaderName)) + if cookieErr != nil || headerToken == "" || !secureEqual(csrfCookie.Value, headerToken) || !secureEqualHash(headerToken, principal.CSRFTokenHash) { + response.Forbidden(c, "CSRF 校验失败") + c.Abort() + return + } + c.Set(contextCSRFToken, headerToken) + c.Next() + } +} + +func (h *Handler) RequirePasswordChanged() gin.HandlerFunc { + // Deprecated helper retained for downstream source compatibility. External routes + // never install this gate, and session principals always expose the marker as false. + return func(c *gin.Context) { + principal, ok := CurrentPrincipal(c) + if !ok { + response.Unauthorized(c, "外管会话已失效") + c.Abort() + return + } + if principal.PasswordChangeRequired { + response.Forbidden(c, "请先修改初始密码") + c.Abort() + return + } + c.Next() + } +} + +func (h *Handler) Audit() gin.HandlerFunc { + return func(c *gin.Context) { + start := time.Now() + c.Next() + if isSafeMethod(c.Request.Method) { + return + } + principal, ok := CurrentPrincipal(c) + if !ok { + return + } + status := "success" + if c.Writer.Status() >= http.StatusBadRequest { + status = "failed" + } + fullPath := c.FullPath() + if fullPath == "" { + fullPath = c.Request.URL.Path + } + _ = h.service.CreateOperationLog(c.Request.Context(), model.ExternalAdminOperationLog{ + AccountID: principal.AccountID, AppCode: principal.AppCode, Username: principal.Username, + RequestID: adminmiddleware.CurrentRequestID(c), Action: strings.ToLower(c.Request.Method) + " " + fullPath, + Resource: externalAuditResource(fullPath), ResourceID: externalAuditResourceID(c), + Method: c.Request.Method, Path: c.Request.URL.Path, IP: c.ClientIP(), UserAgent: c.Request.UserAgent(), + Status: status, HTTPStatus: c.Writer.Status(), LatencyMS: time.Since(start).Milliseconds(), + }) + } +} + +func CurrentPrincipal(c *gin.Context) (SessionPrincipal, bool) { + value, ok := c.Get(contextPrincipal) + if !ok { + return SessionPrincipal{}, false + } + principal, ok := value.(SessionPrincipal) + return principal, ok +} + +func CurrentCSRFToken(c *gin.Context) string { + value, _ := c.Get(contextCSRFToken) + token, _ := value.(string) + return token +} + +func secureEqual(left string, right string) bool { + if len(left) == 0 || len(left) != len(right) { + return false + } + return subtle.ConstantTimeCompare([]byte(left), []byte(right)) == 1 +} + +func secureEqualHash(raw string, expectedHash string) bool { + return secureEqual(security.HashToken(raw), expectedHash) +} + +func isSafeMethod(method string) bool { + switch method { + case http.MethodGet, http.MethodHead, http.MethodOptions: + return true + default: + return false + } +} + +func externalAuditResourceID(c *gin.Context) string { + for _, name := range []string{"id", "user_id", "room_id", "resource_id", "grant_id", "pretty_id", "banner_id"} { + if value := c.Param(name); value != "" { + return value + } + } + return "" +} + +func externalAuditResource(path string) string { + parts := strings.Split(strings.Trim(path, "/"), "/") + for index, part := range parts { + if part == "external" && index+1 < len(parts) { + return parts[index+1] + } + } + return "external-admin" +} diff --git a/server/admin/internal/modules/externaladmin/middleware_test.go b/server/admin/internal/modules/externaladmin/middleware_test.go new file mode 100644 index 00000000..1c6ed3e0 --- /dev/null +++ b/server/admin/internal/modules/externaladmin/middleware_test.go @@ -0,0 +1,271 @@ +package externaladmin + +import ( + "errors" + "net/http" + "net/http/httptest" + "testing" + "time" + + "hyapp-admin-server/internal/appctx" + adminmiddleware "hyapp-admin-server/internal/middleware" + "hyapp-admin-server/internal/security" + + "github.com/DATA-DOG/go-sqlmock" + "github.com/gin-gonic/gin" + "gorm.io/driver/mysql" + "gorm.io/gorm" +) + +func TestRequireCSRFAcceptsOnlyMatchingCookieHeaderAndSessionHash(t *testing.T) { + gin.SetMode(gin.TestMode) + csrfToken := "csrf-secret" + handler := &Handler{} + engine := gin.New() + engine.POST("/write", func(c *gin.Context) { + c.Set(contextPrincipal, SessionPrincipal{CSRFTokenHash: security.HashToken(csrfToken)}) + }, handler.RequireCSRF(), func(c *gin.Context) { c.Status(http.StatusNoContent) }) + + validRequest := httptest.NewRequest(http.MethodPost, "/write", nil) + validRequest.AddCookie(&http.Cookie{Name: CSRFCookieName, Value: csrfToken}) + validRequest.Header.Set(CSRFHeaderName, csrfToken) + validResponse := httptest.NewRecorder() + engine.ServeHTTP(validResponse, validRequest) + if validResponse.Code != http.StatusNoContent { + t.Fatalf("valid csrf status = %d body=%s", validResponse.Code, validResponse.Body.String()) + } + + invalidRequest := httptest.NewRequest(http.MethodPost, "/write", nil) + invalidRequest.AddCookie(&http.Cookie{Name: CSRFCookieName, Value: csrfToken}) + invalidRequest.Header.Set(CSRFHeaderName, "different") + invalidResponse := httptest.NewRecorder() + engine.ServeHTTP(invalidResponse, invalidRequest) + if invalidResponse.Code != http.StatusForbidden { + t.Fatalf("invalid csrf status = %d body=%s", invalidResponse.Code, invalidResponse.Body.String()) + } +} + +func TestExternalSessionCookiesAreHostOnlyAndPathScoped(t *testing.T) { + gin.SetMode(gin.TestMode) + handler := &Handler{cfg: Config{SessionTTL: time.Hour, CookieSecure: true, CookieSameSite: "none"}} + engine := gin.New() + engine.POST("/login", func(c *gin.Context) { + handler.setSessionCookies(c, "session-token", "csrf-token") + c.Status(http.StatusNoContent) + }) + response := httptest.NewRecorder() + engine.ServeHTTP(response, httptest.NewRequest(http.MethodPost, "/login", nil)) + + cookies := response.Result().Cookies() + if len(cookies) != 2 { + t.Fatalf("cookie count = %d, want 2", len(cookies)) + } + for _, cookie := range cookies { + if cookie.Path != CookiePath || cookie.Domain != "" || !cookie.Secure || cookie.SameSite != http.SameSiteNoneMode { + t.Fatalf("unsafe cookie attributes: %+v", cookie) + } + } + if !cookieByName(cookies, SessionCookieName).HttpOnly { + t.Fatal("session cookie must be HttpOnly") + } + if cookieByName(cookies, CSRFCookieName).HttpOnly { + t.Fatal("double-submit CSRF cookie must be readable") + } +} + +func TestExternalSessionCookiesAllowLocalHTTPWithLaxSameSite(t *testing.T) { + gin.SetMode(gin.TestMode) + handler := &Handler{cfg: Config{SessionTTL: time.Hour, CookieSecure: false, CookieSameSite: "lax"}} + engine := gin.New() + engine.POST("/login", func(c *gin.Context) { + handler.setSessionCookies(c, "session-token", "csrf-token") + c.Status(http.StatusNoContent) + }) + response := httptest.NewRecorder() + engine.ServeHTTP(response, httptest.NewRequest(http.MethodPost, "/login", nil)) + for _, cookie := range response.Result().Cookies() { + if cookie.Secure || cookie.SameSite != http.SameSiteLaxMode { + t.Fatalf("local cookie must work over HTTP with Lax SameSite: %+v", cookie) + } + } +} + +func TestAuthRequiredRejectsMismatchedAppHeaderAndBindsOmittedHeaderToSessionApp(t *testing.T) { + for _, testCase := range []struct { + name string + headerApp string + wantStatus int + wantBound bool + }{ + {name: "mismatch rejected", headerApp: "lalu", wantStatus: http.StatusForbidden}, + {name: "omitted header bound", headerApp: "", wantStatus: http.StatusNoContent, wantBound: true}, + } { + t.Run(testCase.name, func(t *testing.T) { + handler, adminMock, userMock, cleanup := newAuthRequiredFixture(t, "session-secret", "active") + defer cleanup() + gin.SetMode(gin.TestMode) + engine := gin.New() + engine.GET("/protected", handler.AuthRequired(), func(c *gin.Context) { + if testCase.wantBound { + principal, ok := CurrentPrincipal(c) + if !ok || principal.SessionID != 11 { + t.Fatalf("session principal = %+v ok=%t", principal, ok) + } + if got := appctx.FromContext(c.Request.Context()); got != "fami" { + t.Fatalf("request app = %q, want session app fami", got) + } + if got := c.Writer.Header().Get(appctx.HeaderAppCode); got != "fami" { + t.Fatalf("response app header = %q", got) + } + if got := adminmiddleware.CurrentUserID(c); uint64(got) != externalOperatorNamespace|7 { + t.Fatalf("synthetic operator = %d", got) + } + } + c.Status(http.StatusNoContent) + }) + + request := httptest.NewRequest(http.MethodGet, "/protected", nil) + request.AddCookie(&http.Cookie{Name: SessionCookieName, Value: "session-secret"}) + if testCase.headerApp != "" { + request.Header.Set(appctx.HeaderAppCode, testCase.headerApp) + } + responseRecorder := httptest.NewRecorder() + engine.ServeHTTP(responseRecorder, request) + if responseRecorder.Code != testCase.wantStatus { + t.Fatalf("status = %d body=%s", responseRecorder.Code, responseRecorder.Body.String()) + } + assertAuthFixtureExpectations(t, adminMock, userMock) + }) + } +} + +func TestAuthRequiredBlocksBusinessDirectlyWhenSessionAppWasDisabled(t *testing.T) { + handler, adminMock, userMock, cleanup := newAuthRequiredFixture(t, "session-secret", "disabled") + defer cleanup() + gin.SetMode(gin.TestMode) + engine := gin.New() + reachedBusiness := false + // Intentionally omit /auth/me: this proves a stale browser cannot bypass the + // App-state check by navigating straight to a business API. + engine.GET("/business", handler.AuthRequired(), func(c *gin.Context) { + reachedBusiness = true + c.Status(http.StatusNoContent) + }) + request := httptest.NewRequest(http.MethodGet, "/business", nil) + request.AddCookie(&http.Cookie{Name: SessionCookieName, Value: "session-secret"}) + responseRecorder := httptest.NewRecorder() + engine.ServeHTTP(responseRecorder, request) + if responseRecorder.Code != http.StatusUnauthorized || reachedBusiness { + t.Fatalf("status=%d reached_business=%t body=%s", responseRecorder.Code, reachedBusiness, responseRecorder.Body.String()) + } + assertAuthFixtureExpectations(t, adminMock, userMock) +} + +func TestAuthRequiredFailsClosedWithoutRevokingOnAppDatabaseError(t *testing.T) { + handler, adminMock, userMock, cleanup := newAuthRequiredFixture(t, "session-secret", "error") + defer cleanup() + gin.SetMode(gin.TestMode) + engine := gin.New() + reachedBusiness := false + engine.GET("/business", handler.AuthRequired(), func(c *gin.Context) { + reachedBusiness = true + c.Status(http.StatusNoContent) + }) + request := httptest.NewRequest(http.MethodGet, "/business", nil) + request.AddCookie(&http.Cookie{Name: SessionCookieName, Value: "session-secret"}) + responseRecorder := httptest.NewRecorder() + engine.ServeHTTP(responseRecorder, request) + if responseRecorder.Code != http.StatusInternalServerError || reachedBusiness { + t.Fatalf("status=%d reached_business=%t body=%s", responseRecorder.Code, reachedBusiness, responseRecorder.Body.String()) + } + // The fixture has no revocation UPDATE expectation. A transient owner-DB error + // must fail this request closed without converting a recoverable session to 401. + assertAuthFixtureExpectations(t, adminMock, userMock) +} + +func TestRequirePasswordChangedBlocksBusinessRoutes(t *testing.T) { + gin.SetMode(gin.TestMode) + handler := &Handler{} + engine := gin.New() + engine.GET("/business", func(c *gin.Context) { + c.Set(contextPrincipal, SessionPrincipal{PasswordChangeRequired: true}) + c.Next() + }, handler.RequirePasswordChanged(), func(c *gin.Context) { + c.Status(http.StatusNoContent) + }) + + responseRecorder := httptest.NewRecorder() + engine.ServeHTTP(responseRecorder, httptest.NewRequest(http.MethodGet, "/business", nil)) + if responseRecorder.Code != http.StatusForbidden { + t.Fatalf("status = %d body=%s", responseRecorder.Code, responseRecorder.Body.String()) + } +} + +func newAuthRequiredFixture(t *testing.T, rawToken string, appState string) (*Handler, sqlmock.Sqlmock, sqlmock.Sqlmock, func()) { + t.Helper() + adminSQL, adminMock, err := sqlmock.New() + if err != nil { + t.Fatalf("create admin sql mock: %v", err) + } + adminDB, err := gorm.Open(mysql.New(mysql.Config{Conn: adminSQL, SkipInitializeWithVersion: true}), &gorm.Config{}) + if err != nil { + adminSQL.Close() + t.Fatalf("create gorm db: %v", err) + } + userDB, userMock, err := sqlmock.New() + if err != nil { + adminSQL.Close() + t.Fatalf("create user sql mock: %v", err) + } + nowMS := time.Now().UTC().UnixMilli() + adminMock.ExpectQuery("SELECT \\* FROM `external_admin_sessions` WHERE token_hash = \\? AND revoked_at_ms = 0 AND expires_at_ms > \\?"). + WithArgs(security.HashToken(rawToken), sqlmock.AnyArg(), 1). + WillReturnRows(sqlmock.NewRows([]string{ + "id", "account_id", "app_code", "token_hash", "csrf_token_hash", "ip", "user_agent", "expires_at_ms", "last_seen_at_ms", "revoked_at_ms", "revoke_reason", "created_at_ms", + }).AddRow(11, 7, "fami", security.HashToken(rawToken), security.HashToken("csrf"), "127.0.0.1", "browser", nowMS+3600000, nowMS, 0, "", nowMS)) + adminMock.ExpectQuery("SELECT \\* FROM `external_admin_accounts` WHERE `external_admin_accounts`.`id` = \\?"). + WithArgs(uint64(7)). + WillReturnRows(sqlmock.NewRows([]string{ + "id", "app_code", "linked_app_user_id", "username", "password_hash", "permissions_json", "status", + "password_change_required", "failed_login_count", "locked_until_ms", "created_by_admin_id", "created_at_ms", "updated_at_ms", + }).AddRow(7, "fami", 9001, "operator", "hash", `["bd:view"]`, "active", false, 0, 0, 1, nowMS, nowMS)) + appQuery := userMock.ExpectQuery("SELECT app_code, app_name, logo_url FROM apps WHERE app_code = \\? AND status = 'active' LIMIT 1").WithArgs("fami") + switch appState { + case "active": + appQuery.WillReturnRows(sqlmock.NewRows([]string{"app_code", "app_name", "logo_url"}).AddRow("fami", "Fami", "logo")) + case "disabled": + appQuery.WillReturnRows(sqlmock.NewRows([]string{"app_code", "app_name", "logo_url"})) + adminMock.ExpectBegin() + adminMock.ExpectExec("UPDATE `external_admin_sessions`"). + WithArgs("app_disabled", sqlmock.AnyArg(), uint64(11)). + WillReturnResult(sqlmock.NewResult(0, 1)) + adminMock.ExpectCommit() + case "error": + appQuery.WillReturnError(errors.New("user database temporarily unavailable")) + default: + t.Fatalf("unknown app state %q", appState) + } + return &Handler{service: NewService(adminDB, userDB, Config{})}, adminMock, userMock, func() { + _ = userDB.Close() + _ = adminSQL.Close() + } +} + +func assertAuthFixtureExpectations(t *testing.T, adminMock sqlmock.Sqlmock, userMock sqlmock.Sqlmock) { + t.Helper() + if err := adminMock.ExpectationsWereMet(); err != nil { + t.Fatalf("admin auth sql expectations: %v", err) + } + if err := userMock.ExpectationsWereMet(); err != nil { + t.Fatalf("user auth sql expectations: %v", err) + } +} + +func cookieByName(cookies []*http.Cookie, name string) *http.Cookie { + for _, cookie := range cookies { + if cookie.Name == name { + return cookie + } + } + return &http.Cookie{} +} diff --git a/server/admin/internal/modules/externaladmin/permissions.go b/server/admin/internal/modules/externaladmin/permissions.go new file mode 100644 index 00000000..8afe6adb --- /dev/null +++ b/server/admin/internal/modules/externaladmin/permissions.go @@ -0,0 +1,344 @@ +package externaladmin + +import ( + "context" + "errors" + "fmt" + "reflect" + "strings" + "time" + + "hyapp-admin-server/internal/model" + + "gorm.io/gorm" + "gorm.io/gorm/clause" +) + +// PermissionCatalogItem is the only assignable permission source for external accounts. +// Keeping route permissions, capability aliases and form metadata in one catalog prevents +// a client from persisting arbitrary main-admin permissions into an external session. +type PermissionCatalogItem struct { + Code string `json:"code"` + Label string `json:"label"` + Group string `json:"group"` + Dependencies []string `json:"dependencies"` + Capabilities []string `json:"capabilities"` + DefaultGranted bool `json:"defaultGranted"` +} + +type AccountPermissionView struct { + AccountID uint64 `json:"accountId,string"` + Permissions []string `json:"permissions"` + Revision uint64 `json:"revision"` +} + +type UpdatePermissionsInput struct { + Permissions []string + ExpectedRevision uint64 +} + +type PermissionUpdateResult struct { + Account AccountDTO + PreviousPermissions []string + Changed bool + SessionsRevoked bool +} + +type PermissionValidationError struct { + Permission string + Dependency string +} + +func (err *PermissionValidationError) Error() string { + if err.Dependency != "" { + return fmt.Sprintf("%s: %s requires %s", ErrInvalidPermissions, err.Permission, err.Dependency) + } + return fmt.Sprintf("%s: unsupported permission %s", ErrInvalidPermissions, err.Permission) +} + +func (err *PermissionValidationError) Unwrap() error { return ErrInvalidPermissions } + +var permissionCatalog = []PermissionCatalogItem{ + {Code: "user:list", Label: "用户列表", Group: "用户管理", Capabilities: []string{"user:list"}, DefaultGranted: true}, + {Code: "user:update", Label: "用户信息编辑", Group: "用户管理", Capabilities: []string{"user:update"}, DefaultGranted: true}, + {Code: "user-ban:list", Label: "账号封禁列表", Group: "用户管理", Capabilities: []string{"user-ban:list"}, DefaultGranted: true}, + {Code: "user:ban", Label: "执行封禁", Group: "用户管理", Capabilities: []string{"user:ban"}, DefaultGranted: true}, + {Code: "user:unban", Label: "解除封禁", Group: "用户管理", Capabilities: []string{"user:unban"}, DefaultGranted: true}, + {Code: "host:list", Label: "主播列表", Group: "组织管理", Capabilities: []string{"host:list"}, DefaultGranted: true}, + {Code: "agency:list", Label: "公会列表", Group: "组织管理", Capabilities: []string{"agency:list"}, DefaultGranted: true}, + {Code: "bd:list", Label: "BD 列表", Group: "组织管理", Capabilities: []string{"bd:list"}, DefaultGranted: true}, + {Code: "bd-manager:list", Label: "BD Manager 列表", Group: "组织管理", Capabilities: []string{"bd-manager:list"}, DefaultGranted: true}, + {Code: "super-admin:list", Label: "Super Admin 列表", Group: "组织管理", Capabilities: []string{"super-admin:list"}, DefaultGranted: true}, + {Code: "team:view", Label: "我的团队", Group: "组织管理", Capabilities: []string{"team:view"}, DefaultGranted: true}, + {Code: "room:list", Label: "房间管理", Group: "房间管理", Capabilities: []string{"room:list"}, DefaultGranted: true}, + {Code: "room:update", Label: "房间编辑", Group: "房间管理", Capabilities: []string{"room:update"}, DefaultGranted: true}, + {Code: "privilege:list", Label: "用户特权道具列表", Group: "资源与发放", Capabilities: []string{"privilege:list"}, DefaultGranted: true}, + {Code: "privilege:grant", Label: "特权道具发放", Group: "资源与发放", Dependencies: []string{"user-title:grant", "room-background:grant"}, Capabilities: []string{"privilege:grant"}, DefaultGranted: true}, + {Code: "pretty-id:grant", Label: "靓号下发", Group: "资源与发放", Capabilities: []string{"pretty-id:grant"}, DefaultGranted: true}, + // Wallet resources currently have no authoritative user-title/room-background semantic type. + // Keep the three labels requested by the product, but make them one fail-closed assignment + // bundle until the owner model can classify them without guessing from names or URLs. + {Code: "user-title:grant", Label: "用户称号下发", Group: "资源与发放", Dependencies: []string{"privilege:grant", "room-background:grant"}, Capabilities: []string{"user-title:grant"}, DefaultGranted: true}, + {Code: "room-background:grant", Label: "房间背景图下发", Group: "资源与发放", Dependencies: []string{"privilege:grant", "user-title:grant"}, Capabilities: []string{"room-background:grant"}, DefaultGranted: true}, + {Code: "user-level:grant", Label: "财富/VIP等级下发", Group: "资源与发放", Capabilities: []string{"user-level:grant"}, DefaultGranted: true}, + {Code: "banner:create", Label: "Banner创建", Group: "运营管理", Capabilities: []string{"banner:create"}, DefaultGranted: true}, +} + +// effectivePermissions upgrades the original 18 route-oriented snapshot into the +// 20 independently displayed business capabilities. New snapshots already contain +// catalog codes and pass through unchanged. Conditional legacy closures avoid turning +// a manually reduced old snapshot into broader Banner, VIP or grant access. +func effectivePermissions(stored []string) []string { + stored = normalizePermissions(stored) + storedSet := make(map[string]struct{}, len(stored)) + for _, permission := range stored { + storedSet[permission] = struct{}{} + } + assignable := make(map[string]struct{}, len(permissionCatalog)) + for _, item := range permissionCatalog { + assignable[item.Code] = struct{}{} + } + effective := make([]string, 0, len(permissionCatalog)) + for _, permission := range stored { + if _, ok := assignable[permission]; ok { + effective = append(effective, permission) + } + } + legacyAliases := map[string][]string{ + "app-user:view": {"user:list", "user-ban:list"}, + "app-user:update": {"user:update"}, + "app-user:status": {"user:ban", "user:unban"}, + "host:view": {"host:list"}, + "agency:view": {"agency:list"}, + "bd:view": {"bd:list", "bd-manager:list", "super-admin:list", "team:view"}, + "room:view": {"room:list"}, + "resource-grant:create": {"privilege:grant", "user-title:grant", "room-background:grant"}, + } + for legacy, aliases := range legacyAliases { + if _, ok := storedSet[legacy]; ok { + effective = append(effective, aliases...) + } + } + if containsPermission(storedSet, "resource:view") && containsPermission(storedSet, "resource-grant:view") { + effective = append(effective, "privilege:list") + } + if containsPermission(storedSet, "app-user:level") && containsPermission(storedSet, "vip-config:grant") { + effective = append(effective, "user-level:grant") + } + if containsPermission(storedSet, "app-config:view") && containsPermission(storedSet, "app-config:update") && containsPermission(storedSet, "upload:create") { + effective = append(effective, "banner:create") + } + effective = normalizePermissions(effective) + // A hand-edited/corrupt new snapshot must not bypass the atomic grant bundle. + // Unknown codes and wildcard-looking values were already discarded above. + effectiveSet := make(map[string]struct{}, len(effective)) + for _, permission := range effective { + effectiveSet[permission] = struct{}{} + } + grantBundle := []string{"privilege:grant", "user-title:grant", "room-background:grant"} + completeGrantBundle := true + for _, permission := range grantBundle { + if !containsPermission(effectiveSet, permission) { + completeGrantBundle = false + } + } + if !completeGrantBundle { + filtered := effective[:0] + for _, permission := range effective { + if permission != "privilege:grant" && permission != "user-title:grant" && permission != "room-background:grant" { + filtered = append(filtered, permission) + } + } + effective = filtered + } + return effective +} + +func containsPermission(permissions map[string]struct{}, code string) bool { + _, ok := permissions[code] + return ok +} + +func PermissionCatalog() []PermissionCatalogItem { + items := make([]PermissionCatalogItem, 0, len(permissionCatalog)) + for _, item := range permissionCatalog { + item.Dependencies = append([]string(nil), item.Dependencies...) + item.Capabilities = append([]string(nil), item.Capabilities...) + items = append(items, item) + } + return items +} + +func permissionCapabilityAliases() map[string][]string { + aliases := make(map[string][]string, len(permissionCatalog)) + for _, item := range permissionCatalog { + aliases[item.Code] = item.Capabilities + } + return aliases +} + +// validatePermissionSelection normalizes duplicates/order only after checking every +// code against the fixed catalog and every write dependency against the same snapshot. +// An explicit empty list is valid and represents an account with no business access. +func validatePermissionSelection(permissions []string) ([]string, error) { + normalized := normalizePermissions(permissions) + selected := make(map[string]struct{}, len(normalized)) + assignable := make(map[string]PermissionCatalogItem, len(permissionCatalog)) + for _, item := range permissionCatalog { + assignable[item.Code] = item + } + for _, permission := range normalized { + if _, ok := assignable[permission]; !ok { + return nil, &PermissionValidationError{Permission: permission} + } + selected[permission] = struct{}{} + } + for _, permission := range normalized { + for _, dependency := range assignable[permission].Dependencies { + if _, ok := selected[dependency]; !ok { + return nil, &PermissionValidationError{Permission: permission, Dependency: dependency} + } + } + } + return normalized, nil +} + +// createPermissionSnapshot intentionally keeps omitted and explicit-empty requests +// distinct. Existing credential-creation clients omit the field and retain the full +// legacy snapshot; a permission-aware client may submit [] to create a locked-down +// account that can authenticate but cannot enter any business page. +func createPermissionSnapshot(input CreateInput) ([]string, error) { + if !input.PermissionsSet { + return DefaultPermissionSnapshot(), nil + } + return validatePermissionSelection(input.Permissions) +} + +func (s *Service) GetAccountPermissions(ctx context.Context, appCode string, id uint64) (AccountPermissionView, error) { + appCode = normalizeAppCode(appCode) + if s.db == nil { + return AccountPermissionView{}, errors.New("admin mysql is not configured") + } + if appCode == "" || id == 0 { + return AccountPermissionView{}, ErrInvalidInput + } + var account model.ExternalAdminAccount + err := s.db.WithContext(ctx).Select("id", "permissions_json", "permission_revision").Where("id = ? AND app_code = ?", id, appCode).Take(&account).Error + if errors.Is(err, gorm.ErrRecordNotFound) { + return AccountPermissionView{}, ErrAccountNotFound + } + if err != nil { + return AccountPermissionView{}, err + } + permissions, err := decodePermissions(account.PermissionsJSON) + if err != nil { + return AccountPermissionView{}, err + } + return AccountPermissionView{AccountID: account.ID, Permissions: permissions, Revision: account.PermissionRevision}, nil +} + +func (s *Service) UpdateAccountPermissions(ctx context.Context, appCode string, id uint64, input UpdatePermissionsInput) (PermissionUpdateResult, error) { + appCode = normalizeAppCode(appCode) + if s.db == nil { + return PermissionUpdateResult{}, errors.New("admin mysql is not configured") + } + if appCode == "" || id == 0 || input.ExpectedRevision == 0 { + return PermissionUpdateResult{}, ErrInvalidInput + } + normalized, err := validatePermissionSelection(input.Permissions) + if err != nil { + return PermissionUpdateResult{}, err + } + encoded, err := encodePermissions(normalized) + if err != nil { + return PermissionUpdateResult{}, err + } + + result := PermissionUpdateResult{} + var account model.ExternalAdminAccount + err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + // The account row lock serializes concurrent permission writers and makes the + // old/new audit snapshot match the exact value replaced by this transaction. + if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("id = ? AND app_code = ?", id, appCode).First(&account).Error; err != nil { + return err + } + if account.PermissionRevision != input.ExpectedRevision { + return ErrPermissionConflict + } + previous, err := decodePermissions(account.PermissionsJSON) + if err != nil { + return err + } + result.PreviousPermissions = previous + if reflect.DeepEqual(previous, normalized) { + return nil + } + if err := tx.Model(&account).Updates(map[string]any{ + "permissions_json": encoded, + "permission_revision": account.PermissionRevision + 1, + }).Error; err != nil { + return err + } + // Revocation is committed atomically with the snapshot. No browser can keep a + // still-valid session after a permission reduction or silently retain a broader UI. + if err := revokeAllSessions(tx, account.ID, "permissions_changed", time.Now().UTC().UnixMilli()); err != nil { + return err + } + result.Changed = true + result.SessionsRevoked = true + return nil + }) + if errors.Is(err, gorm.ErrRecordNotFound) { + return PermissionUpdateResult{}, ErrAccountNotFound + } + if errors.Is(err, ErrPermissionConflict) { + return PermissionUpdateResult{}, ErrPermissionConflict + } + if err != nil { + return PermissionUpdateResult{}, err + } + // Clear the transaction-loaded primary key before reloading. Otherwise GORM adds a + // redundant implicit id predicate, which hides the intended App-scope contract and + // makes future key changes harder to reason about. + account = model.ExternalAdminAccount{} + if err := s.db.WithContext(ctx).Where("id = ? AND app_code = ?", id, appCode).First(&account).Error; err != nil { + return PermissionUpdateResult{}, err + } + users, err := s.loadLinkedUsers(ctx, appCode, []int64{account.LinkedAppUserID}) + if err != nil { + return PermissionUpdateResult{}, err + } + result.Account = accountDTO(account, users[account.LinkedAppUserID]) + return result, nil +} + +func permissionValidationMessage(err error) string { + var validationErr *PermissionValidationError + if !errors.As(err, &validationErr) { + return "外管权限配置不正确" + } + permissionLabel, permissionKnown := permissionCatalogLabel(validationErr.Permission) + if !permissionKnown { + // Unsupported raw codes are implementation details and may contain attacker- + // controlled input. Keep the client error stable without reflecting that value. + return "外管权限中包含不支持的权限" + } + if validationErr.Dependency != "" { + dependencyLabel, dependencyKnown := permissionCatalogLabel(validationErr.Dependency) + if !dependencyKnown { + return "外管权限配置不正确" + } + return fmt.Sprintf("权限“%s”需同时选择“%s”", permissionLabel, dependencyLabel) + } + return "外管权限配置不正确" +} + +func permissionCatalogLabel(code string) (string, bool) { + code = strings.TrimSpace(code) + for _, item := range permissionCatalog { + if item.Code == code { + return item.Label, true + } + } + return "", false +} diff --git a/server/admin/internal/modules/externaladmin/permissions_handler.go b/server/admin/internal/modules/externaladmin/permissions_handler.go new file mode 100644 index 00000000..6142a17d --- /dev/null +++ b/server/admin/internal/modules/externaladmin/permissions_handler.go @@ -0,0 +1,122 @@ +package externaladmin + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "strconv" + "strings" + + "hyapp-admin-server/internal/appctx" + "hyapp-admin-server/internal/modules/shared" + "hyapp-admin-server/internal/response" + + "github.com/gin-gonic/gin" +) + +// optionalPermissionSelection preserves the JSON distinction required by account +// creation: omitted keeps the legacy full snapshot, while an explicit [] creates a +// valid account with no business permissions. JSON null is rejected as ambiguous. +type optionalPermissionSelection struct { + Value []string + Set bool +} + +func (selection *optionalPermissionSelection) UnmarshalJSON(body []byte) error { + selection.Set = true + body = bytes.TrimSpace(body) + if bytes.Equal(body, []byte("null")) { + return errors.New("permissions must be an array") + } + var permissions []string + if err := json.Unmarshal(body, &permissions); err != nil { + return err + } + selection.Value = permissions + return nil +} + +type updatePermissionsRequest struct { + Permissions optionalPermissionSelection `json:"permissions"` + ExpectedRevision uint64 `json:"expectedRevision"` +} + +func (h *Handler) ListPermissionCatalog(c *gin.Context) { + items := PermissionCatalog() + response.OK(c, gin.H{"items": items, "total": len(items)}) +} + +func (h *Handler) GetAccountPermissions(c *gin.Context) { + id, ok := parseUint64Param(c, "id") + if !ok { + return + } + permissions, err := h.service.GetAccountPermissions(c.Request.Context(), appctx.FromContext(c.Request.Context()), id) + if errors.Is(err, ErrAccountNotFound) { + response.NotFound(c, "外管用户不存在") + return + } + if errors.Is(err, ErrInvalidInput) { + response.BadRequest(c, "外管用户参数不正确") + return + } + if err != nil { + response.ServerError(c, "获取外管用户权限失败") + return + } + response.OK(c, permissions) +} + +func (h *Handler) UpdateAccountPermissions(c *gin.Context) { + id, ok := parseUint64Param(c, "id") + if !ok { + return + } + var request updatePermissionsRequest + if err := c.ShouldBindJSON(&request); err != nil || !request.Permissions.Set || request.ExpectedRevision == 0 { + response.BadRequest(c, "权限参数不正确") + return + } + result, err := h.service.UpdateAccountPermissions(c.Request.Context(), appctx.FromContext(c.Request.Context()), id, UpdatePermissionsInput{ + Permissions: request.Permissions.Value, ExpectedRevision: request.ExpectedRevision, + }) + if errors.Is(err, ErrInvalidPermissions) { + response.BadRequest(c, permissionValidationMessage(err)) + return + } + if errors.Is(err, ErrInvalidInput) { + response.BadRequest(c, "外管用户参数不正确") + return + } + if errors.Is(err, ErrAccountNotFound) { + response.NotFound(c, "外管用户不存在") + return + } + if errors.Is(err, ErrPermissionConflict) { + response.Conflict(c, "外管用户权限已被其他管理员修改,请刷新后重试") + return + } + if err != nil { + response.ServerError(c, "更新外管用户权限失败") + return + } + shared.OperationLogWithResourceID( + c, + h.audit, + "update-external-admin-user-permissions", + "external_admin_accounts", + strconv.FormatUint(id, 10), + "success", + fmt.Sprintf( + "app_code=%s previous_permissions=%s permissions=%s revision=%d changed=%t sessions_revoked=%t", + result.Account.AppCode, + strings.Join(result.PreviousPermissions, ","), + strings.Join(result.Account.Permissions, ","), + result.Account.PermissionRevision, + result.Changed, + result.SessionsRevoked, + ), + ) + response.OK(c, result.Account) +} diff --git a/server/admin/internal/modules/externaladmin/permissions_test.go b/server/admin/internal/modules/externaladmin/permissions_test.go new file mode 100644 index 00000000..457dbb1e --- /dev/null +++ b/server/admin/internal/modules/externaladmin/permissions_test.go @@ -0,0 +1,294 @@ +package externaladmin + +import ( + "encoding/json" + "errors" + "net/http" + "net/http/httptest" + "reflect" + "strings" + "testing" + + "hyapp-admin-server/internal/appctx" + adminmiddleware "hyapp-admin-server/internal/middleware" + + "github.com/DATA-DOG/go-sqlmock" + "github.com/gin-gonic/gin" +) + +func TestPermissionCatalogMatchesTwentyProductCapabilities(t *testing.T) { + items := PermissionCatalog() + want := []string{ + "user:list", "user:update", "user-ban:list", "user:ban", "user:unban", + "host:list", "agency:list", "bd:list", "bd-manager:list", "super-admin:list", "team:view", + "room:list", "room:update", "privilege:list", "privilege:grant", "pretty-id:grant", + "user-title:grant", "room-background:grant", "user-level:grant", "banner:create", + } + if len(items) != len(want) { + t.Fatalf("catalog count = %d, want %d", len(items), len(want)) + } + for index, item := range items { + if item.Code != want[index] || item.Label == "" || item.Group == "" || !item.DefaultGranted { + t.Fatalf("catalog[%d] = %+v, want code %s with display metadata/default", index, item, want[index]) + } + if !reflect.DeepEqual(item.Capabilities, []string{item.Code}) { + t.Fatalf("catalog capability must be independently addressable: %+v", item) + } + } +} + +func TestPermissionSelectionAllowlistDependenciesAndNormalization(t *testing.T) { + if got, err := validatePermissionSelection(nil); err != nil || len(got) != 0 { + t.Fatalf("explicit empty permissions must be valid: got=%v err=%v", got, err) + } + all := append(DefaultPermissionSnapshot(), " user:list ", "user:list") + got, err := validatePermissionSelection(all) + if err != nil { + t.Fatalf("default permission validation: %v", err) + } + if !reflect.DeepEqual(got, DefaultPermissionSnapshot()) { + t.Fatalf("permissions not deduplicated/sorted: got=%v", got) + } + for _, invalid := range [][]string{ + {"unknown:permission"}, + {"*"}, + {"external-admin:*"}, + {"privilege:grant"}, + {"user-title:grant", "room-background:grant"}, + } { + if _, err := validatePermissionSelection(invalid); !errors.Is(err, ErrInvalidPermissions) { + t.Fatalf("invalid selection %v error = %v", invalid, err) + } + } +} + +func TestPermissionValidationMessagesUseCatalogLabelsWithoutReflectingCodes(t *testing.T) { + _, dependencyErr := validatePermissionSelection([]string{"privilege:grant"}) + dependencyMessage := permissionValidationMessage(dependencyErr) + if !strings.Contains(dependencyMessage, "特权道具发放") || !strings.Contains(dependencyMessage, "用户称号下发") || strings.Contains(dependencyMessage, "privilege:grant") { + t.Fatalf("dependency message leaked internal code: %q", dependencyMessage) + } + _, unknownErr := validatePermissionSelection([]string{"attacker:controlled"}) + unknownMessage := permissionValidationMessage(unknownErr) + if unknownMessage != "外管权限中包含不支持的权限" || strings.Contains(unknownMessage, "attacker") { + t.Fatalf("unknown message reflected input: %q", unknownMessage) + } +} + +func TestEffectivePermissionsSafelyUpgradesLegacyAndRejectsCorruptSnapshots(t *testing.T) { + legacy := []string{ + "app-user:view", "app-user:update", "app-user:status", "app-user:level", + "host:view", "agency:view", "bd:view", "room:view", "room:update", + "resource:view", "resource-grant:view", "resource-grant:create", + "pretty-id:view", "pretty-id:grant", "app-config:view", "app-config:update", + "vip-config:grant", "upload:create", + } + if got := effectivePermissions(legacy); !reflect.DeepEqual(got, DefaultPermissionSnapshot()) { + t.Fatalf("legacy default did not expand to full 20: got=%v want=%v", got, DefaultPermissionSnapshot()) + } + got := effectivePermissions([]string{"user:list", "privilege:grant", "unknown:permission", "*", "external-admin:*"}) + if !reflect.DeepEqual(got, []string{"user:list"}) { + t.Fatalf("corrupt new snapshot must remove incomplete bundle/unknowns: %v", got) + } + got = effectivePermissions([]string{"app-config:view", "app-config:update", "app-user:level", "resource:view"}) + if len(got) != 0 { + t.Fatalf("incomplete legacy closures must fail closed: %v", got) + } +} + +func TestCreatePermissionFieldDistinguishesOmittedEmptyAndNull(t *testing.T) { + var omitted createAccountRequest + if err := json.Unmarshal([]byte(`{"targetUserId":"1","username":"operator","password":"password"}`), &omitted); err != nil { + t.Fatalf("decode omitted: %v", err) + } + if omitted.Permissions.Set { + t.Fatal("omitted permissions must keep legacy default") + } + var empty createAccountRequest + if err := json.Unmarshal([]byte(`{"targetUserId":"1","username":"operator","password":"password","permissions":[]}`), &empty); err != nil { + t.Fatalf("decode empty: %v", err) + } + if !empty.Permissions.Set || len(empty.Permissions.Value) != 0 { + t.Fatalf("explicit [] was not preserved: %+v", empty.Permissions) + } + var nullValue createAccountRequest + if err := json.Unmarshal([]byte(`{"targetUserId":"1","username":"operator","password":"password","permissions":null}`), &nullValue); err == nil { + t.Fatal("permissions:null must be rejected as ambiguous") + } +} + +func TestCreatePermissionSnapshotKeepsOmittedAndExplicitEmptyDistinct(t *testing.T) { + omitted, err := createPermissionSnapshot(CreateInput{}) + if err != nil || !reflect.DeepEqual(omitted, DefaultPermissionSnapshot()) { + t.Fatalf("omitted snapshot=%v err=%v", omitted, err) + } + empty, err := createPermissionSnapshot(CreateInput{PermissionsSet: true, Permissions: []string{}}) + if err != nil || len(empty) != 0 { + t.Fatalf("explicit empty snapshot=%v err=%v", empty, err) + } + if _, err := createPermissionSnapshot(CreateInput{PermissionsSet: true, Permissions: []string{"*"}}); !errors.Is(err, ErrInvalidPermissions) { + t.Fatalf("explicit wildcard error=%v", err) + } +} + +func TestCreateAccountRequiresCredentialAndPermissionDelegationCapabilities(t *testing.T) { + gin.SetMode(gin.TestMode) + tests := []struct { + name string + permissions []string + wantStatus int + }{ + {name: "create alone cannot delegate default full snapshot", permissions: []string{"external-admin-user:create"}, wantStatus: http.StatusForbidden}, + {name: "delegation alone cannot create credential", permissions: []string{"external-admin-user:permissions"}, wantStatus: http.StatusForbidden}, + {name: "both capabilities reach request validation", permissions: []string{"external-admin-user:create", "external-admin-user:permissions"}, wantStatus: http.StatusBadRequest}, + } + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + engine := gin.New() + engine.Use(func(c *gin.Context) { + c.Set(adminmiddleware.ContextPermissions, testCase.permissions) + c.Next() + }) + RegisterAdminRoutes(engine.Group(""), &Handler{service: NewService(nil, nil, Config{})}) + request := httptest.NewRequest(http.MethodPost, "/admin/external-admin-users", strings.NewReader(`{}`)) + request.Header.Set("Content-Type", "application/json") + recorder := httptest.NewRecorder() + engine.ServeHTTP(recorder, request) + if recorder.Code != testCase.wantStatus { + t.Fatalf("permissions=%v status=%d body=%s", testCase.permissions, recorder.Code, recorder.Body.String()) + } + }) + } + + // Handler-level defense must also reject omitted permissions when a caller + // bypasses the standard route middleware during a future refactor. + engine := gin.New() + engine.POST("/direct", (&Handler{service: NewService(nil, nil, Config{})}).CreateAccount) + recorder := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodPost, "/direct", strings.NewReader(`{"targetUserId":"1","username":"operator","password":"password1"}`)) + request.Header.Set("Content-Type", "application/json") + engine.ServeHTTP(recorder, request) + if recorder.Code != http.StatusForbidden { + t.Fatalf("direct omitted-permission create status=%d body=%s", recorder.Code, recorder.Body.String()) + } +} + +func TestGetAccountPermissionsIsScopedToAppAndReturnsRevision(t *testing.T) { + service, adminMock, userMock, cleanup := newAccountMutationFixture(t) + defer cleanup() + adminMock.ExpectQuery("SELECT `id`,`permissions_json`,`permission_revision` FROM `external_admin_accounts` WHERE id = \\? AND app_code = \\? LIMIT \\?"). + WithArgs(uint64(7), "fami", 1). + WillReturnRows(sqlmock.NewRows([]string{"id", "permissions_json", "permission_revision"}).AddRow(7, `["user:update","user:list"]`, 9)) + + view, err := service.GetAccountPermissions(t.Context(), " FAMI ", 7) + if err != nil { + t.Fatalf("get permissions: %v", err) + } + if view.AccountID != 7 || view.Revision != 9 || !reflect.DeepEqual(view.Permissions, []string{"user:list", "user:update"}) { + t.Fatalf("permission view=%+v", view) + } + assertAccountMutationExpectations(t, adminMock, userMock) +} + +func TestUpdatePermissionsUsesRevisionAndRevokesSessionsAtomically(t *testing.T) { + service, adminMock, userMock, cleanup := newAccountMutationFixture(t) + defer cleanup() + adminMock.ExpectBegin() + adminMock.ExpectQuery("SELECT \\* FROM `external_admin_accounts` WHERE id = \\? AND app_code = \\?"). + WithArgs(uint64(7), "fami", 1).WillReturnRows(permissionAccountRows(4, `["user:list"]`)) + adminMock.ExpectExec("UPDATE `external_admin_accounts` SET .*permission_revision.*permissions_json.* WHERE `id` = \\?"). + WillReturnResult(sqlmock.NewResult(0, 1)) + adminMock.ExpectExec("UPDATE `external_admin_sessions` SET .*revoke_reason.*revoked_at_ms.* WHERE account_id = \\? AND revoked_at_ms = 0"). + WithArgs("permissions_changed", sqlmock.AnyArg(), uint64(7)).WillReturnResult(sqlmock.NewResult(0, 2)) + adminMock.ExpectCommit() + adminMock.ExpectQuery("SELECT \\* FROM `external_admin_accounts` WHERE id = \\? AND app_code = \\?"). + WithArgs(uint64(7), "fami", 1).WillReturnRows(permissionAccountRows(5, `["user:list","user:update"]`)) + expectPermissionLinkedUser(userMock) + + result, err := service.UpdateAccountPermissions(t.Context(), "fami", 7, UpdatePermissionsInput{ + Permissions: []string{"user:update", "user:list", "user:update"}, ExpectedRevision: 4, + }) + if err != nil { + t.Fatalf("update permissions: %v", err) + } + if !result.Changed || !result.SessionsRevoked || result.Account.PermissionRevision != 5 || !reflect.DeepEqual(result.PreviousPermissions, []string{"user:list"}) { + t.Fatalf("unexpected update result: %+v", result) + } + assertAccountMutationExpectations(t, adminMock, userMock) +} + +func TestUpdatePermissionsRejectsStaleRevisionWithoutWriting(t *testing.T) { + service, adminMock, userMock, cleanup := newAccountMutationFixture(t) + defer cleanup() + adminMock.ExpectBegin() + adminMock.ExpectQuery("SELECT \\* FROM `external_admin_accounts` WHERE id = \\? AND app_code = \\?"). + WithArgs(uint64(7), "fami", 1).WillReturnRows(permissionAccountRows(5, `["user:list"]`)) + adminMock.ExpectRollback() + + _, err := service.UpdateAccountPermissions(t.Context(), "fami", 7, UpdatePermissionsInput{ + Permissions: []string{"user:list", "user:update"}, ExpectedRevision: 4, + }) + if !errors.Is(err, ErrPermissionConflict) { + t.Fatalf("stale revision error = %v", err) + } + assertAccountMutationExpectations(t, adminMock, userMock) +} + +func TestUpdatePermissionsNoopIsIdempotentWithoutRevisionOrSessionChange(t *testing.T) { + service, adminMock, userMock, cleanup := newAccountMutationFixture(t) + defer cleanup() + adminMock.ExpectBegin() + adminMock.ExpectQuery("SELECT \\* FROM `external_admin_accounts` WHERE id = \\? AND app_code = \\?"). + WithArgs(uint64(7), "fami", 1).WillReturnRows(permissionAccountRows(6, `["user:list"]`)) + adminMock.ExpectCommit() + adminMock.ExpectQuery("SELECT \\* FROM `external_admin_accounts` WHERE id = \\? AND app_code = \\?"). + WithArgs(uint64(7), "fami", 1).WillReturnRows(permissionAccountRows(6, `["user:list"]`)) + expectPermissionLinkedUser(userMock) + + result, err := service.UpdateAccountPermissions(t.Context(), "fami", 7, UpdatePermissionsInput{ + Permissions: []string{" user:list ", "user:list"}, ExpectedRevision: 6, + }) + if err != nil || result.Changed || result.SessionsRevoked || result.Account.PermissionRevision != 6 { + t.Fatalf("noop result=%+v err=%v", result, err) + } + assertAccountMutationExpectations(t, adminMock, userMock) +} + +func TestUpdatePermissionsHandlerMapsRevisionConflictTo409(t *testing.T) { + service, adminMock, userMock, cleanup := newAccountMutationFixture(t) + defer cleanup() + adminMock.ExpectBegin() + adminMock.ExpectQuery("SELECT \\* FROM `external_admin_accounts` WHERE id = \\? AND app_code = \\?"). + WithArgs(uint64(7), "fami", 1).WillReturnRows(permissionAccountRows(3, `["user:list"]`)) + adminMock.ExpectRollback() + + gin.SetMode(gin.TestMode) + engine := gin.New() + engine.PUT("/accounts/:id", func(c *gin.Context) { + c.Request = c.Request.WithContext(appctx.WithContext(c.Request.Context(), "fami")) + c.Next() + }, (&Handler{service: service}).UpdateAccountPermissions) + request := httptest.NewRequest(http.MethodPut, "/accounts/7", strings.NewReader(`{"permissions":["user:list"],"expectedRevision":2}`)) + request.Header.Set("Content-Type", "application/json") + recorder := httptest.NewRecorder() + engine.ServeHTTP(recorder, request) + if recorder.Code != http.StatusConflict { + t.Fatalf("status=%d body=%s", recorder.Code, recorder.Body.String()) + } + assertAccountMutationExpectations(t, adminMock, userMock) +} + +func permissionAccountRows(revision uint64, permissions string) *sqlmock.Rows { + return sqlmock.NewRows([]string{ + "id", "app_code", "linked_app_user_id", "username", "password_hash", "permissions_json", "permission_revision", "status", + "password_change_required", "failed_login_count", "locked_until_ms", "created_by_admin_id", "created_at_ms", "updated_at_ms", + }).AddRow(7, "fami", 9001, "operator", "hash", permissions, revision, "active", false, 0, 0, 1, 1, 1) +} + +func expectPermissionLinkedUser(userMock sqlmock.Sqlmock) { + userMock.ExpectQuery("SELECT u.user_id,"). + WithArgs(sqlmock.AnyArg(), sqlmock.AnyArg(), "fami", int64(9001)). + WillReturnRows(sqlmock.NewRows([]string{ + "user_id", "current_display_user_id", "default_display_user_id", "pretty_display_user_id", "pretty_id", "username", "avatar", "status", + }).AddRow(9001, "123456", "654321", "8888", "8888", "linked-user", "avatar", "active")) +} diff --git a/server/admin/internal/modules/externaladmin/rate_limit_test.go b/server/admin/internal/modules/externaladmin/rate_limit_test.go new file mode 100644 index 00000000..5c6aa719 --- /dev/null +++ b/server/admin/internal/modules/externaladmin/rate_limit_test.go @@ -0,0 +1,180 @@ +package externaladmin + +import ( + "context" + "errors" + "net/http" + "net/http/httptest" + "strings" + "testing" + "time" + + "hyapp-admin-server/internal/cache" + + "github.com/gin-gonic/gin" + "gorm.io/gorm" +) + +type allowFixedWindowLimiter struct{} + +func (allowFixedWindowLimiter) ConsumeFixedWindow(context.Context, time.Duration, []cache.FixedWindowRule) (cache.FixedWindowDecision, error) { + return cache.FixedWindowDecision{Allowed: true}, nil +} + +type recordingFixedWindowLimiter struct { + decision cache.FixedWindowDecision + err error + calls int + window time.Duration + rules []cache.FixedWindowRule + batches [][]cache.FixedWindowRule + deadlineSet bool + deadlineIn time.Duration +} + +func (limiter *recordingFixedWindowLimiter) ConsumeFixedWindow(ctx context.Context, window time.Duration, rules []cache.FixedWindowRule) (cache.FixedWindowDecision, error) { + limiter.calls++ + limiter.window = window + limiter.rules = append([]cache.FixedWindowRule(nil), rules...) + limiter.batches = append(limiter.batches, append([]cache.FixedWindowRule(nil), rules...)) + deadline, ok := ctx.Deadline() + limiter.deadlineSet = ok + if ok { + limiter.deadlineIn = time.Until(deadline) + } + return limiter.decision, limiter.err +} + +func TestLoginRateLimiterUsesTrustedHashedLayersBeforeAccountResolution(t *testing.T) { + limiter := &recordingFixedWindowLimiter{decision: cache.FixedWindowDecision{Allowed: true}} + service := NewService(&gorm.DB{}, nil, Config{LoginRateLimit: LoginRateLimitConfig{ + Window: time.Minute, SystemLimit: 300, AppLimit: 120, IPLimit: 30, IdentityLimit: 10, + }}) + service.limiter = limiter + + // Empty password is invalid, but this syntactically valid attempt must consume + // distributed counters before dummy bcrypt/input rejection. + _, err := service.Login(t.Context(), LoginInput{Username: "Operator", IP: "203.0.113.44"}) + if !errors.Is(err, ErrInvalidCredentials) { + t.Fatalf("login error = %v", err) + } + if limiter.calls != 1 || limiter.window != time.Minute || len(limiter.rules) != 3 { + t.Fatalf("limiter call=%d window=%s rules=%+v", limiter.calls, limiter.window, limiter.rules) + } + if !limiter.deadlineSet || limiter.deadlineIn <= 0 || limiter.deadlineIn > loginLimiterTimeout+25*time.Millisecond { + t.Fatalf("independent limiter deadline = %s set=%t", limiter.deadlineIn, limiter.deadlineSet) + } + wantLimits := []uint64{300, 30, 10} + for index, rule := range limiter.rules { + if rule.Limit != wantLimits[index] { + t.Fatalf("rule %d limit=%d", index, rule.Limit) + } + if !strings.Contains(rule.Key, loginLimiterClusterTag) { + t.Fatalf("rule %d is not Redis Cluster-safe: %s", index, rule.Key) + } + for _, secret := range []string{"operator", "203.0.113.44"} { + if strings.Contains(rule.Key, secret) { + t.Fatalf("rule %d leaks %q: %s", index, secret, rule.Key) + } + } + } + if limiter.rules[0].Key != "rate:{external-login}:system" { + t.Fatalf("system-global key must not vary by App: %s", limiter.rules[0].Key) + } + if len(loginRateLimitDigest("fami")) != 32 || loginRateLimitDigest("fami") == loginRateLimitDigest("lalu") { + t.Fatal("rate-limit identifiers must use a truncated SHA-256 digest") + } +} + +func TestLoginRateLimitDenialAndRedisFailurePrecedeAllDatabaseWork(t *testing.T) { + t.Run("limited", func(t *testing.T) { + limiter := &recordingFixedWindowLimiter{decision: cache.FixedWindowDecision{Allowed: false, RetryAfter: 1500 * time.Millisecond}} + service := NewService(nil, nil, Config{}) + service.limiter = limiter + _, err := service.Login(t.Context(), LoginInput{Username: "operator", Password: "password", IP: "127.0.0.1"}) + var rateErr *LoginRateLimitError + if !errors.As(err, &rateErr) || rateErr.RetryAfter != 1500*time.Millisecond { + t.Fatalf("rate error = %#v", err) + } + }) + + t.Run("redis unavailable", func(t *testing.T) { + limiter := &recordingFixedWindowLimiter{err: errors.New("redis down")} + service := NewService(nil, nil, Config{}) + service.limiter = limiter + _, err := service.Login(t.Context(), LoginInput{Username: "operator", Password: "password", IP: "127.0.0.1"}) + if !errors.Is(err, ErrLoginLimiterFailed) { + t.Fatalf("login error = %v", err) + } + }) + + t.Run("missing redis", func(t *testing.T) { + service := NewService(nil, nil, Config{}) + _, err := service.Login(t.Context(), LoginInput{Username: "operator", Password: "password", IP: "127.0.0.1"}) + if !errors.Is(err, ErrLoginLimiterFailed) { + t.Fatalf("login error = %v", err) + } + }) +} + +func TestLoginHandlerReturns429RetryAfterAnd503OnLimiterFailure(t *testing.T) { + for _, testCase := range []struct { + name string + limiter *recordingFixedWindowLimiter + wantStatus int + wantRetry string + body string + }{ + { + name: "limited", limiter: &recordingFixedWindowLimiter{decision: cache.FixedWindowDecision{Allowed: false, RetryAfter: 1500 * time.Millisecond}}, + wantStatus: http.StatusTooManyRequests, wantRetry: "2", body: `{"account":"operator","password":"password"}`, + }, + { + name: "valid empty json still counted", limiter: &recordingFixedWindowLimiter{decision: cache.FixedWindowDecision{Allowed: false, RetryAfter: time.Second}}, + wantStatus: http.StatusTooManyRequests, wantRetry: "1", body: `{}`, + }, + { + name: "redis unavailable", limiter: &recordingFixedWindowLimiter{err: errors.New("redis down")}, + wantStatus: http.StatusServiceUnavailable, body: `{"account":"operator","password":"password"}`, + }, + } { + t.Run(testCase.name, func(t *testing.T) { + gin.SetMode(gin.TestMode) + engine := gin.New() + handler := New(nil, nil, Config{}, nil, WithLoginRateLimiter(testCase.limiter)) + RegisterExternalRoutes(engine.Group("/api/v1"), handler, BusinessHandlers{}) + request := httptest.NewRequest(http.MethodPost, "/api/v1/external/auth/login", strings.NewReader(testCase.body)) + request.Header.Set("Content-Type", "application/json") + responseRecorder := httptest.NewRecorder() + engine.ServeHTTP(responseRecorder, request) + if responseRecorder.Code != testCase.wantStatus { + t.Fatalf("status=%d body=%s", responseRecorder.Code, responseRecorder.Body.String()) + } + if got := responseRecorder.Header().Get("Retry-After"); got != testCase.wantRetry { + t.Fatalf("Retry-After=%q want=%q", got, testCase.wantRetry) + } + if responseRecorder.Header().Get("Cache-Control") != "no-store" { + t.Fatal("rate-limit auth responses must remain non-cacheable") + } + }) + } +} + +func TestLoginHandlerCapsBodyBeforeDistributedLimiter(t *testing.T) { + limiter := &recordingFixedWindowLimiter{decision: cache.FixedWindowDecision{Allowed: true}} + gin.SetMode(gin.TestMode) + engine := gin.New() + handler := New(nil, nil, Config{}, nil, WithLoginRateLimiter(limiter)) + RegisterExternalRoutes(engine.Group("/api/v1"), handler, BusinessHandlers{}) + body := `{"account":"operator","password":"` + strings.Repeat("x", int(maxLoginBodyBytes)) + `"}` + request := httptest.NewRequest(http.MethodPost, "/api/v1/external/auth/login", strings.NewReader(body)) + request.Header.Set("Content-Type", "application/json") + responseRecorder := httptest.NewRecorder() + engine.ServeHTTP(responseRecorder, request) + if responseRecorder.Code != http.StatusRequestEntityTooLarge { + t.Fatalf("status=%d body=%s", responseRecorder.Code, responseRecorder.Body.String()) + } + if limiter.calls != 0 { + t.Fatalf("oversized, unparseable body reached limiter %d times", limiter.calls) + } +} diff --git a/server/admin/internal/modules/externaladmin/route_permissions_test.go b/server/admin/internal/modules/externaladmin/route_permissions_test.go new file mode 100644 index 00000000..852db09a --- /dev/null +++ b/server/admin/internal/modules/externaladmin/route_permissions_test.go @@ -0,0 +1,112 @@ +package externaladmin + +import ( + "context" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "hyapp-admin-server/internal/appctx" + "hyapp-admin-server/internal/config" + "hyapp-admin-server/internal/integration/walletclient" + adminmiddleware "hyapp-admin-server/internal/middleware" + "hyapp-admin-server/internal/modules/appuser" + "hyapp-admin-server/internal/modules/hostorg" + "hyapp-admin-server/internal/modules/vipconfig" + walletv1 "hyapp.local/api/proto/wallet/v1" + + "github.com/gin-gonic/gin" +) + +func TestExternalBusinessRoutesKeepIndependentPermissionBoundaries(t *testing.T) { + gin.SetMode(gin.TestMode) + engine := gin.New() + engine.Use(func(c *gin.Context) { + // Each request gets exactly one product capability. Allowed reads reach an + // intentionally unconfigured handler and return 500; denied routes must stop + // at the permission middleware with 403 before any dependency is touched. + c.Set(adminmiddleware.ContextPermissions, []string{c.GetHeader("X-Test-Permission")}) + c.Next() + }) + registerBusinessWhitelist(engine.Group(""), &Handler{}, BusinessHandlers{ + AppUser: appuser.New(nil, nil, nil, nil, nil, config.Config{}, nil), + HostOrg: hostorg.New(nil, nil, nil, nil, nil, nil), + }) + + tests := []struct { + name string + method string + path string + permission string + allowed bool + }{ + {name: "BD Manager list accepts its capability", method: http.MethodGet, path: "/admin/managers", permission: "bd-manager:list", allowed: true}, + {name: "BD Manager list rejects Super Admin capability", method: http.MethodGet, path: "/admin/managers", permission: "super-admin:list"}, + {name: "Super Admin list accepts its capability", method: http.MethodGet, path: "/admin/bd-leaders", permission: "super-admin:list", allowed: true}, + {name: "Super Admin list rejects BD Manager capability", method: http.MethodGet, path: "/admin/bd-leaders", permission: "bd-manager:list"}, + {name: "user update can read support list", method: http.MethodGet, path: "/app/users", permission: "user:update", allowed: true}, + {name: "user update cannot ban", method: http.MethodPost, path: "/app/users/9001/ban", permission: "user:update"}, + {name: "user unban can read ban support list", method: http.MethodGet, path: "/app/users/bans", permission: "user:unban", allowed: true}, + } + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + request := httptest.NewRequest(testCase.method, testCase.path, nil) + request.Header.Set("X-Test-Permission", testCase.permission) + recorder := httptest.NewRecorder() + engine.ServeHTTP(recorder, request) + if testCase.allowed && recorder.Code == http.StatusForbidden { + t.Fatalf("permission %s was rejected for %s %s: %s", testCase.permission, testCase.method, testCase.path, recorder.Body.String()) + } + if !testCase.allowed && recorder.Code != http.StatusForbidden { + t.Fatalf("permission %s unexpectedly reached %s %s: status=%d body=%s", testCase.permission, testCase.method, testCase.path, recorder.Code, recorder.Body.String()) + } + }) + } +} + +func TestExternalVIPRoutesUseManagerCenterOwnerPolicySource(t *testing.T) { + gin.SetMode(gin.TestMode) + wallet := &externalVIPRouteWallet{} + engine := gin.New() + engine.Use(func(c *gin.Context) { + c.Request = c.Request.WithContext(appctx.WithContext(c.Request.Context(), "fami")) + c.Set(adminmiddleware.ContextPermissions, []string{"user-level:grant"}) + c.Set(adminmiddleware.ContextRequestID, "external-vip-route-test") + c.Set(adminmiddleware.ContextUserID, uint(77)) + c.Next() + }) + registerBusinessWhitelist(engine.Group(""), &Handler{}, BusinessHandlers{VIPConfig: vipconfig.New(wallet, nil)}) + + vipRequest := httptest.NewRequest(http.MethodPost, "/admin/activity/vip-grants", strings.NewReader(`{"targetUserId":"9001","level":5,"reason":"manual"}`)) + vipRequest.Header.Set("Content-Type", "application/json") + vipRecorder := httptest.NewRecorder() + engine.ServeHTTP(vipRecorder, vipRequest) + if vipRecorder.Code != http.StatusCreated || wallet.vipRequest == nil || wallet.vipRequest.GetGrantSource() != "manager_center" { + t.Fatalf("external VIP route source: status=%d request=%+v body=%s", vipRecorder.Code, wallet.vipRequest, vipRecorder.Body.String()) + } + + trialRequest := httptest.NewRequest(http.MethodPost, "/admin/activity/vip-trial-card-grants", strings.NewReader(`{"targetUserId":"9001","level":5,"durationMs":86400000,"resourceId":99,"reason":"manual"}`)) + trialRequest.Header.Set("Content-Type", "application/json") + trialRecorder := httptest.NewRecorder() + engine.ServeHTTP(trialRecorder, trialRequest) + if trialRecorder.Code != http.StatusCreated || wallet.trialRequest == nil || wallet.trialRequest.GetGrantSource() != "manager_center" { + t.Fatalf("external trial route source: status=%d request=%+v body=%s", trialRecorder.Code, wallet.trialRequest, trialRecorder.Body.String()) + } +} + +type externalVIPRouteWallet struct { + walletclient.Client + vipRequest *walletv1.GrantVipRequest + trialRequest *walletv1.GrantVipTrialCardRequest +} + +func (wallet *externalVIPRouteWallet) GrantVip(_ context.Context, request *walletv1.GrantVipRequest) (*walletv1.GrantVipResponse, error) { + wallet.vipRequest = request + return &walletv1.GrantVipResponse{TransactionId: "vip-route"}, nil +} + +func (wallet *externalVIPRouteWallet) GrantVipTrialCard(_ context.Context, request *walletv1.GrantVipTrialCardRequest) (*walletv1.GrantVipTrialCardResponse, error) { + wallet.trialRequest = request + return &walletv1.GrantVipTrialCardResponse{TrialCard: &walletv1.VipTrialCard{TrialCardId: "trial-route"}}, nil +} diff --git a/server/admin/internal/modules/externaladmin/routes.go b/server/admin/internal/modules/externaladmin/routes.go new file mode 100644 index 00000000..8f713cf0 --- /dev/null +++ b/server/admin/internal/modules/externaladmin/routes.go @@ -0,0 +1,137 @@ +package externaladmin + +import ( + "hyapp-admin-server/internal/middleware" + "hyapp-admin-server/internal/modules/appconfig" + "hyapp-admin-server/internal/modules/appuser" + "hyapp-admin-server/internal/modules/hostorg" + "hyapp-admin-server/internal/modules/prettyid" + "hyapp-admin-server/internal/modules/resource" + "hyapp-admin-server/internal/modules/roomadmin" + "hyapp-admin-server/internal/modules/upload" + "hyapp-admin-server/internal/modules/vipconfig" + + "github.com/gin-gonic/gin" +) + +type BusinessHandlers struct { + AppUser *appuser.Handler + HostOrg *hostorg.Handler + RoomAdmin *roomadmin.Handler + Resource *resource.Handler + PrettyID *prettyid.Handler + AppConfig *appconfig.Handler + VIPConfig *vipconfig.Handler + Upload *upload.Handler +} + +func RegisterAdminRoutes(protected *gin.RouterGroup, h *Handler) { + if protected == nil || h == nil { + return + } + protected.GET("/admin/external-admin-users", middleware.RequirePermission("external-admin-user:view"), h.ListAccounts) + protected.GET("/admin/external-admin-users/permission-catalog", middleware.RequirePermission("external-admin-user:permissions"), h.ListPermissionCatalog) + protected.GET("/admin/external-admin-users/:id/permissions", middleware.RequirePermission("external-admin-user:permissions"), h.GetAccountPermissions) + protected.GET("/admin/external-admin-users/target", middleware.RequirePermission("external-admin-user:create"), h.ResolveTarget) + protected.POST("/admin/external-admin-users", middleware.RequirePermission("external-admin-user:create"), middleware.RequirePermission("external-admin-user:permissions"), h.CreateAccount) + protected.PUT("/admin/external-admin-users/:id/permissions", middleware.RequirePermission("external-admin-user:permissions"), h.UpdateAccountPermissions) + protected.PATCH("/admin/external-admin-users/:id/status", middleware.RequirePermission("external-admin-user:status"), h.SetStatus) + protected.POST("/admin/external-admin-users/:id/password", middleware.RequirePermission("external-admin-user:reset-password"), h.ResetPassword) +} + +func RegisterExternalRoutes(api *gin.RouterGroup, h *Handler, handlers BusinessHandlers) { + if api == nil || h == nil { + return + } + external := api.Group("/external") + auth := external.Group("/auth") + // Credentials, session state and CSRF secrets must never be cached by browsers, + // service workers or intermediary proxies. This middleware runs before session + // auth so 4xx/5xx responses carry the same protection as successful responses. + auth.Use(noStore()) + auth.POST("/login", h.Login) + + protectedAuth := auth.Group("") + // Audit wraps CSRF so forged writes are recorded as failed attempts instead of disappearing + // before the audit middleware gets control. + protectedAuth.Use(h.AuthRequired(), h.Audit(), h.RequireCSRF()) + protectedAuth.GET("/me", h.Me) + protectedAuth.POST("/logout", h.Logout) + protectedAuth.POST("/change-password", h.ChangePassword) + + // Password changes remain available as a self-service action, but they are not a + // business-route gate. Legacy rows may still carry password_change_required=true; + // authorization must therefore depend only on the active session and permissions. + business := external.Group("") + business.Use(h.AuthRequired(), h.Audit(), h.RequireCSRF()) + registerBusinessWhitelist(business, h, handlers) +} + +func noStore() gin.HandlerFunc { + return func(c *gin.Context) { + c.Header("Cache-Control", "no-store") + c.Header("Pragma", "no-cache") + c.Next() + } +} + +func registerBusinessWhitelist(group *gin.RouterGroup, h *Handler, handlers BusinessHandlers) { + // "My team" is not a generic manager-list alias. Its handler derives the root + // manager from the external session and never accepts a client-selected user ID. + group.GET("/admin/my-team/agencies", middleware.RequirePermission("team:view"), h.ListMyTeamAgencies) + if handlers.AppUser != nil { + group.GET("/app/users", middleware.RequireAnyPermission("user:list", "user:update", "user:ban", "user-level:grant"), handlers.AppUser.ListUsers) + group.GET("/app/users/bans", middleware.RequireAnyPermission("user-ban:list", "user:unban"), handlers.AppUser.ListBannedUsers) + // Detail is a support read for each user-targeted action, not a second product + // capability. Any independently assigned user action can resolve its exact target. + group.GET("/app/users/:id", middleware.RequireAnyPermission("user:list", "user:update", "user:ban", "user:unban", "user-level:grant"), handlers.AppUser.GetUser) + group.PATCH("/app/users/:id", middleware.RequirePermission("user:update"), handlers.AppUser.UpdateUser) + group.PUT("/app/users/:id/levels", middleware.RequirePermission("user-level:grant"), handlers.AppUser.AdjustTemporaryLevels) + group.POST("/app/users/:id/ban", middleware.RequirePermission("user:ban"), handlers.AppUser.BanUser) + group.POST("/app/users/:id/unban", middleware.RequirePermission("user:unban"), handlers.AppUser.UnbanUser) + } + if handlers.HostOrg != nil { + group.GET("/admin/hosts", middleware.RequirePermission("host:list"), handlers.HostOrg.ListHosts) + group.GET("/admin/agencies", middleware.RequirePermission("agency:list"), handlers.HostOrg.ListAgencies) + group.GET("/admin/bds", middleware.RequirePermission("bd:list"), handlers.HostOrg.ListBDs) + // The shared host-org API names are historical: external BD Manager uses + // /managers, while the Super Admin projection uses /bd-leaders. + group.GET("/admin/bd-leaders", middleware.RequirePermission("super-admin:list"), handlers.HostOrg.ListBDLeaders) + group.GET("/admin/managers", middleware.RequirePermission("bd-manager:list"), handlers.HostOrg.ListManagers) + } + if handlers.RoomAdmin != nil { + group.GET("/admin/rooms", middleware.RequireAnyPermission("room:list", "room:update"), handlers.RoomAdmin.ListRooms) + group.PATCH("/admin/rooms/:room_id", middleware.RequirePermission("room:update"), handlers.RoomAdmin.UpdateRoom) + } + if handlers.Resource != nil { + // Resource owner data cannot yet classify generic entitlements into the three + // product labels below. The assignment validator therefore keeps them atomic, + // and the route repeats all three checks so corrupt DB JSON still fails closed. + group.GET("/admin/resources", middleware.RequirePermission("privilege:grant"), middleware.RequirePermission("user-title:grant"), middleware.RequirePermission("room-background:grant"), handlers.Resource.ListExternalGrantResources) + group.GET("/admin/resource-grants", middleware.RequirePermission("privilege:list"), handlers.Resource.ListResourceGrants) + group.GET("/admin/resource-grants/target", middleware.RequireAnyPermission("privilege:grant", "pretty-id:grant", "user-title:grant", "room-background:grant"), handlers.Resource.LookupResourceGrantTarget) + group.POST("/admin/resource-grants/resource", middleware.RequirePermission("privilege:grant"), middleware.RequirePermission("user-title:grant"), middleware.RequirePermission("room-background:grant"), handlers.Resource.GrantExternalResource) + // External UI never uses group grants. Without an owner-level semantic category, + // a mixed group cannot be authorized safely, so it is intentionally not exposed. + } + if handlers.PrettyID != nil { + group.GET("/admin/users/pretty-ids", middleware.RequirePermission("pretty-id:grant"), handlers.PrettyID.ListIDs) + group.POST("/admin/users/pretty-ids/grant", middleware.RequirePermission("pretty-id:grant"), handlers.PrettyID.Grant) + } + if handlers.AppConfig != nil { + group.GET("/admin/app-config/banners", middleware.RequirePermission("banner:create"), handlers.AppConfig.ListBanners) + group.POST("/admin/app-config/banners", middleware.RequirePermission("banner:create"), handlers.AppConfig.CreateBanner) + } + if handlers.VIPConfig != nil { + // Grant mode and level IDs are owner-service facts. Read them with the same narrowly scoped + // grant permission so the portal can select direct-VIP vs trial-card without config write access. + group.GET("/admin/activity/vip-program", middleware.RequirePermission("user-level:grant"), handlers.VIPConfig.GetProgram) + group.GET("/admin/activity/vip-levels", middleware.RequirePermission("user-level:grant"), handlers.VIPConfig.ListLevels) + group.POST("/admin/activity/vip-trial-card-grants", middleware.RequirePermission("user-level:grant"), handlers.VIPConfig.GrantExternalVIPTrialCard) + group.POST("/admin/activity/vip-grants", middleware.RequirePermission("user-level:grant"), handlers.VIPConfig.GrantExternalVIP) + } + if handlers.Upload != nil { + // Banner/avatar forms need a real upload endpoint; no other file-management route is exposed. + group.POST("/admin/files/image/upload", middleware.RequirePermission("banner:create"), handlers.Upload.UploadImage) + } +} diff --git a/server/admin/internal/modules/externaladmin/routes_security_test.go b/server/admin/internal/modules/externaladmin/routes_security_test.go new file mode 100644 index 00000000..76ca970d --- /dev/null +++ b/server/admin/internal/modules/externaladmin/routes_security_test.go @@ -0,0 +1,58 @@ +package externaladmin + +import ( + "bytes" + "net/http" + "net/http/httptest" + "testing" + + "github.com/gin-gonic/gin" +) + +func TestExternalAuthResponsesAlwaysDisableCachingIncludingErrors(t *testing.T) { + gin.SetMode(gin.TestMode) + engine := gin.New() + RegisterExternalRoutes(engine.Group("/api/v1"), New(nil, nil, Config{}, nil), BusinessHandlers{}) + + tests := []struct { + name string + method string + path string + body string + }{ + {name: "login validation error", method: http.MethodPost, path: "/api/v1/external/auth/login", body: `{}`}, + {name: "me auth error", method: http.MethodGet, path: "/api/v1/external/auth/me"}, + {name: "logout auth error", method: http.MethodPost, path: "/api/v1/external/auth/logout"}, + {name: "change password auth error", method: http.MethodPost, path: "/api/v1/external/auth/change-password", body: `{}`}, + } + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + request := httptest.NewRequest(testCase.method, testCase.path, bytes.NewBufferString(testCase.body)) + request.Header.Set("Content-Type", "application/json") + responseRecorder := httptest.NewRecorder() + engine.ServeHTTP(responseRecorder, request) + if responseRecorder.Code < http.StatusBadRequest { + t.Fatalf("expected error response, status=%d body=%s", responseRecorder.Code, responseRecorder.Body.String()) + } + if got := responseRecorder.Header().Get("Cache-Control"); got != "no-store" { + t.Fatalf("Cache-Control = %q", got) + } + if got := responseRecorder.Header().Get("Pragma"); got != "no-cache" { + t.Fatalf("Pragma = %q", got) + } + }) + } +} + +func TestExternalAuthDoesNotExposeAppCatalogBeforeLogin(t *testing.T) { + gin.SetMode(gin.TestMode) + engine := gin.New() + RegisterExternalRoutes(engine.Group("/api/v1"), New(nil, nil, Config{}, nil), BusinessHandlers{}) + + request := httptest.NewRequest(http.MethodGet, "/api/v1/external/auth/apps", nil) + responseRecorder := httptest.NewRecorder() + engine.ServeHTTP(responseRecorder, request) + if responseRecorder.Code != http.StatusNotFound { + t.Fatalf("anonymous App catalog status=%d body=%s", responseRecorder.Code, responseRecorder.Body.String()) + } +} diff --git a/server/admin/internal/modules/externaladmin/service.go b/server/admin/internal/modules/externaladmin/service.go new file mode 100644 index 00000000..ab42fc82 --- /dev/null +++ b/server/admin/internal/modules/externaladmin/service.go @@ -0,0 +1,881 @@ +package externaladmin + +import ( + "context" + "crypto/sha256" + "database/sql" + "encoding/hex" + "errors" + "fmt" + "strconv" + "strings" + "time" + + "hyapp-admin-server/internal/appctx" + "hyapp-admin-server/internal/cache" + "hyapp-admin-server/internal/model" + "hyapp-admin-server/internal/modules/shared" + "hyapp-admin-server/internal/security" + + mysqlDriver "github.com/go-sql-driver/mysql" + "gorm.io/gorm" + "gorm.io/gorm/clause" +) + +const ( + lastSeenWriteInterval = 5 * time.Minute + loginLimiterTimeout = 200 * time.Millisecond + loginLimiterClusterTag = "{external-login}" +) + +type Service struct { + db *gorm.DB + userDB *sql.DB + cfg Config + dummyHash string + limiter FixedWindowLimiter +} + +func NewService(db *gorm.DB, userDB *sql.DB, cfg Config) *Service { + if cfg.SessionTTL <= 0 { + cfg.SessionTTL = 12 * time.Hour + } + if cfg.MaxLoginFailures == 0 { + cfg.MaxLoginFailures = 5 + } + if cfg.LockDuration <= 0 { + cfg.LockDuration = 15 * time.Minute + } + if cfg.LoginRateLimit.Window <= 0 { + cfg.LoginRateLimit.Window = 60 * time.Second + } + if cfg.LoginRateLimit.SystemLimit == 0 { + cfg.LoginRateLimit.SystemLimit = 300 + } + if cfg.LoginRateLimit.AppLimit == 0 { + cfg.LoginRateLimit.AppLimit = 120 + } + if cfg.LoginRateLimit.IPLimit == 0 { + cfg.LoginRateLimit.IPLimit = 30 + } + if cfg.LoginRateLimit.IdentityLimit == 0 { + cfg.LoginRateLimit.IdentityLimit = 10 + } + dummyHash, _ := security.HashPassword("external-login-dummy-password") + return &Service{db: db, userDB: userDB, cfg: cfg, dummyHash: dummyHash} +} + +func (s *Service) ResolveTarget(ctx context.Context, appCode string, target string) (LinkedUser, error) { + appCode = normalizeAppCode(appCode) + target = strings.TrimSpace(target) + if appCode == "" || target == "" || s.userDB == nil { + return LinkedUser{}, ErrInvalidInput + } + userID, matched, err := shared.ResolveExactUserID(ctx, s.userDB, appCode, target, time.Now().UTC().UnixMilli()) + if err != nil { + return LinkedUser{}, err + } + if !matched { + return LinkedUser{}, ErrTargetNotFound + } + users, err := s.loadLinkedUsers(ctx, appCode, []int64{userID}) + if err != nil { + return LinkedUser{}, err + } + user, ok := users[userID] + if !ok { + return LinkedUser{}, ErrTargetNotFound + } + // ResolveExactUserID keeps nickname fallback for generic admin forms. External-account creation + // accepts only an exact long/short/pretty ID so an ambiguous nickname can never bind credentials. + if !matchesExactIdentity(user, target) { + return LinkedUser{}, ErrTargetNotFound + } + return user, nil +} + +func (s *Service) ListAccounts(ctx context.Context, input ListInput) (ListResult, error) { + if s.db == nil { + return ListResult{}, errors.New("admin mysql is not configured") + } + input.AppCode = normalizeAppCode(input.AppCode) + input.Page, input.PageSize = normalizePage(input.Page, input.PageSize) + query := s.db.WithContext(ctx).Model(&model.ExternalAdminAccount{}).Where("app_code = ?", input.AppCode) + if status := normalizeStatus(input.Status); status != "" { + query = query.Where("status = ?", status) + } + if keyword := strings.TrimSpace(input.Keyword); keyword != "" { + like := "%" + keyword + "%" + linkedUserID := int64(0) + if user, resolveErr := s.ResolveTarget(ctx, input.AppCode, keyword); resolveErr == nil { + linkedUserID = user.UserID + } else if userID, parseErr := strconv.ParseInt(keyword, 10, 64); parseErr == nil && userID > 0 { + linkedUserID = userID + } + if linkedUserID > 0 { + query = query.Where("username LIKE ? OR linked_app_user_id = ?", like, linkedUserID) + } else { + query = query.Where("username LIKE ?", like) + } + } + var total int64 + if err := query.Count(&total).Error; err != nil { + return ListResult{}, err + } + accounts := []model.ExternalAdminAccount{} + if err := query.Order("updated_at_ms DESC, id DESC").Offset((input.Page - 1) * input.PageSize).Limit(input.PageSize).Find(&accounts).Error; err != nil { + return ListResult{}, err + } + userIDs := make([]int64, 0, len(accounts)) + for _, account := range accounts { + userIDs = append(userIDs, account.LinkedAppUserID) + } + users, err := s.loadLinkedUsers(ctx, input.AppCode, userIDs) + if err != nil { + return ListResult{}, err + } + items := make([]AccountDTO, 0, len(accounts)) + for _, account := range accounts { + items = append(items, accountDTO(account, users[account.LinkedAppUserID])) + } + return ListResult{Items: items, Page: input.Page, PageSize: input.PageSize, Total: total}, nil +} + +func (s *Service) FindAccountByLinkedUser(ctx context.Context, appCode string, linkedUser LinkedUser) (*AccountDTO, error) { + if s.db == nil || linkedUser.UserID <= 0 { + return nil, ErrInvalidInput + } + var account model.ExternalAdminAccount + err := s.db.WithContext(ctx).Where("app_code = ? AND linked_app_user_id = ?", normalizeAppCode(appCode), linkedUser.UserID).First(&account).Error + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + if err != nil { + return nil, err + } + dto := accountDTO(account, linkedUser) + return &dto, nil +} + +func (s *Service) CreateAccount(ctx context.Context, input CreateInput) (AccountDTO, error) { + if s.db == nil { + return AccountDTO{}, errors.New("admin mysql is not configured") + } + input.AppCode = normalizeAppCode(input.AppCode) + input.Username = normalizeUsername(input.Username) + if input.AppCode == "" || !validUsername(input.Username) || input.CreatedByAdminID == 0 { + return AccountDTO{}, ErrInvalidInput + } + if err := validatePassword(input.Password); err != nil { + return AccountDTO{}, err + } + permissions, err := createPermissionSnapshot(input) + if err != nil { + return AccountDTO{}, err + } + // Login has no client-selected App. Check the normalized username globally before + // doing an owner-DB lookup or bcrypt work; the global unique index remains the + // authoritative race-safe guard if two administrators create it concurrently. + var existing model.ExternalAdminAccount + err = s.db.WithContext(ctx).Select("id").Where("username = ?", input.Username).Take(&existing).Error + if err == nil { + return AccountDTO{}, ErrAccountConflict + } + if !errors.Is(err, gorm.ErrRecordNotFound) { + return AccountDTO{}, err + } + if _, err := s.findActiveApp(ctx, input.AppCode); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return AccountDTO{}, ErrInvalidInput + } + return AccountDTO{}, err + } + linkedUser, err := s.ResolveTarget(ctx, input.AppCode, input.TargetUserID) + if err != nil { + return AccountDTO{}, err + } + passwordHash, err := security.HashPasswordWithoutMinimum(input.Password) + if err != nil { + return AccountDTO{}, ErrInvalidInput + } + permissionsJSON, err := encodePermissions(permissions) + if err != nil { + return AccountDTO{}, err + } + account := model.ExternalAdminAccount{ + AppCode: input.AppCode, + LinkedAppUserID: linkedUser.UserID, + Username: input.Username, + PasswordHash: passwordHash, + PermissionsJSON: permissionsJSON, + PermissionRevision: 1, + Status: model.ExternalAdminStatusActive, + CreatedByAdminID: input.CreatedByAdminID, + } + // The legacy model/database default is true, so assigning Go's false zero value + // is not enough: GORM substitutes the default during Create. Clear the marker in + // the same transaction so a rolling-release request handled by an older instance + // cannot revive the retired first-login gate for a newly created account. + err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + if err := tx.Create(&account).Error; err != nil { + return err + } + if err := tx.Model(&account).UpdateColumn("password_change_required", false).Error; err != nil { + return err + } + account.PasswordChangeRequired = false + return nil + }) + if err != nil { + if isDuplicateKey(err) { + return AccountDTO{}, ErrAccountConflict + } + return AccountDTO{}, err + } + return accountDTO(account, linkedUser), nil +} + +func (s *Service) SetStatus(ctx context.Context, appCode string, id uint64, status string) (AccountDTO, error) { + appCode = normalizeAppCode(appCode) + status = normalizeStatus(status) + if id == 0 || status == "" { + return AccountDTO{}, ErrInvalidInput + } + var account model.ExternalAdminAccount + err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("id = ? AND app_code = ?", id, appCode).First(&account).Error; err != nil { + return err + } + updates := map[string]any{"status": status} + if status == model.ExternalAdminStatusActive { + updates["failed_login_count"] = 0 + updates["locked_until_ms"] = 0 + } + if err := tx.Model(&account).Updates(updates).Error; err != nil { + return err + } + if status == model.ExternalAdminStatusDisabled { + return revokeAllSessions(tx, account.ID, "account_disabled", time.Now().UTC().UnixMilli()) + } + return nil + }) + if errors.Is(err, gorm.ErrRecordNotFound) { + return AccountDTO{}, ErrAccountNotFound + } + if err != nil { + return AccountDTO{}, err + } + if err := s.db.WithContext(ctx).Where("id = ?", id).First(&account).Error; err != nil { + return AccountDTO{}, err + } + users, err := s.loadLinkedUsers(ctx, appCode, []int64{account.LinkedAppUserID}) + return accountDTO(account, users[account.LinkedAppUserID]), err +} + +func (s *Service) ResetPassword(ctx context.Context, appCode string, id uint64, password string) (AccountDTO, error) { + appCode = normalizeAppCode(appCode) + if id == 0 { + return AccountDTO{}, ErrInvalidInput + } + if err := validatePassword(password); err != nil { + return AccountDTO{}, err + } + hash, err := security.HashPasswordWithoutMinimum(password) + if err != nil { + return AccountDTO{}, ErrInvalidInput + } + var account model.ExternalAdminAccount + err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("id = ? AND app_code = ?", id, appCode).First(&account).Error; err != nil { + return err + } + if err := tx.Model(&account).Updates(map[string]any{ + "password_hash": hash, + // A reset still revokes every active session, but the replacement password + // is immediately usable and never creates a first-login rotation gate. + "password_change_required": false, + "failed_login_count": 0, + "locked_until_ms": 0, + }).Error; err != nil { + return err + } + return revokeAllSessions(tx, account.ID, "password_reset", time.Now().UTC().UnixMilli()) + }) + if errors.Is(err, gorm.ErrRecordNotFound) { + return AccountDTO{}, ErrAccountNotFound + } + if err != nil { + return AccountDTO{}, err + } + if err := s.db.WithContext(ctx).Where("id = ?", id).First(&account).Error; err != nil { + return AccountDTO{}, err + } + users, err := s.loadLinkedUsers(ctx, appCode, []int64{account.LinkedAppUserID}) + return accountDTO(account, users[account.LinkedAppUserID]), err +} + +func (s *Service) Login(ctx context.Context, input LoginInput) (LoginResult, error) { + input.Username = normalizeUsername(input.Username) + input.IP = truncateText(strings.TrimSpace(input.IP), 64) + input.UserAgent = truncateText(strings.TrimSpace(input.UserAgent), 512) + // The pre-resolution limiter uses only facts the server can trust: system, real + // client IP and the globally normalized username. AppCode is intentionally absent, + // so a forged tenant cannot select another account or evade any of these counters. + if err := s.consumeUnresolvedLoginRateLimit(ctx, input); err != nil { + return LoginResult{}, err + } + if s.db == nil { + return LoginResult{}, errors.New("admin mysql is not configured") + } + if !validUsername(input.Username) || input.Password == "" { + security.CheckPassword(s.dummyHash, input.Password) + return LoginResult{}, ErrInvalidCredentials + } + + // The global unique index makes this indexed projection the sole tenant resolver. + // Do not accept a request/header App here: only the AppCode stored with the account + // may select owner data, create the session or populate audit rows. + var resolvedAccount model.ExternalAdminAccount + err := s.db.WithContext(ctx).Select("id", "app_code").Where("username = ?", input.Username).Take(&resolvedAccount).Error + if errors.Is(err, gorm.ErrRecordNotFound) { + security.CheckPassword(s.dummyHash, input.Password) + s.writeUnknownLoginLog(ctx, input, "invalid_credentials") + return LoginResult{}, ErrInvalidCredentials + } + if err != nil { + return LoginResult{}, err + } + resolvedAccount.AppCode = normalizeAppCode(resolvedAccount.AppCode) + if !validAppCode(resolvedAccount.AppCode) { + security.CheckPassword(s.dummyHash, input.Password) + s.writeResolvedLoginLog(ctx, resolvedAccount.ID, resolvedAccount.AppCode, input, "invalid_account_app") + return LoginResult{}, ErrInvalidCredentials + } + // App quota is consumed in a second Redis call only after the indexed account + // resolution. System/IP/username rules are not repeated, so one attempt increments + // each layer exactly once while still containing a targeted tenant attack. + if err := s.consumeResolvedAppLoginRateLimit(ctx, resolvedAccount.AppCode); err != nil { + return LoginResult{}, err + } + app, err := s.findActiveApp(ctx, resolvedAccount.AppCode) + if err != nil { + // Keep disabled App, unknown account and wrong password indistinguishable. + security.CheckPassword(s.dummyHash, input.Password) + if errors.Is(err, sql.ErrNoRows) { + s.writeResolvedLoginLog(ctx, resolvedAccount.ID, resolvedAccount.AppCode, input, "app_inactive") + return LoginResult{}, ErrInvalidCredentials + } + return LoginResult{}, err + } + + nowMS := time.Now().UTC().UnixMilli() + var account model.ExternalAdminAccount + var session model.ExternalAdminSession + var sessionToken string + var csrfToken string + var authErr error + // Lock the account row while checking/updating the failure counter. Concurrent bad passwords + // must serialize on one counter; otherwise attackers could race requests below the lock threshold. + err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("id = ? AND username = ?", resolvedAccount.ID, input.Username).First(&account).Error + if errors.Is(err, gorm.ErrRecordNotFound) { + security.CheckPassword(s.dummyHash, input.Password) + authErr = ErrInvalidCredentials + return tx.Create(&model.ExternalAdminLoginLog{ + AppCode: resolvedAccount.AppCode, Username: input.Username, IP: input.IP, UserAgent: input.UserAgent, + Status: "failed", Message: "invalid_credentials", + }).Error + } + if err != nil { + return err + } + + accountID := account.ID + validPassword := security.CheckPassword(account.PasswordHash, input.Password) + accountAppCode := normalizeAppCode(account.AppCode) + if accountAppCode != resolvedAccount.AppCode { + // AppCode is not mutable through this module, but a concurrent/manual data + // correction between projection and row lock must not create a session whose + // App metadata and tenant scope came from different rows/snapshots. + authErr = ErrInvalidCredentials + return tx.Create(&model.ExternalAdminLoginLog{AccountID: &accountID, AppCode: accountAppCode, Username: input.Username, IP: input.IP, UserAgent: input.UserAgent, Status: "failed", Message: "account_app_changed"}).Error + } + account.AppCode = accountAppCode + if account.Status != model.ExternalAdminStatusActive { + authErr = ErrInvalidCredentials + return tx.Create(&model.ExternalAdminLoginLog{AccountID: &accountID, AppCode: account.AppCode, Username: input.Username, IP: input.IP, UserAgent: input.UserAgent, Status: "failed", Message: "account_disabled"}).Error + } + if account.LockedUntilMS > nowMS { + authErr = ErrInvalidCredentials + return tx.Create(&model.ExternalAdminLoginLog{AccountID: &accountID, AppCode: account.AppCode, Username: input.Username, IP: input.IP, UserAgent: input.UserAgent, Status: "failed", Message: "account_locked"}).Error + } + if !validPassword { + failedCount := account.FailedLoginCount + if account.LockedUntilMS > 0 && account.LockedUntilMS <= nowMS { + failedCount = 0 + } + failedCount++ + lockedUntilMS := int64(0) + message := "invalid_credentials" + if failedCount >= s.cfg.MaxLoginFailures { + lockedUntilMS = time.Now().UTC().Add(s.cfg.LockDuration).UnixMilli() + failedCount = 0 + message = "failure_limit_locked" + } + if err := tx.Model(&account).Updates(map[string]any{"failed_login_count": failedCount, "locked_until_ms": lockedUntilMS}).Error; err != nil { + return err + } + authErr = ErrInvalidCredentials + return tx.Create(&model.ExternalAdminLoginLog{AccountID: &accountID, AppCode: account.AppCode, Username: input.Username, IP: input.IP, UserAgent: input.UserAgent, Status: "failed", Message: message}).Error + } + + var tokenHash string + sessionToken, tokenHash, err = security.NewRefreshToken() + if err != nil { + return err + } + var csrfHash string + csrfToken, csrfHash, err = security.NewRefreshToken() + if err != nil { + return err + } + session = model.ExternalAdminSession{ + AccountID: account.ID, AppCode: account.AppCode, TokenHash: tokenHash, CSRFTokenHash: csrfHash, + IP: input.IP, UserAgent: input.UserAgent, ExpiresAtMS: time.Now().UTC().Add(s.cfg.SessionTTL).UnixMilli(), LastSeenAtMS: nowMS, + } + if err := tx.Create(&session).Error; err != nil { + return err + } + if err := tx.Model(&account).Updates(map[string]any{"failed_login_count": 0, "locked_until_ms": 0, "last_login_at_ms": nowMS}).Error; err != nil { + return err + } + account.LastLoginAtMS = &nowMS + return tx.Create(&model.ExternalAdminLoginLog{AccountID: &accountID, AppCode: account.AppCode, Username: input.Username, IP: input.IP, UserAgent: input.UserAgent, Status: "success", Message: "login_success"}).Error + }) + if err != nil { + return LoginResult{}, err + } + if authErr != nil { + return LoginResult{}, authErr + } + view, err := s.sessionView(ctx, account, app, csrfToken) + if err != nil { + _ = s.RevokeSession(ctx, session.ID, "profile_load_failed") + return LoginResult{}, err + } + return LoginResult{SessionToken: sessionToken, CSRFToken: csrfToken, View: view}, nil +} + +func (s *Service) consumeUnresolvedLoginRateLimit(ctx context.Context, input LoginInput) error { + if s.limiter == nil { + return ErrLoginLimiterFailed + } + ipDigest := loginRateLimitDigest(input.IP) + identityDigest := loginRateLimitDigest(input.Username) + rules := []cache.FixedWindowRule{ + // These keys are independent of App because no client-provided tenant value + // is trusted before the globally unique username resolves an account. + {Key: "rate:" + loginLimiterClusterTag + ":system", Limit: s.cfg.LoginRateLimit.SystemLimit}, + {Key: "rate:" + loginLimiterClusterTag + ":ip:" + ipDigest, Limit: s.cfg.LoginRateLimit.IPLimit}, + {Key: "rate:" + loginLimiterClusterTag + ":identity:" + identityDigest, Limit: s.cfg.LoginRateLimit.IdentityLimit}, + } + return s.consumeLoginRateLimitRules(ctx, rules) +} + +func (s *Service) consumeResolvedAppLoginRateLimit(ctx context.Context, appCode string) error { + if s.limiter == nil { + return ErrLoginLimiterFailed + } + rules := []cache.FixedWindowRule{{ + Key: "rate:" + loginLimiterClusterTag + ":app:" + loginRateLimitDigest(normalizeAppCode(appCode)), + Limit: s.cfg.LoginRateLimit.AppLimit, + }} + return s.consumeLoginRateLimitRules(ctx, rules) +} + +func (s *Service) consumeLoginRateLimitRules(ctx context.Context, rules []cache.FixedWindowRule) error { + limitCtx, cancel := context.WithTimeout(ctx, loginLimiterTimeout) + defer cancel() + decision, err := s.limiter.ConsumeFixedWindow(limitCtx, s.cfg.LoginRateLimit.Window, rules) + if err != nil { + return fmt.Errorf("%w: %v", ErrLoginLimiterFailed, err) + } + if !decision.Allowed { + retryAfter := decision.RetryAfter + if retryAfter <= 0 { + retryAfter = s.cfg.LoginRateLimit.Window + } + return &LoginRateLimitError{RetryAfter: retryAfter} + } + return nil +} + +func loginRateLimitDigest(value string) string { + digest := sha256.Sum256([]byte(value)) + // 128 bits of the SHA-256 output keeps keys compact while retaining ample + // collision resistance; no App, IP or account identifier appears in Redis. + return hex.EncodeToString(digest[:16]) +} + +func (s *Service) Authenticate(ctx context.Context, rawToken string) (SessionPrincipal, error) { + if strings.TrimSpace(rawToken) == "" || s.db == nil { + return SessionPrincipal{}, ErrInvalidSession + } + nowMS := time.Now().UTC().UnixMilli() + var session model.ExternalAdminSession + err := s.db.WithContext(ctx).Preload("Account").Where("token_hash = ? AND revoked_at_ms = 0 AND expires_at_ms > ?", security.HashToken(rawToken), nowMS).First(&session).Error + if errors.Is(err, gorm.ErrRecordNotFound) { + return SessionPrincipal{}, ErrInvalidSession + } + if err != nil { + return SessionPrincipal{}, err + } + if session.Account.Status != model.ExternalAdminStatusActive || session.Account.AppCode != session.AppCode { + _ = s.RevokeSession(ctx, session.ID, "account_invalid") + return SessionPrincipal{}, ErrInvalidSession + } + // Login-time App validation is insufficient because an already authenticated + // browser can skip /auth/me and call a business route directly after operators + // disable the App. Re-read the indexed App row on every opaque-session auth. + // Only a confirmed missing/inactive App revokes the session; transient user DB + // failures fail closed for this request without destroying a recoverable session. + if _, err := s.findActiveApp(ctx, session.AppCode); err != nil { + if errors.Is(err, sql.ErrNoRows) { + _ = s.RevokeSession(ctx, session.ID, "app_disabled") + return SessionPrincipal{}, ErrInvalidSession + } + return SessionPrincipal{}, err + } + permissions, err := decodePermissions(session.Account.PermissionsJSON) + if err != nil { + _ = s.RevokeSession(ctx, session.ID, "permission_snapshot_invalid") + return SessionPrincipal{}, ErrInvalidSession + } + if nowMS-session.LastSeenAtMS >= lastSeenWriteInterval.Milliseconds() { + // last_seen is intentionally throttled so read-heavy external pages do not turn every request into a write. + _ = s.db.WithContext(ctx).Model(&model.ExternalAdminSession{}).Where("id = ? AND revoked_at_ms = 0", session.ID).Update("last_seen_at_ms", nowMS).Error + } + operatorID, err := operatorIDForAccount(session.Account.ID) + if err != nil { + _ = s.RevokeSession(ctx, session.ID, "account_id_out_of_range") + return SessionPrincipal{}, ErrInvalidSession + } + return SessionPrincipal{ + SessionID: session.ID, AccountID: session.Account.ID, OperatorID: operatorID, AppCode: session.AppCode, + LinkedAppUserID: session.Account.LinkedAppUserID, Username: session.Account.Username, + // The persisted flag is a deprecated compatibility column. Always expose false + // so historical rows marked by older releases cannot recreate the retired gate. + Permissions: permissions, PasswordChangeRequired: false, + CSRFTokenHash: session.CSRFTokenHash, ExpiresAtMS: session.ExpiresAtMS, + }, nil +} + +func (s *Service) Me(ctx context.Context, principal SessionPrincipal, csrfToken string) (SessionView, error) { + var account model.ExternalAdminAccount + if err := s.db.WithContext(ctx).Where("id = ? AND app_code = ?", principal.AccountID, principal.AppCode).First(&account).Error; err != nil { + return SessionView{}, err + } + app, err := s.findActiveApp(ctx, principal.AppCode) + if err != nil { + return SessionView{}, err + } + return s.sessionView(ctx, account, app, csrfToken) +} + +func (s *Service) ChangePassword(ctx context.Context, principal SessionPrincipal, input ChangePasswordInput) error { + if err := validatePassword(input.NewPassword); err != nil { + return err + } + if strings.TrimSpace(input.CurrentPassword) == "" { + return ErrInvalidInput + } + hash, err := security.HashPasswordWithoutMinimum(input.NewPassword) + if err != nil { + return ErrInvalidInput + } + var passwordErr error + err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + var account model.ExternalAdminAccount + if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("id = ? AND app_code = ?", principal.AccountID, principal.AppCode).First(&account).Error; err != nil { + return err + } + if !security.CheckPassword(account.PasswordHash, input.CurrentPassword) { + passwordErr = ErrInvalidCredentials + return nil + } + // This comparison must use the hash read under the account row lock. Otherwise + // two concurrent password changes could both compare against a stale hash. + // Returning before both Updates calls also guarantees a rejected request does + // not revoke the account's other active sessions. + if security.CheckPassword(account.PasswordHash, input.NewPassword) { + passwordErr = ErrPasswordReused + return nil + } + if err := tx.Model(&account).Updates(map[string]any{ + "password_hash": hash, "password_change_required": false, + "failed_login_count": 0, "locked_until_ms": 0, + }).Error; err != nil { + return err + } + nowMS := time.Now().UTC().UnixMilli() + return tx.Model(&model.ExternalAdminSession{}). + Where("account_id = ? AND id <> ? AND revoked_at_ms = 0", principal.AccountID, principal.SessionID). + Updates(map[string]any{"revoked_at_ms": nowMS, "revoke_reason": "password_changed"}).Error + }) + if err != nil { + return err + } + return passwordErr +} + +func (s *Service) RevokeSession(ctx context.Context, sessionID uint64, reason string) error { + if sessionID == 0 || s.db == nil { + return nil + } + return s.db.WithContext(ctx).Model(&model.ExternalAdminSession{}). + Where("id = ? AND revoked_at_ms = 0", sessionID). + Updates(map[string]any{"revoked_at_ms": time.Now().UTC().UnixMilli(), "revoke_reason": strings.TrimSpace(reason)}).Error +} + +func (s *Service) CreateOperationLog(ctx context.Context, log model.ExternalAdminOperationLog) error { + if s.db == nil { + return errors.New("admin mysql is not configured") + } + return s.db.WithContext(ctx).Create(&log).Error +} + +func (s *Service) sessionView(ctx context.Context, account model.ExternalAdminAccount, app App, csrfToken string) (SessionView, error) { + users, err := s.loadLinkedUsers(ctx, account.AppCode, []int64{account.LinkedAppUserID}) + if err != nil { + return SessionView{}, err + } + user, ok := users[account.LinkedAppUserID] + if !ok { + return SessionView{}, ErrTargetNotFound + } + permissions, err := decodePermissions(account.PermissionsJSON) + if err != nil { + return SessionView{}, err + } + return SessionView{ + User: user, + Account: AccountSummary{ID: account.ID, Username: account.Username, Status: account.Status}, + App: app, AppCode: account.AppCode, Permissions: permissions, Capabilities: capabilitiesFor(permissions), + // Keep the wire field during rolling upgrades, but never surface the deprecated + // database marker as an instruction to block navigation or business APIs. + PasswordChangeRequired: false, CSRFToken: csrfToken, + }, nil +} + +func (s *Service) findActiveApp(ctx context.Context, appCode string) (App, error) { + if s.userDB == nil { + return App{}, errors.New("user mysql is not configured") + } + var app App + err := s.userDB.QueryRowContext(ctx, `SELECT app_code, app_name, logo_url FROM apps WHERE app_code = ? AND status = 'active' LIMIT 1`, normalizeAppCode(appCode)).Scan(&app.AppCode, &app.AppName, &app.LogoURL) + return app, err +} + +func (s *Service) loadLinkedUsers(ctx context.Context, appCode string, userIDs []int64) (map[int64]LinkedUser, error) { + users := make(map[int64]LinkedUser, len(userIDs)) + if len(userIDs) == 0 { + return users, nil + } + if s.userDB == nil { + return nil, errors.New("user mysql is not configured") + } + uniqueIDs := make([]int64, 0, len(userIDs)) + seen := map[int64]struct{}{} + for _, userID := range userIDs { + if userID <= 0 { + continue + } + if _, ok := seen[userID]; ok { + continue + } + seen[userID] = struct{}{} + uniqueIDs = append(uniqueIDs, userID) + } + if len(uniqueIDs) == 0 { + return users, nil + } + placeholders := strings.TrimRight(strings.Repeat("?,", len(uniqueIDs)), ",") + nowMS := time.Now().UTC().UnixMilli() + args := []any{nowMS, nowMS, normalizeAppCode(appCode)} + for _, userID := range uniqueIDs { + args = append(args, userID) + } + rows, err := s.userDB.QueryContext(ctx, ` + SELECT u.user_id, + COALESCE(u.current_display_user_id, ''), + COALESCE(u.default_display_user_id, ''), + COALESCE(( + SELECT lease.display_user_id + FROM pretty_display_user_id_leases lease + WHERE lease.app_code = u.app_code AND lease.user_id = u.user_id + AND lease.status = 'active' + AND (COALESCE(lease.expires_at_ms, 0) = 0 OR lease.expires_at_ms > ?) + ORDER BY lease.created_at_ms DESC, lease.lease_id DESC LIMIT 1 + ), ''), + COALESCE(( + SELECT pdi.pretty_id + FROM pretty_display_user_id_leases lease + JOIN pretty_display_ids pdi ON pdi.app_code = lease.app_code + AND pdi.assigned_lease_id = lease.lease_id AND pdi.status = 'assigned' + WHERE lease.app_code = u.app_code AND lease.user_id = u.user_id + AND lease.status = 'active' + AND (COALESCE(lease.expires_at_ms, 0) = 0 OR lease.expires_at_ms > ?) + ORDER BY lease.created_at_ms DESC, lease.lease_id DESC LIMIT 1 + ), ''), + COALESCE(u.username, ''), COALESCE(u.avatar, ''), COALESCE(u.status, '') + FROM users u + WHERE u.app_code = ? AND u.user_id IN (`+placeholders+`)`, args...) + if err != nil { + return nil, err + } + defer rows.Close() + for rows.Next() { + var user LinkedUser + if err := rows.Scan(&user.UserID, &user.DisplayUserID, &user.DefaultDisplayUserID, &user.PrettyDisplayUserID, &user.PrettyID, &user.Username, &user.Avatar, &user.Status); err != nil { + return nil, err + } + users[user.UserID] = user + } + return users, rows.Err() +} + +func (s *Service) writeUnknownLoginLog(ctx context.Context, input LoginInput, message string) { + if s.db == nil { + return + } + // Empty app_code is the audit sentinel for an unresolved username. Persisting a + // request-supplied tenant here would incorrectly attribute an attack to a real App. + _ = s.db.WithContext(ctx).Create(&model.ExternalAdminLoginLog{ + AppCode: "", Username: input.Username, IP: input.IP, UserAgent: input.UserAgent, + Status: "failed", Message: message, + }).Error +} + +func (s *Service) writeResolvedLoginLog(ctx context.Context, accountID uint64, appCode string, input LoginInput, message string) { + if s.db == nil { + return + } + _ = s.db.WithContext(ctx).Create(&model.ExternalAdminLoginLog{ + AccountID: &accountID, AppCode: normalizeAppCode(appCode), Username: input.Username, + IP: input.IP, UserAgent: input.UserAgent, Status: "failed", Message: message, + }).Error +} + +func accountDTO(account model.ExternalAdminAccount, linkedUser LinkedUser) AccountDTO { + permissions, _ := decodePermissions(account.PermissionsJSON) + if linkedUser.UserID == 0 { + linkedUser.UserID = account.LinkedAppUserID + } + return AccountDTO{ + ID: account.ID, AppCode: account.AppCode, Username: account.Username, Status: account.Status, + LinkedUser: linkedUser, Permissions: permissions, PermissionRevision: account.PermissionRevision, CreatedByAdminID: account.CreatedByAdminID, + CreatedAtMS: account.CreatedAtMS, UpdatedAtMS: account.UpdatedAtMS, LastLoginAtMS: account.LastLoginAtMS, + } +} + +func revokeAllSessions(tx *gorm.DB, accountID uint64, reason string, nowMS int64) error { + return tx.Model(&model.ExternalAdminSession{}).Where("account_id = ? AND revoked_at_ms = 0", accountID). + Updates(map[string]any{"revoked_at_ms": nowMS, "revoke_reason": reason}).Error +} + +func matchesExactIdentity(user LinkedUser, target string) bool { + target = strings.TrimSpace(target) + return target == strconv.FormatInt(user.UserID, 10) || + target == user.DisplayUserID || target == user.DefaultDisplayUserID || target == user.PrettyDisplayUserID || target == user.PrettyID +} + +func normalizePage(page int, pageSize int) (int, int) { + if page < 1 { + page = 1 + } + if pageSize < 1 { + pageSize = 20 + } + if pageSize > 100 { + pageSize = 100 + } + return page, pageSize +} + +func normalizeAppCode(value string) string { + value = strings.ToLower(strings.TrimSpace(value)) + if value == "" { + return "" + } + return appctx.Normalize(value) +} + +func normalizeUsername(value string) string { + return strings.ToLower(strings.TrimSpace(value)) +} + +func normalizeStatus(value string) string { + switch strings.ToLower(strings.TrimSpace(value)) { + case model.ExternalAdminStatusActive: + return model.ExternalAdminStatusActive + case model.ExternalAdminStatusDisabled: + return model.ExternalAdminStatusDisabled + default: + return "" + } +} + +func validUsername(value string) bool { + if len(value) < 3 || len(value) > 64 { + return false + } + for _, char := range value { + if (char >= 'a' && char <= 'z') || (char >= '0' && char <= '9') || char == '.' || char == '_' || char == '-' { + continue + } + return false + } + return true +} + +func validAppCode(value string) bool { + if len(value) == 0 || len(value) > 32 { + return false + } + for _, char := range value { + if (char >= 'a' && char <= 'z') || (char >= '0' && char <= '9') || char == '_' || char == '-' { + continue + } + return false + } + return true +} + +func truncateText(value string, maxRunes int) string { + if maxRunes <= 0 { + return "" + } + runes := []rune(value) + if len(runes) <= maxRunes { + return value + } + return string(runes[:maxRunes]) +} + +func validatePassword(password string) error { + // External administrators intentionally have no minimum password length. Preserve + // exact bytes (no trim), reject unusable all-whitespace credentials, and enforce + // bcrypt's hard 72-byte input limit before doing the expensive hash operation. + if strings.TrimSpace(password) == "" { + return ErrPasswordBlank + } + if len(password) > 72 { + return fmt.Errorf("%w: password length must not exceed 72 bytes", ErrInvalidInput) + } + return nil +} + +func isDuplicateKey(err error) bool { + var mysqlErr *mysqlDriver.MySQLError + return errors.As(err, &mysqlErr) && mysqlErr.Number == 1062 +} diff --git a/server/admin/internal/modules/externaladmin/service_login_test.go b/server/admin/internal/modules/externaladmin/service_login_test.go new file mode 100644 index 00000000..561997e4 --- /dev/null +++ b/server/admin/internal/modules/externaladmin/service_login_test.go @@ -0,0 +1,165 @@ +package externaladmin + +import ( + "database/sql/driver" + "errors" + "strings" + "testing" + "time" + + "hyapp-admin-server/internal/cache" + "hyapp-admin-server/internal/security" + + "github.com/DATA-DOG/go-sqlmock" + "gorm.io/driver/mysql" + "gorm.io/gorm" +) + +func TestLoginFailureLimitPersistsTimedLockAndUnifiedError(t *testing.T) { + adminSQL, adminMock, err := sqlmock.New() + if err != nil { + t.Fatalf("create admin sql mock: %v", err) + } + defer adminSQL.Close() + adminDB, err := gorm.Open(mysql.New(mysql.Config{Conn: adminSQL, SkipInitializeWithVersion: true}), &gorm.Config{}) + if err != nil { + t.Fatalf("create admin gorm db: %v", err) + } + userDB, userMock, err := sqlmock.New() + if err != nil { + t.Fatalf("create user sql mock: %v", err) + } + defer userDB.Close() + + passwordHash, err := security.HashPassword("correct-password") + if err != nil { + t.Fatalf("hash fixture password: %v", err) + } + // Login resolves the tenant from the globally unique account name before it + // touches the owner App database; no request App participates in either query. + adminMock.ExpectQuery("SELECT `id`,`app_code` FROM `external_admin_accounts` WHERE username = \\? LIMIT \\?"). + WithArgs("operator", 1). + WillReturnRows(sqlmock.NewRows([]string{"id", "app_code"}).AddRow(7, "fami")) + userMock.ExpectQuery("SELECT app_code, app_name, logo_url FROM apps"). + WithArgs("fami"). + WillReturnRows(sqlmock.NewRows([]string{"app_code", "app_name", "logo_url"}).AddRow("fami", "Fami", "logo")) + adminMock.ExpectBegin() + adminMock.ExpectQuery("SELECT \\* FROM `external_admin_accounts` WHERE id = \\? AND username = \\?"). + WithArgs(uint64(7), "operator", 1). + WillReturnRows(sqlmock.NewRows([]string{ + "id", "app_code", "linked_app_user_id", "username", "password_hash", "permissions_json", "status", + "password_change_required", "failed_login_count", "locked_until_ms", "created_by_admin_id", "created_at_ms", "updated_at_ms", + }).AddRow(7, "fami", 9001, "operator", passwordHash, `[]`, "active", false, 0, 0, 1, 1, 1)) + adminMock.ExpectExec("UPDATE `external_admin_accounts` SET"). + WithArgs(uint(0), futureMillis{}, sqlmock.AnyArg(), uint64(7)). + WillReturnResult(sqlmock.NewResult(0, 1)) + adminMock.ExpectExec("INSERT INTO `external_admin_login_logs`"). + WithArgs(sqlmock.AnyArg(), "fami", "operator", "127.0.0.1", "browser", "failed", "failure_limit_locked", sqlmock.AnyArg()). + WillReturnResult(sqlmock.NewResult(1, 1)) + adminMock.ExpectCommit() + + service := NewService(adminDB, userDB, Config{MaxLoginFailures: 1, LockDuration: 10 * time.Minute}) + limiter := &recordingFixedWindowLimiter{decision: cache.FixedWindowDecision{Allowed: true}} + service.limiter = limiter + _, err = service.Login(t.Context(), LoginInput{ + Username: "Operator", Password: "wrong-password", IP: "127.0.0.1", UserAgent: "browser", + }) + if !errors.Is(err, ErrInvalidCredentials) { + t.Fatalf("login error = %v, want unified invalid credentials", err) + } + if err := adminMock.ExpectationsWereMet(); err != nil { + t.Fatalf("admin sql expectations: %v", err) + } + if err := userMock.ExpectationsWereMet(); err != nil { + t.Fatalf("user sql expectations: %v", err) + } + if limiter.calls != 2 || len(limiter.batches) != 2 || len(limiter.batches[0]) != 3 || len(limiter.batches[1]) != 1 { + t.Fatalf("rate-limit batches = %+v", limiter.batches) + } + if !strings.Contains(limiter.batches[1][0].Key, ":app:") || limiter.batches[1][0].Limit != 120 { + t.Fatalf("resolved App limiter = %+v", limiter.batches[1]) + } + for _, rule := range limiter.batches[1] { + if strings.Contains(rule.Key, ":system") || strings.Contains(rule.Key, ":ip:") || strings.Contains(rule.Key, ":identity:") { + t.Fatalf("resolved App phase repeated a pre-resolution counter: %s", rule.Key) + } + } +} + +func TestLoginWithoutAppCreatesSessionFromResolvedAccountTenant(t *testing.T) { + adminSQL, adminMock, err := sqlmock.New() + if err != nil { + t.Fatalf("create admin sql mock: %v", err) + } + defer adminSQL.Close() + adminDB, err := gorm.Open(mysql.New(mysql.Config{Conn: adminSQL, SkipInitializeWithVersion: true}), &gorm.Config{}) + if err != nil { + t.Fatalf("create admin gorm db: %v", err) + } + userDB, userMock, err := sqlmock.New() + if err != nil { + t.Fatalf("create user sql mock: %v", err) + } + defer userDB.Close() + passwordHash, err := security.HashPassword("correct-password") + if err != nil { + t.Fatalf("hash fixture password: %v", err) + } + + adminMock.ExpectQuery("SELECT `id`,`app_code` FROM `external_admin_accounts` WHERE username = \\? LIMIT \\?"). + WithArgs("operator", 1). + WillReturnRows(sqlmock.NewRows([]string{"id", "app_code"}).AddRow(7, "fami")) + userMock.ExpectQuery("SELECT app_code, app_name, logo_url FROM apps"). + WithArgs("fami"). + WillReturnRows(sqlmock.NewRows([]string{"app_code", "app_name", "logo_url"}).AddRow("fami", "Fami", "logo")) + adminMock.ExpectBegin() + adminMock.ExpectQuery("SELECT \\* FROM `external_admin_accounts` WHERE id = \\? AND username = \\?"). + WithArgs(uint64(7), "operator", 1). + WillReturnRows(sqlmock.NewRows([]string{ + "id", "app_code", "linked_app_user_id", "username", "password_hash", "permissions_json", "status", + "password_change_required", "failed_login_count", "locked_until_ms", "last_login_at_ms", "created_by_admin_id", "created_at_ms", "updated_at_ms", + }).AddRow(7, "fami", 9001, "operator", passwordHash, `["bd:view"]`, "active", false, 0, 0, nil, 1, 1, 1)) + // The session insert is the persistence proof: AppCode comes from the account + // projection even though LoginInput has no App field at all. + adminMock.ExpectExec("INSERT INTO `external_admin_sessions`"). + WithArgs(uint64(7), "fami", sqlmock.AnyArg(), sqlmock.AnyArg(), "203.0.113.10", "browser", sqlmock.AnyArg(), sqlmock.AnyArg(), int64(0), "", sqlmock.AnyArg()). + WillReturnResult(sqlmock.NewResult(21, 1)) + adminMock.ExpectExec("UPDATE `external_admin_accounts` SET").WillReturnResult(sqlmock.NewResult(0, 1)) + adminMock.ExpectExec("INSERT INTO `external_admin_login_logs`"). + WithArgs(uint64(7), "fami", "operator", "203.0.113.10", "browser", "success", "login_success", sqlmock.AnyArg()). + WillReturnResult(sqlmock.NewResult(31, 1)) + adminMock.ExpectCommit() + userMock.ExpectQuery("SELECT u.user_id,"). + WithArgs(sqlmock.AnyArg(), sqlmock.AnyArg(), "fami", int64(9001)). + WillReturnRows(sqlmock.NewRows([]string{ + "user_id", "current_display_user_id", "default_display_user_id", "pretty_display_user_id", "pretty_id", "username", "avatar", "status", + }).AddRow(9001, "123456", "654321", "8888", "8888", "linked-user", "avatar", "active")) + + service := NewService(adminDB, userDB, Config{}) + service.limiter = allowFixedWindowLimiter{} + result, err := service.Login(t.Context(), LoginInput{ + Username: "Operator", Password: "correct-password", IP: "203.0.113.10", UserAgent: "browser", + }) + if err != nil { + t.Fatalf("login without App: %v", err) + } + if result.SessionToken == "" || result.CSRFToken == "" { + t.Fatal("successful login must issue opaque session and CSRF tokens") + } + if result.View.AppCode != "fami" || result.View.App.AppCode != "fami" || result.View.Account.Username != "operator" { + t.Fatalf("resolved session view = %+v", result.View) + } + if err := adminMock.ExpectationsWereMet(); err != nil { + t.Fatalf("admin sql expectations: %v", err) + } + if err := userMock.ExpectationsWereMet(); err != nil { + t.Fatalf("user sql expectations: %v", err) + } +} + +type futureMillis struct{} + +func (futureMillis) Match(value driver.Value) bool { + millis, ok := value.(int64) + return ok && millis > time.Now().UTC().UnixMilli() +} diff --git a/server/admin/internal/modules/externaladmin/team_test.go b/server/admin/internal/modules/externaladmin/team_test.go new file mode 100644 index 00000000..f81e39b9 --- /dev/null +++ b/server/admin/internal/modules/externaladmin/team_test.go @@ -0,0 +1,155 @@ +package externaladmin + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "strings" + "testing" + + adminmiddleware "hyapp-admin-server/internal/middleware" + + "github.com/gin-gonic/gin" + "google.golang.org/grpc" + userv1 "hyapp.local/api/proto/user/v1" +) + +type managerTeamHostClient struct { + userv1.UserHostServiceClient + request *userv1.ListManagerTeamAgenciesRequest + calls int +} + +func (client *managerTeamHostClient) ListManagerTeamAgencies(_ context.Context, request *userv1.ListManagerTeamAgenciesRequest, _ ...grpc.CallOption) (*userv1.ListManagerTeamAgenciesResponse, error) { + client.calls++ + client.request = request + return &userv1.ListManagerTeamAgenciesResponse{ + Agencies: []*userv1.ManagerTeamAgency{ + {AgencyId: 101, OwnerUserId: 1001, ParentBdUserId: 2001}, + {AgencyId: 102, OwnerUserId: 1002, ParentBdUserId: 2002}, + {AgencyId: 103, OwnerUserId: 1003, ParentBdUserId: 2003}, + }, + TotalBdLeaders: 4, + TotalBds: 9, + Truncated: true, + }, nil +} + +func TestMyTeamRouteUsesOnlySessionLinkedUserAndPaginates(t *testing.T) { + gin.SetMode(gin.TestMode) + client := &managerTeamHostClient{} + handler := New(nil, nil, Config{}, nil, WithUserHostClient(client)) + engine := gin.New() + group := engine.Group("/api/v1/external") + group.Use(func(c *gin.Context) { + // This fixture models fields populated by AuthRequired. Query parameters below + // intentionally carry attacker-selected IDs and must never override the principal. + c.Set(contextPrincipal, SessionPrincipal{AppCode: "fami", LinkedAppUserID: 42}) + c.Set(adminmiddleware.ContextPermissions, []string{"team:view"}) + c.Next() + }) + registerBusinessWhitelist(group, handler, BusinessHandlers{}) + + request := httptest.NewRequest(http.MethodGet, "/api/v1/external/admin/my-team/agencies?page=2&page_size=2&manager_user_id=999&user_id=888", nil) + responseRecorder := httptest.NewRecorder() + engine.ServeHTTP(responseRecorder, request) + if responseRecorder.Code != http.StatusOK { + t.Fatalf("status = %d body=%s", responseRecorder.Code, responseRecorder.Body.String()) + } + if client.calls != 1 || client.request == nil { + t.Fatalf("owner service calls = %d request=%v", client.calls, client.request) + } + if client.request.GetManagerUserId() != 42 { + t.Fatalf("manager user id = %d, want session linked user 42", client.request.GetManagerUserId()) + } + if client.request.GetMeta().GetAppCode() != "fami" || client.request.GetPageSize() != myTeamAgencyRPCPageSize { + t.Fatalf("owner request is not session scoped: %+v", client.request) + } + + var body struct { + Data MyTeamAgencyPage `json:"data"` + } + if err := json.Unmarshal(responseRecorder.Body.Bytes(), &body); err != nil { + t.Fatalf("decode response: %v", err) + } + if body.Data.Page != 2 || body.Data.PageSize != 2 || body.Data.Total != 3 || len(body.Data.Items) != 1 { + t.Fatalf("unexpected page: %+v", body.Data) + } + item := body.Data.Items[0] + if item.AgencyID != 103 || item.OwnerUserID != 1003 || item.ParentBDUserID != 2003 || item.Status != "active" { + t.Fatalf("unexpected agency projection: %+v", item) + } + if body.Data.TotalBDLeaders != 4 || body.Data.TotalBDs != 9 || !body.Data.Truncated { + t.Fatalf("owner totals not preserved: %+v", body.Data) + } + if got := responseRecorder.Body.String(); !containsAll(got, `"agencyId":"103"`, `"ownerUserId":"1003"`, `"parentBdUserId":"2003"`) { + t.Fatalf("int64 ids must be JSON strings: %s", got) + } +} + +func TestMyTeamRouteRequiresTeamViewPermissionBeforeOwnerCall(t *testing.T) { + gin.SetMode(gin.TestMode) + client := &managerTeamHostClient{} + handler := New(nil, nil, Config{}, nil, WithUserHostClient(client)) + engine := gin.New() + group := engine.Group("/api/v1/external") + group.Use(func(c *gin.Context) { + c.Set(contextPrincipal, SessionPrincipal{AppCode: "fami", LinkedAppUserID: 42}) + c.Set(adminmiddleware.ContextPermissions, []string{"agency:list"}) + c.Next() + }) + registerBusinessWhitelist(group, handler, BusinessHandlers{}) + + responseRecorder := httptest.NewRecorder() + engine.ServeHTTP(responseRecorder, httptest.NewRequest(http.MethodGet, "/api/v1/external/admin/my-team/agencies", nil)) + if responseRecorder.Code != http.StatusForbidden { + t.Fatalf("status = %d body=%s", responseRecorder.Code, responseRecorder.Body.String()) + } + if client.calls != 0 { + t.Fatalf("owner service called %d times without team:view", client.calls) + } +} + +func TestMyTeamRouteFiltersScopedIDProjectionBeforeTotalAndPagination(t *testing.T) { + gin.SetMode(gin.TestMode) + client := &managerTeamHostClient{} + handler := New(nil, nil, Config{}, nil, WithUserHostClient(client)) + engine := gin.New() + group := engine.Group("/api/v1/external") + group.Use(func(c *gin.Context) { + c.Set(contextPrincipal, SessionPrincipal{AppCode: "fami", LinkedAppUserID: 42}) + c.Set(adminmiddleware.ContextPermissions, []string{"team:view"}) + c.Next() + }) + registerBusinessWhitelist(group, handler, BusinessHandlers{}) + + // "002" matches owner 1002 and parent BD 2002. Filtering happens only over + // the already session-scoped RPC projection and must precede total/pagination. + responseRecorder := httptest.NewRecorder() + engine.ServeHTTP(responseRecorder, httptest.NewRequest(http.MethodGet, "/api/v1/external/admin/my-team/agencies?keyword=002&page=1&page_size=1", nil)) + if responseRecorder.Code != http.StatusOK { + t.Fatalf("status = %d body=%s", responseRecorder.Code, responseRecorder.Body.String()) + } + var body struct { + Data MyTeamAgencyPage `json:"data"` + } + if err := json.Unmarshal(responseRecorder.Body.Bytes(), &body); err != nil { + t.Fatalf("decode response: %v", err) + } + if body.Data.Total != 1 || len(body.Data.Items) != 1 || body.Data.Items[0].AgencyID != 102 { + t.Fatalf("keyword filter/page = %+v", body.Data) + } + if client.request.GetManagerUserId() != 42 { + t.Fatalf("keyword must not change team scope: manager=%d", client.request.GetManagerUserId()) + } +} + +func containsAll(value string, targets ...string) bool { + for _, target := range targets { + if !strings.Contains(value, target) { + return false + } + } + return true +} diff --git a/server/admin/internal/modules/externaladmin/types.go b/server/admin/internal/modules/externaladmin/types.go new file mode 100644 index 00000000..730b2781 --- /dev/null +++ b/server/admin/internal/modules/externaladmin/types.go @@ -0,0 +1,305 @@ +package externaladmin + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "sort" + "strconv" + "strings" + "time" + + "hyapp-admin-server/internal/cache" +) + +const ( + SessionCookieName = "hyapp_external_session" + CSRFCookieName = "hyapp_external_csrf" + CSRFHeaderName = "X-CSRF-Token" + CookiePath = "/api/v1/external" +) + +var ( + ErrInvalidCredentials = errors.New("invalid external admin credentials") + ErrAccountConflict = errors.New("external admin account conflict") + ErrAccountNotFound = errors.New("external admin account not found") + ErrTargetNotFound = errors.New("linked app user not found") + ErrInvalidInput = errors.New("invalid external admin input") + ErrInvalidPermissions = errors.New("invalid external admin permissions") + ErrPermissionConflict = errors.New("external admin permission revision conflict") + ErrInvalidSession = errors.New("invalid external admin session") + ErrPasswordReused = errors.New("new external admin password matches current password") + ErrPasswordBlank = errors.New("external admin password cannot be only whitespace") + ErrLoginRateLimited = errors.New("external admin login rate limited") + ErrLoginLimiterFailed = errors.New("external admin login rate limiter unavailable") +) + +const externalOperatorNamespace uint64 = 1 << 62 + +// Config contains only external-portal controls. Cookie transport attributes are inherited +// from the already validated admin cookie settings so local/prod deployments stay consistent. +type Config struct { + SessionTTL time.Duration + MaxLoginFailures uint + LockDuration time.Duration + CookieSecure bool + CookieSameSite string + LoginRateLimit LoginRateLimitConfig +} + +type LoginRateLimitConfig struct { + Window time.Duration + SystemLimit uint64 + AppLimit uint64 + IPLimit uint64 + IdentityLimit uint64 +} + +type FixedWindowLimiter interface { + ConsumeFixedWindow(context.Context, time.Duration, []cache.FixedWindowRule) (cache.FixedWindowDecision, error) +} + +type LoginRateLimitError struct { + RetryAfter time.Duration +} + +func (err *LoginRateLimitError) Error() string { + return ErrLoginRateLimited.Error() +} + +func (err *LoginRateLimitError) Unwrap() error { + return ErrLoginRateLimited +} + +type App struct { + AppCode string `json:"appCode"` + AppName string `json:"appName"` + LogoURL string `json:"logoUrl"` +} + +type LinkedUser struct { + UserID int64 `json:"userId,string"` + DisplayUserID string `json:"displayUserId"` + DefaultDisplayUserID string `json:"defaultDisplayUserId"` + PrettyDisplayUserID string `json:"prettyDisplayUserId"` + PrettyID string `json:"prettyId"` + Username string `json:"username"` + Avatar string `json:"avatar"` + Status string `json:"status"` +} + +type AccountDTO struct { + ID uint64 `json:"id"` + AppCode string `json:"appCode"` + Username string `json:"username"` + Status string `json:"status"` + LinkedUser LinkedUser `json:"linkedUser"` + Permissions []string `json:"permissions"` + PermissionRevision uint64 `json:"permissionRevision"` + CreatedByAdminID uint `json:"createdByAdminId"` + CreatedAtMS int64 `json:"createdAtMs"` + UpdatedAtMS int64 `json:"updatedAtMs"` + LastLoginAtMS *int64 `json:"lastLoginAtMs"` +} + +type AccountSummary struct { + ID uint64 `json:"id"` + Username string `json:"username"` + Status string `json:"status"` +} + +type SessionView struct { + User LinkedUser `json:"user"` + Account AccountSummary `json:"account"` + App App `json:"app"` + AppCode string `json:"appCode"` + Permissions []string `json:"permissions"` + Capabilities []string `json:"capabilities"` + PasswordChangeRequired bool `json:"passwordChangeRequired"` + CSRFToken string `json:"csrfToken,omitempty"` +} + +type LoginInput struct { + Username string + Password string + IP string + UserAgent string +} + +type LoginResult struct { + SessionToken string + CSRFToken string + View SessionView +} + +type ListInput struct { + AppCode string + Page int + PageSize int + Keyword string + Status string +} + +type ListResult struct { + Items []AccountDTO `json:"items"` + Page int `json:"page"` + PageSize int `json:"pageSize"` + Total int64 `json:"total"` +} + +type CreateInput struct { + AppCode string + TargetUserID string + Username string + Password string + Permissions []string + PermissionsSet bool + CreatedByAdminID uint +} + +type ChangePasswordInput struct { + CurrentPassword string + NewPassword string +} + +type SessionPrincipal struct { + SessionID uint64 + AccountID uint64 + OperatorID uint + AppCode string + LinkedAppUserID int64 + Username string + Permissions []string + PasswordChangeRequired bool + CSRFTokenHash string + ExpiresAtMS int64 +} + +// MyTeamAgency is intentionally a narrow projection of the owner service's active +// manager-team relation. IDs are encoded as strings so browser clients cannot lose +// precision when HYApp's int64 identifiers exceed JavaScript's safe integer range. +type MyTeamAgency struct { + AgencyID int64 `json:"agencyId,string"` + OwnerUserID int64 `json:"ownerUserId,string"` + ParentBDUserID int64 `json:"parentBdUserId,string"` + Status string `json:"status"` +} + +type MyTeamAgencyPage struct { + Items []MyTeamAgency `json:"items"` + Page int `json:"page"` + PageSize int `json:"pageSize"` + Total int `json:"total"` + TotalBDLeaders int32 `json:"totalBdLeaders"` + TotalBDs int32 `json:"totalBds"` + Truncated bool `json:"truncated"` +} + +func operatorIDForAccount(accountID uint64) (uint, error) { + if accountID == 0 || accountID >= externalOperatorNamespace { + return 0, ErrInvalidSession + } + // Reused business handlers accept only a positive admin/operator integer. A high-bit namespace + // prevents external account #1 from being recorded as main admin #1 while staying <= MaxInt64 + // for signed downstream protos and positive for UNSIGNED audit columns. + return uint(externalOperatorNamespace | accountID), nil +} + +func operatorUsername(appCode string, username string) string { + return truncateText("external:"+normalizeAppCode(appCode)+":"+normalizeUsername(username), 64) +} + +// FlexibleString accepts either a JSON string or number. Short IDs must remain textual in +// storage, but accepting numeric JSON prevents clients from silently losing older contracts. +type FlexibleString string + +func (value *FlexibleString) UnmarshalJSON(body []byte) error { + body = bytes.TrimSpace(body) + if len(body) == 0 || bytes.Equal(body, []byte("null")) { + *value = "" + return nil + } + if body[0] == '"' { + var text string + if err := json.Unmarshal(body, &text); err != nil { + return err + } + *value = FlexibleString(strings.TrimSpace(text)) + return nil + } + var number json.Number + if err := json.Unmarshal(body, &number); err != nil { + return fmt.Errorf("targetUserId must be a string or integer: %w", err) + } + if _, err := strconv.ParseInt(number.String(), 10, 64); err != nil { + return fmt.Errorf("targetUserId must be an integer: %w", err) + } + *value = FlexibleString(number.String()) + return nil +} + +func DefaultPermissionSnapshot() []string { + permissions := make([]string, 0, len(permissionCatalog)) + for _, item := range permissionCatalog { + if item.DefaultGranted { + permissions = append(permissions, item.Code) + } + } + return normalizePermissions(permissions) +} + +func encodePermissions(permissions []string) (string, error) { + normalized := normalizePermissions(permissions) + body, err := json.Marshal(normalized) + return string(body), err +} + +func decodePermissions(raw string) ([]string, error) { + permissions := []string{} + if err := json.Unmarshal([]byte(raw), &permissions); err != nil { + return nil, err + } + return effectivePermissions(permissions), nil +} + +func normalizePermissions(permissions []string) []string { + seen := make(map[string]struct{}, len(permissions)) + out := make([]string, 0, len(permissions)) + for _, permission := range permissions { + permission = strings.TrimSpace(permission) + if permission == "" { + continue + } + if _, ok := seen[permission]; ok { + continue + } + seen[permission] = struct{}{} + out = append(out, permission) + } + sort.Strings(out) + return out +} + +func capabilitiesFor(permissions []string) []string { + permissions = effectivePermissions(permissions) + permissionSet := make(map[string]struct{}, len(permissions)) + for _, permission := range permissions { + permissionSet[permission] = struct{}{} + } + aliases := permissionCapabilityAliases() + seen := map[string]struct{}{} + capabilities := []string{} + for permission := range permissionSet { + for _, capability := range aliases[permission] { + if _, ok := seen[capability]; ok { + continue + } + seen[capability] = struct{}{} + capabilities = append(capabilities, capability) + } + } + sort.Strings(capabilities) + return capabilities +} diff --git a/server/admin/internal/modules/externaladmin/types_test.go b/server/admin/internal/modules/externaladmin/types_test.go new file mode 100644 index 00000000..ccc0c7dd --- /dev/null +++ b/server/admin/internal/modules/externaladmin/types_test.go @@ -0,0 +1,115 @@ +package externaladmin + +import ( + "encoding/json" + "errors" + "reflect" + "sort" + "strings" + "testing" +) + +func TestExternalOperatorIdentityUsesStablePositiveNamespace(t *testing.T) { + first, err := operatorIDForAccount(1) + if err != nil { + t.Fatalf("operator id for first account: %v", err) + } + second, err := operatorIDForAccount(2) + if err != nil { + t.Fatalf("operator id for second account: %v", err) + } + if first == 1 || second == 2 || first == second { + t.Fatalf("operator ids must be namespaced and unique: first=%d second=%d", first, second) + } + if uint64(first) > uint64(1<<63-1) || uint64(second) > uint64(1<<63-1) { + t.Fatalf("operator ids must fit signed downstream fields: first=%d second=%d", first, second) + } + if _, err := operatorIDForAccount(externalOperatorNamespace); !errors.Is(err, ErrInvalidSession) { + t.Fatalf("out-of-range account id error = %v", err) + } + if got := operatorUsername("FAMI", "Operator"); got != "external:fami:operator" { + t.Fatalf("operator username = %q", got) + } + if got := operatorUsername("fami", strings.Repeat("x", 80)); len([]rune(got)) != 64 || !strings.HasPrefix(got, "external:fami:") { + t.Fatalf("long operator username is not safely prefixed/truncated: %q", got) + } +} + +func TestLinkedUserMarshalsLongIDAsString(t *testing.T) { + body, err := json.Marshal(LinkedUser{UserID: 9223372036854770000}) + if err != nil { + t.Fatalf("marshal linked user: %v", err) + } + if string(body) != `{"userId":"9223372036854770000","displayUserId":"","defaultDisplayUserId":"","prettyDisplayUserId":"","prettyId":"","username":"","avatar":"","status":""}` { + t.Fatalf("linked user json = %s", body) + } +} + +func TestDefaultPermissionSnapshotProducesCompleteCapabilityContract(t *testing.T) { + permissions := DefaultPermissionSnapshot() + wantPermissions := []string{ + "user:list", "user:update", "user-ban:list", "user:ban", "user:unban", + "host:list", "agency:list", "bd:list", "bd-manager:list", "super-admin:list", + "room:list", "room:update", "privilege:list", "privilege:grant", "banner:create", + "pretty-id:grant", "user-title:grant", "room-background:grant", "user-level:grant", "team:view", + } + for _, permission := range wantPermissions { + if !contains(permissions, permission) { + t.Fatalf("default permission snapshot missing %s", permission) + } + } + + capabilities := capabilitiesFor(permissions) + wantCapabilities := []string{ + "user:list", "user:update", "user-ban:list", "user:ban", "user:unban", + "host:list", "agency:list", "bd:list", "bd-manager:list", "super-admin:list", + "room:list", "room:update", "privilege:list", "privilege:grant", "banner:create", + "pretty-id:grant", "user-title:grant", "room-background:grant", "user-level:grant", "team:view", + } + sort.Strings(wantCapabilities) + if !reflect.DeepEqual(capabilities, wantCapabilities) { + t.Fatalf("capabilities = %#v, want %#v", capabilities, wantCapabilities) + } +} + +func TestFlexibleStringAcceptsShortIDStringAndInteger(t *testing.T) { + for _, testCase := range []struct { + body string + want string + }{ + {body: `"001234"`, want: "001234"}, + {body: `123456`, want: "123456"}, + } { + var value FlexibleString + if err := json.Unmarshal([]byte(testCase.body), &value); err != nil { + t.Fatalf("unmarshal %s: %v", testCase.body, err) + } + if string(value) != testCase.want { + t.Fatalf("value = %q, want %q", value, testCase.want) + } + } +} + +func TestExactIdentityDoesNotAcceptNicknameFallback(t *testing.T) { + user := LinkedUser{ + UserID: 77, DisplayUserID: "1234567", DefaultDisplayUserID: "7654321", + PrettyDisplayUserID: "8888", PrettyID: "8888", Username: "nickname", + } + for _, accepted := range []string{"77", "1234567", "7654321", "8888"} { + if !matchesExactIdentity(user, accepted) { + t.Fatalf("exact identity %s rejected", accepted) + } + } + if matchesExactIdentity(user, "nickname") { + t.Fatal("nickname must not bind an external credential") + } +} + +func contains(values []string, target string) bool { + for _, value := range values { + if value == target { + return true + } + } + return false +} diff --git a/server/admin/internal/modules/financewithdrawal/handler.go b/server/admin/internal/modules/financewithdrawal/handler.go index 623cc3ec..02277c73 100644 --- a/server/admin/internal/modules/financewithdrawal/handler.go +++ b/server/admin/internal/modules/financewithdrawal/handler.go @@ -5,6 +5,7 @@ import ( "strconv" "strings" + "hyapp-admin-server/internal/appctx" "hyapp-admin-server/internal/integration/activityclient" "hyapp-admin-server/internal/integration/walletclient" "hyapp-admin-server/internal/middleware" @@ -26,14 +27,37 @@ func New(store *repository.Store, wallet walletclient.Client, activity activityc } func (h *Handler) ListApplications(c *gin.Context) { + h.listApplications(c, false) +} + +func (h *Handler) ListOperationsApplications(c *gin.Context) { + h.listApplications(c, true) +} + +func (h *Handler) listApplications(c *gin.Context, operations bool) { options := shared.ListOptions(c) - items, total, err := h.service.ListApplications(repository.WithdrawalApplicationListOptions{ + listOptions := repository.WithdrawalApplicationListOptions{ Page: options.Page, PageSize: options.PageSize, AppCode: firstQuery(c, "app_code", "appCode"), Keyword: options.Keyword, - }) + } + var ( + items []withdrawalApplicationDTO + total int64 + err error + ) + actor := shared.ActorFromContext(c) + if operations { + items, total, err = h.service.ListOperationsApplications(actor, listOptions) + } else { + items, total, err = h.service.ListApplications(actor, listOptions) + } if err != nil { + if errors.Is(err, errWithdrawalMoneyScopeForbidden) { + response.Forbidden(c, err.Error()) + return + } response.ServerError(c, "获取用户提现申请列表失败") return } @@ -41,18 +65,31 @@ func (h *Handler) ListApplications(c *gin.Context) { } func (h *Handler) ApproveApplication(c *gin.Context) { - h.auditApplication(c, "approved") + h.auditApplication(c, "approved", false) } func (h *Handler) RejectApplication(c *gin.Context) { - h.auditApplication(c, "rejected") + h.auditApplication(c, "rejected", false) } -func (h *Handler) auditApplication(c *gin.Context, decision string) { +func (h *Handler) ApproveOperationsApplication(c *gin.Context) { + h.auditApplication(c, "approved", true) +} + +func (h *Handler) RejectOperationsApplication(c *gin.Context) { + h.auditApplication(c, "rejected", true) +} + +func (h *Handler) auditApplication(c *gin.Context, decision string, operations bool) { id, ok := shared.ParseID(c, "application_id") if !ok { return } + if strings.TrimSpace(c.GetHeader(appctx.HeaderAppCode)) == "" { + // 财务工作台可跨 App 列表,审核时必须由前端显式选中目标行 App;不能让 appctx 的 lalu 默认值静默决定资金数据域。 + response.BadRequest(c, "缺少 "+appctx.HeaderAppCode) + return + } var req struct { AuditRemark string `json:"auditRemark"` AuditImageURL string `json:"auditImageUrl"` @@ -66,7 +103,11 @@ func (h *Handler) auditApplication(c *gin.Context, decision string) { item *withdrawalApplicationDTO err error ) - if decision == "approved" { + if operations && decision == "approved" { + item, err = h.service.ApproveOperationsApplication(c.Request.Context(), shared.ActorFromContext(c), id, req.AuditRemark, middleware.CurrentRequestID(c)) + } else if operations { + item, err = h.service.RejectOperationsApplication(c.Request.Context(), shared.ActorFromContext(c), id, req.AuditRemark, middleware.CurrentRequestID(c)) + } else if decision == "approved" { item, err = h.service.ApproveApplication(c.Request.Context(), shared.ActorFromContext(c), id, req.AuditRemark, firstNonEmpty(req.AuditImageURL, req.AuditImageURLSnake), middleware.CurrentRequestID(c)) } else { item, err = h.service.RejectApplication(c.Request.Context(), shared.ActorFromContext(c), id, req.AuditRemark, middleware.CurrentRequestID(c)) @@ -75,7 +116,11 @@ func (h *Handler) auditApplication(c *gin.Context, decision string) { writeWithdrawalServiceError(c, err) return } - shared.OperationLogWithResourceID(c, h.audit, "audit-user-withdrawal-application", "admin_user_withdrawal_applications", strconv.FormatUint(uint64(item.ID), 10), "success", decision) + action := "audit-user-withdrawal-finance" + if operations { + action = "audit-user-withdrawal-operations" + } + shared.OperationLogWithResourceID(c, h.audit, action, "admin_user_withdrawal_applications", strconv.FormatUint(uint64(item.ID), 10), "success", decision) response.OK(c, item) } @@ -88,6 +133,14 @@ func writeWithdrawalServiceError(c *gin.Context, err error) { response.BadRequest(c, "提现申请已审核") return } + if errors.Is(err, repository.ErrWithdrawalApplicationStageNotReviewable) { + response.BadRequest(c, "提现申请尚未进入当前审核阶段") + return + } + if errors.Is(err, errWithdrawalMoneyScopeForbidden) { + response.Forbidden(c, err.Error()) + return + } switch strings.TrimSpace(err.Error()) { case "没有操作权限": response.Forbidden(c, err.Error()) diff --git a/server/admin/internal/modules/financewithdrawal/permission_test.go b/server/admin/internal/modules/financewithdrawal/permission_test.go index 1ff44f59..0feb140f 100644 --- a/server/admin/internal/modules/financewithdrawal/permission_test.go +++ b/server/admin/internal/modules/financewithdrawal/permission_test.go @@ -1,12 +1,56 @@ package financewithdrawal -import "testing" +import ( + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/gin-gonic/gin" +) func TestCanAuditWithdrawalUsesDedicatedPermission(t *testing.T) { if !canAuditWithdrawal([]string{"finance-withdrawal:audit"}) { - t.Fatal("dedicated withdrawal audit permission must allow auditing") + t.Fatal("finance withdrawal permission must allow finance final review") + } + if canAuditWithdrawal([]string{"operations-withdrawal:audit"}) { + t.Fatal("operations permission must not allow finance final review") } if canAuditWithdrawal([]string{"finance-application:audit"}) { t.Fatal("removed finance application permission must not authorize withdrawal auditing") } } + +func TestCanAuditOperationsWithdrawalUsesDedicatedPermission(t *testing.T) { + if !canAuditOperationsWithdrawal([]string{"operations-withdrawal:audit"}) { + t.Fatal("operations withdrawal permission must allow operations initial review") + } + if canAuditOperationsWithdrawal([]string{"finance-withdrawal:audit"}) { + t.Fatal("finance permission must not allow operations initial review") + } +} + +func TestWithdrawalAuditHandlersRequireExplicitAppHeader(t *testing.T) { + gin.SetMode(gin.TestMode) + handler := &Handler{} + router := gin.New() + router.POST("/finance/:application_id/approve", handler.ApproveApplication) + router.POST("/finance/:application_id/reject", handler.RejectApplication) + router.POST("/operations/:application_id/approve", handler.ApproveOperationsApplication) + router.POST("/operations/:application_id/reject", handler.RejectOperationsApplication) + + for _, path := range []string{ + "/finance/77/approve", + "/finance/77/reject", + "/operations/77/approve", + "/operations/77/reject", + } { + request := httptest.NewRequest(http.MethodPost, path, strings.NewReader(`{}`)) + request.Header.Set("Content-Type", "application/json") + response := httptest.NewRecorder() + router.ServeHTTP(response, request) + if response.Code != http.StatusBadRequest || !strings.Contains(response.Body.String(), "X-App-Code") { + t.Fatalf("missing App header path %s status=%d body=%s", path, response.Code, response.Body.String()) + } + } +} diff --git a/server/admin/internal/modules/financewithdrawal/response.go b/server/admin/internal/modules/financewithdrawal/response.go index cae15c08..1a9c9616 100644 --- a/server/admin/internal/modules/financewithdrawal/response.go +++ b/server/admin/internal/modules/financewithdrawal/response.go @@ -3,54 +3,66 @@ package financewithdrawal import "hyapp-admin-server/internal/model" type withdrawalApplicationDTO struct { - ID uint `json:"id"` - AppCode string `json:"appCode"` - AppName string `json:"appName"` - UserID string `json:"userId"` - SalaryAssetType string `json:"salaryAssetType"` - WithdrawAmount string `json:"withdrawAmount"` - WithdrawAmountMinor int64 `json:"withdrawAmountMinor"` - PointGrossAmount int64 `json:"pointGrossAmount,omitempty"` - PointFeeAmount int64 `json:"pointFeeAmount,omitempty"` - PointNetAmount int64 `json:"pointNetAmount,omitempty"` - PointsPerUSD int64 `json:"pointsPerUsd,omitempty"` - PointFeeBPS int32 `json:"pointFeeBps,omitempty"` - PointPolicyInstance string `json:"pointPolicyInstanceCode,omitempty"` - WithdrawMethod string `json:"withdrawMethod"` - WithdrawAddress string `json:"withdrawAddress"` - FreezeTransactionID string `json:"freezeTransactionId"` - AuditTransactionID string `json:"auditTransactionId"` - Status string `json:"status"` - ApproverUserID *uint `json:"approverUserId"` - ApproverName string `json:"approverName"` - AuditRemark string `json:"auditRemark"` - AuditImageURL string `json:"auditImageUrl"` - ApprovedAtMS *int64 `json:"approvedAtMs"` - CreatedAtMS int64 `json:"createdAtMs"` - UpdatedAtMS int64 `json:"updatedAtMs"` + ID uint `json:"id"` + AppCode string `json:"appCode"` + AppName string `json:"appName"` + UserID string `json:"userId"` + SalaryAssetType string `json:"salaryAssetType"` + WithdrawAmount string `json:"withdrawAmount"` + WithdrawAmountMinor int64 `json:"withdrawAmountMinor"` + PointGrossAmount int64 `json:"pointGrossAmount,omitempty"` + PointFeeAmount int64 `json:"pointFeeAmount,omitempty"` + PointNetAmount int64 `json:"pointNetAmount,omitempty"` + PointsPerUSD int64 `json:"pointsPerUsd,omitempty"` + PointFeeBPS int32 `json:"pointFeeBps,omitempty"` + PointPolicyInstance string `json:"pointPolicyInstanceCode,omitempty"` + WithdrawMethod string `json:"withdrawMethod"` + WithdrawAddress string `json:"withdrawAddress"` + FreezeTransactionID string `json:"freezeTransactionId"` + AuditTransactionID string `json:"auditTransactionId"` + Status string `json:"status"` + ApproverUserID *uint `json:"approverUserId"` + ApproverName string `json:"approverName"` + AuditRemark string `json:"auditRemark"` + AuditImageURL string `json:"auditImageUrl"` + ApprovedAtMS *int64 `json:"approvedAtMs"` + OperationsStatus string `json:"operationsStatus"` + OperationsReviewerUserID *uint `json:"operationsReviewerUserId"` + OperationsReviewerName string `json:"operationsReviewerName"` + OperationsAuditRemark string `json:"operationsAuditRemark"` + OperationsAuditTransactionID string `json:"operationsAuditTransactionId"` + OperationsReviewedAtMS *int64 `json:"operationsReviewedAtMs"` + CreatedAtMS int64 `json:"createdAtMs"` + UpdatedAtMS int64 `json:"updatedAtMs"` } func withdrawalApplicationDTOFromModel(item model.UserWithdrawalApplication) withdrawalApplicationDTO { dto := withdrawalApplicationDTO{ - ID: item.ID, - AppCode: item.AppCode, - AppName: item.AppCode, - UserID: item.UserID, - SalaryAssetType: item.SalaryAssetType, - WithdrawAmount: item.WithdrawAmount, - WithdrawAmountMinor: item.WithdrawAmountMinor, - WithdrawMethod: item.WithdrawMethod, - WithdrawAddress: item.WithdrawAddress, - FreezeTransactionID: item.FreezeTransactionID, - AuditTransactionID: item.AuditTransactionID, - Status: item.Status, - ApproverUserID: item.ApproverUserID, - ApproverName: item.ApproverName, - AuditRemark: item.AuditRemark, - AuditImageURL: item.AuditImageURL, - ApprovedAtMS: item.ApprovedAtMS, - CreatedAtMS: item.CreatedAtMS, - UpdatedAtMS: item.UpdatedAtMS, + ID: item.ID, + AppCode: item.AppCode, + AppName: item.AppCode, + UserID: item.UserID, + SalaryAssetType: item.SalaryAssetType, + WithdrawAmount: item.WithdrawAmount, + WithdrawAmountMinor: item.WithdrawAmountMinor, + WithdrawMethod: item.WithdrawMethod, + WithdrawAddress: item.WithdrawAddress, + FreezeTransactionID: item.FreezeTransactionID, + AuditTransactionID: item.AuditTransactionID, + Status: item.Status, + ApproverUserID: item.ApproverUserID, + ApproverName: item.ApproverName, + AuditRemark: item.AuditRemark, + AuditImageURL: item.AuditImageURL, + ApprovedAtMS: item.ApprovedAtMS, + OperationsStatus: item.OperationsStatus, + OperationsReviewerUserID: item.OperationsReviewerUserID, + OperationsReviewerName: item.OperationsReviewerName, + OperationsAuditRemark: item.OperationsAuditRemark, + OperationsAuditTransactionID: item.OperationsAuditTransactionID, + OperationsReviewedAtMS: item.OperationsReviewedAtMS, + CreatedAtMS: item.CreatedAtMS, + UpdatedAtMS: item.UpdatedAtMS, } if isPointWithdrawalAssetType(item.SalaryAssetType) { feePoints, netPoints, pointsPerUSD, feeBPS := pointWithdrawalSnapshot(item) diff --git a/server/admin/internal/modules/financewithdrawal/routes.go b/server/admin/internal/modules/financewithdrawal/routes.go index 94cf26fa..6b634743 100644 --- a/server/admin/internal/modules/financewithdrawal/routes.go +++ b/server/admin/internal/modules/financewithdrawal/routes.go @@ -13,4 +13,7 @@ func RegisterRoutes(protected *gin.RouterGroup, h *Handler) { protected.GET("/admin/finance/withdrawal-applications", middleware.RequireAnyPermission(permissionViewWithdrawalApplications, permissionAuditWithdrawalApplications), h.ListApplications) protected.POST("/admin/finance/withdrawal-applications/:application_id/approve", middleware.RequirePermission(permissionAuditWithdrawalApplications), h.ApproveApplication) protected.POST("/admin/finance/withdrawal-applications/:application_id/reject", middleware.RequirePermission(permissionAuditWithdrawalApplications), h.RejectApplication) + protected.GET("/admin/operations/withdrawal-applications", middleware.RequireAnyPermission(permissionViewOperationsWithdrawals, permissionAuditOperationsWithdrawals), h.ListOperationsApplications) + protected.POST("/admin/operations/withdrawal-applications/:application_id/approve", middleware.RequirePermission(permissionAuditOperationsWithdrawals), h.ApproveOperationsApplication) + protected.POST("/admin/operations/withdrawal-applications/:application_id/reject", middleware.RequirePermission(permissionAuditOperationsWithdrawals), h.RejectOperationsApplication) } diff --git a/server/admin/internal/modules/financewithdrawal/service.go b/server/admin/internal/modules/financewithdrawal/service.go index 4b263952..79b4ca48 100644 --- a/server/admin/internal/modules/financewithdrawal/service.go +++ b/server/admin/internal/modules/financewithdrawal/service.go @@ -22,11 +22,15 @@ import ( const ( permissionViewWithdrawalApplications = "finance-withdrawal:view" permissionAuditWithdrawalApplications = "finance-withdrawal:audit" + permissionViewOperationsWithdrawals = "operations-withdrawal:view" + permissionAuditOperationsWithdrawals = "operations-withdrawal:audit" pointWithdrawalDefaultPointsPerUSD = int64(100000) pointWithdrawalDefaultFeeBPS = int32(500) ) +var errWithdrawalMoneyScopeForbidden = errors.New("没有该 App 的财务范围") + type Service struct { store *repository.Store wallet walletclient.Client @@ -43,10 +47,16 @@ func NewService(store *repository.Store, wallet walletclient.Client, activity ac return &Service{store: store, wallet: wallet, activity: activity, now: func() time.Time { return time.Now().UTC() }} } -func (s *Service) ListApplications(options repository.WithdrawalApplicationListOptions) ([]withdrawalApplicationDTO, int64, error) { +func (s *Service) ListApplications(actor shared.Actor, options repository.WithdrawalApplicationListOptions) ([]withdrawalApplicationDTO, int64, error) { if s == nil || s.store == nil { return nil, 0, errors.New("admin store is not configured") } + var err error + options, err = s.scopeWithdrawalList(actor, options) + if err != nil { + return nil, 0, err + } + options.Stage = repository.WithdrawalApplicationReviewStageFinance items, total, err := s.store.ListWithdrawalApplications(options) if err != nil { return nil, 0, err @@ -54,73 +64,128 @@ func (s *Service) ListApplications(options repository.WithdrawalApplicationListO return withdrawalApplicationDTOsFromModel(items), total, nil } +func (s *Service) ListOperationsApplications(actor shared.Actor, options repository.WithdrawalApplicationListOptions) ([]withdrawalApplicationDTO, int64, error) { + if s == nil || s.store == nil { + return nil, 0, errors.New("admin store is not configured") + } + var err error + options, err = s.scopeWithdrawalList(actor, options) + if err != nil { + return nil, 0, err + } + options.Stage = repository.WithdrawalApplicationReviewStageOperations + items, total, err := s.store.ListWithdrawalApplications(options) + if err != nil { + return nil, 0, err + } + return withdrawalApplicationDTOsFromModel(items), total, nil +} + +func (s *Service) scopeWithdrawalList(actor shared.Actor, options repository.WithdrawalApplicationListOptions) (repository.WithdrawalApplicationListOptions, error) { + access, err := s.store.MoneyAccessForUser(actor.UserID) + if err != nil { + return options, err + } + if requestedApp := strings.TrimSpace(options.AppCode); requestedApp != "" { + options.AppCode = appctx.Normalize(requestedApp) + if !access.AllowsApp(options.AppCode) { + return options, errWithdrawalMoneyScopeForbidden + } + return options, nil + } + options.AppCode = "" + if !access.All { + // 空 app 查询不代表全局;非全量财务用户只能在 admin_user_money_scopes 授权的 App 集合中分页。 + options.RestrictAppCodes = true + options.AllowedAppCodes = access.AppCodes() + } + return options, nil +} + func (s *Service) ApproveApplication(ctx context.Context, actor shared.Actor, id uint, remark string, auditImageURL string, requestID string) (*withdrawalApplicationDTO, error) { - return s.auditApplication(ctx, actor, id, model.WithdrawalApplicationStatusApproved, remark, auditImageURL, requestID) + return s.auditApplication(ctx, actor, id, repository.WithdrawalApplicationReviewStageFinance, model.WithdrawalApplicationStatusApproved, remark, auditImageURL, requestID) } func (s *Service) RejectApplication(ctx context.Context, actor shared.Actor, id uint, remark string, requestID string) (*withdrawalApplicationDTO, error) { - return s.auditApplication(ctx, actor, id, model.WithdrawalApplicationStatusRejected, remark, "", requestID) + return s.auditApplication(ctx, actor, id, repository.WithdrawalApplicationReviewStageFinance, model.WithdrawalApplicationStatusRejected, remark, "", requestID) } -func (s *Service) auditApplication(ctx context.Context, actor shared.Actor, id uint, decision string, remark string, auditImageURL string, requestID string) (*withdrawalApplicationDTO, error) { +func (s *Service) ApproveOperationsApplication(ctx context.Context, actor shared.Actor, id uint, remark string, requestID string) (*withdrawalApplicationDTO, error) { + return s.auditApplication(ctx, actor, id, repository.WithdrawalApplicationReviewStageOperations, model.WithdrawalApplicationStatusApproved, remark, "", requestID) +} + +func (s *Service) RejectOperationsApplication(ctx context.Context, actor shared.Actor, id uint, remark string, requestID string) (*withdrawalApplicationDTO, error) { + return s.auditApplication(ctx, actor, id, repository.WithdrawalApplicationReviewStageOperations, model.WithdrawalApplicationStatusRejected, remark, "", requestID) +} + +func (s *Service) auditApplication(ctx context.Context, actor shared.Actor, id uint, stage repository.WithdrawalApplicationReviewStage, decision string, remark string, auditImageURL string, requestID string) (*withdrawalApplicationDTO, error) { if s == nil || s.store == nil || s.wallet == nil || s.activity == nil { return nil, errors.New("admin finance withdrawal service is not configured") } - if id == 0 || actor.UserID == 0 || !canAuditWithdrawal(actor.Permissions) { + if id == 0 || actor.UserID == 0 || !canAuditWithdrawalStage(stage, actor.Permissions) { return nil, errors.New("没有操作权限") } remark = strings.TrimSpace(remark) auditImageURL = strings.TrimSpace(auditImageURL) - if decision == model.WithdrawalApplicationStatusApproved && auditImageURL == "" { + if stage == repository.WithdrawalApplicationReviewStageFinance && decision == model.WithdrawalApplicationStatusApproved && auditImageURL == "" { return nil, errors.New("提现通过凭证图片不能为空") } if decision == model.WithdrawalApplicationStatusRejected && remark == "" { return nil, errors.New("拒绝原因不能为空") } appCode := appctx.FromContext(ctx) - item, err := s.store.GetWithdrawalApplicationForApp(appCode, id) + access, err := s.store.MoneyAccessForUser(actor.UserID) if err != nil { return nil, err } - if item.Status != model.WithdrawalApplicationStatusPending { - return nil, repository.ErrWithdrawalApplicationAlreadyAudited - } - userID, err := strconv.ParseInt(strings.TrimSpace(item.UserID), 10, 64) - if err != nil || userID <= 0 || item.SalaryAssetType == "" || item.WithdrawAmountMinor <= 0 || item.FreezeTransactionID == "" { - return nil, errors.New("提现单冻结信息不完整") - } - commandID := withdrawalAuditCommandID(id, decision) - amountMinor := item.WithdrawAmountMinor - transactionID, err := s.applyWalletDecision(ctx, decision, commandID, appCode, userID, item.SalaryAssetType, amountMinor, item.PointFeeAmount, item.PointNetAmount, item.PointsPerUSD, item.PointFeeBPS, actor, strings.TrimSpace(remark), id) - if err != nil { - return nil, err + if !access.AllowsApp(appCode) { + // 审核以目标行的 App header 为数据域;即使 JWT 含按钮权限,也不能跨 admin_user_money_scopes 触发钱包动作。 + return nil, errWithdrawalMoneyScopeForbidden } nowMS := s.now().UnixMilli() - if err := s.sendWithdrawalAuditNotice(ctx, auditNoticeInput{ - ApplicationID: id, - AppCode: appCode, - UserID: userID, - Decision: decision, - Remark: remark, - AuditImageURL: auditImageURL, - AuditTransactionID: transactionID, - WithdrawAmount: item.WithdrawAmount, - WithdrawMethod: item.WithdrawMethod, - RequestID: requestID, - SentAtMS: nowMS, - }); err != nil { - // 钱包同意/释放已经用 command id 做幂等;通知失败时不写后台终态,财务重试会复用同一钱包命令和消息事件,避免重复扣款、返还或重复通知。 - return nil, err + commandID := withdrawalAuditCommandID(id, stage) + if stage == repository.WithdrawalApplicationReviewStageOperations && decision == model.WithdrawalApplicationStatusRejected { + return s.executeOperationsRejection(ctx, actor, id, appCode, remark, requestID, commandID, nowMS) } - updated, err := s.store.AuditWithdrawalApplicationForApp(appCode, id, repository.WithdrawalApplicationAuditInput{ - Decision: decision, - ApproverUserID: actor.UserID, - ApproverName: actor.Username, - AuditRemark: remark, - AuditImageURL: auditImageURL, - AuditCommandID: commandID, - AuditTransactionID: transactionID, - ApprovedAtMS: nowMS, + updated, err := s.store.ReviewWithdrawalApplicationForApp(appCode, id, repository.WithdrawalApplicationAuditInput{ + Stage: stage, + Decision: decision, + ApproverUserID: actor.UserID, + ApproverName: actor.Username, + AuditRemark: remark, + AuditImageURL: auditImageURL, + ApprovedAtMS: nowMS, + }, func(item model.UserWithdrawalApplication) (repository.WithdrawalApplicationAuditEffect, error) { + userID, parseErr := withdrawalWalletUserID(item) + if parseErr != nil { + return repository.WithdrawalApplicationAuditEffect{}, parseErr + } + if stage == repository.WithdrawalApplicationReviewStageOperations && decision == model.WithdrawalApplicationStatusApproved { + // 运营通过只确认业务资料并转交财务;申请金额继续保留在 frozen,且不能提前向用户发送最终通过通知。 + return repository.WithdrawalApplicationAuditEffect{}, nil + } + transactionID, walletErr := s.applyWalletDecision(ctx, decision, commandID, appCode, userID, item.SalaryAssetType, item.WithdrawAmountMinor, item.PointFeeAmount, item.PointNetAmount, item.PointsPerUSD, item.PointFeeBPS, actor, strings.TrimSpace(remark), id) + if walletErr != nil { + return repository.WithdrawalApplicationAuditEffect{}, walletErr + } + if noticeErr := s.sendWithdrawalAuditNotice(ctx, auditNoticeInput{ + ApplicationID: id, + AppCode: appCode, + UserID: userID, + Stage: stage, + Decision: decision, + Remark: remark, + AuditImageURL: auditImageURL, + AuditTransactionID: transactionID, + WithdrawAmount: item.WithdrawAmount, + WithdrawMethod: item.WithdrawMethod, + RequestID: requestID, + SentAtMS: nowMS, + }); noticeErr != nil { + // 钱包扣冻/释放使用阶段固定 command id,通知使用阶段+结果事件 id;回调失败会回滚 admin 状态,重试不会重复资金动作或消息。 + return repository.WithdrawalApplicationAuditEffect{}, noticeErr + } + return repository.WithdrawalApplicationAuditEffect{CommandID: commandID, TransactionID: transactionID}, nil }) if err != nil { return nil, err @@ -129,6 +194,80 @@ func (s *Service) auditApplication(ctx context.Context, actor shared.Actor, id u return &dto, nil } +// executeOperationsRejection 把拒绝拆成 claim -> 外部幂等动作 -> finalize 三段。 +// claim 是独立短事务,因此 wallet 已释放后即使 notice 或最终 admin 提交失败,申请仍停在 rejecting,不能被改点通过或进入财务。 +func (s *Service) executeOperationsRejection(ctx context.Context, actor shared.Actor, id uint, appCode string, remark string, requestID string, commandID string, nowMS int64) (*withdrawalApplicationDTO, error) { + claimed, err := s.store.ClaimWithdrawalOperationsRejectionForApp(appCode, id, repository.WithdrawalApplicationAuditInput{ + Stage: repository.WithdrawalApplicationReviewStageOperations, + Decision: model.WithdrawalApplicationStatusRejected, + ApproverUserID: actor.UserID, + ApproverName: actor.Username, + AuditRemark: remark, + AuditCommandID: commandID, + ApprovedAtMS: nowMS, + }, func(item model.UserWithdrawalApplication) error { + _, err := withdrawalWalletUserID(item) + return err + }) + if err != nil { + return nil, err + } + if claimed.Status == model.WithdrawalApplicationStatusRejected && claimed.OperationsStatus == model.WithdrawalOperationsStatusRejected { + // 已完成的重复请求直接返回终态,避免再次调用 wallet/inbox;前端重试是安全的。 + dto := withdrawalApplicationDTOFromModel(*claimed) + return &dto, nil + } + + userID, err := withdrawalWalletUserID(*claimed) + if err != nil { + return nil, err + } + if claimed.OperationsReviewerUserID == nil || *claimed.OperationsReviewerUserID == 0 || strings.TrimSpace(claimed.OperationsAuditRemark) == "" { + return nil, errors.New("提现单运营拒绝 claim 不完整") + } + // 重试沿用第一次 claim 的审核人和拒绝原因,不能让资金 metadata、用户通知和后台审计快照随重试人改变。 + claimedActor := shared.Actor{UserID: *claimed.OperationsReviewerUserID, Username: claimed.OperationsReviewerName} + claimedRemark := strings.TrimSpace(claimed.OperationsAuditRemark) + transactionID, err := s.applyWalletDecision(ctx, model.WithdrawalApplicationStatusRejected, commandID, appCode, userID, claimed.SalaryAssetType, claimed.WithdrawAmountMinor, claimed.PointFeeAmount, claimed.PointNetAmount, claimed.PointsPerUSD, claimed.PointFeeBPS, claimedActor, claimedRemark, id) + if err != nil { + return nil, err + } + sentAtMS := nowMS + if claimed.OperationsReviewedAtMS != nil && *claimed.OperationsReviewedAtMS > 0 { + sentAtMS = *claimed.OperationsReviewedAtMS + } + if err := s.sendWithdrawalAuditNotice(ctx, auditNoticeInput{ + ApplicationID: id, + AppCode: appCode, + UserID: userID, + Stage: repository.WithdrawalApplicationReviewStageOperations, + Decision: model.WithdrawalApplicationStatusRejected, + Remark: claimedRemark, + AuditTransactionID: transactionID, + WithdrawAmount: claimed.WithdrawAmount, + WithdrawMethod: claimed.WithdrawMethod, + RequestID: requestID, + SentAtMS: sentAtMS, + }); err != nil { + // rejecting 已在前一事务提交;返回错误让运营页展示“重试拒绝”,绝不能回退成 pending。 + return nil, err + } + updated, err := s.store.FinalizeWithdrawalOperationsRejectionForApp(appCode, id, commandID, transactionID, s.now().UnixMilli()) + if err != nil { + return nil, err + } + dto := withdrawalApplicationDTOFromModel(*updated) + return &dto, nil +} + +func withdrawalWalletUserID(item model.UserWithdrawalApplication) (int64, error) { + userID, err := strconv.ParseInt(strings.TrimSpace(item.UserID), 10, 64) + if err != nil || userID <= 0 || strings.TrimSpace(item.SalaryAssetType) == "" || item.WithdrawAmountMinor <= 0 || strings.TrimSpace(item.FreezeTransactionID) == "" { + return 0, errors.New("提现单冻结信息不完整") + } + return userID, nil +} + func (s *Service) applyWalletDecision(ctx context.Context, decision string, commandID string, appCode string, userID int64, assetType string, amountMinor int64, storedFeePoints int64, storedNetPoints int64, storedPointsPerUSD int64, storedFeeBPS int32, actor shared.Actor, remark string, applicationID uint) (string, error) { reason := strings.TrimSpace(remark) if reason == "" { @@ -223,8 +362,9 @@ func (s *Service) applyWalletDecision(ctx context.Context, decision string, comm } } -func withdrawalAuditCommandID(id uint, decision string) string { - return fmt.Sprintf("salary-withdrawal:%d:%s", id, decision) +func withdrawalAuditCommandID(id uint, stage repository.WithdrawalApplicationReviewStage) string { + // 同一阶段的通过和拒绝复用 command id;并发相反决策会在 wallet request hash 校验处冲突,不能先后 settle/release 同一冻结金额。 + return fmt.Sprintf("salary-withdrawal:%d:%s", id, stage) } func isPointWithdrawalAssetType(assetType string) bool { @@ -240,6 +380,7 @@ type auditNoticeInput struct { ApplicationID uint AppCode string UserID int64 + Stage repository.WithdrawalApplicationReviewStage Decision string Remark string AuditImageURL string @@ -259,6 +400,9 @@ func (s *Service) sendWithdrawalAuditNotice(ctx context.Context, input auditNoti body = "Your withdrawal request has been rejected. Reason: " + strings.TrimSpace(input.Remark) title = "Withdrawal request rejected" eventType = "finance_withdrawal_rejected" + if input.Stage == repository.WithdrawalApplicationReviewStageOperations { + eventType = "operations_withdrawal_rejected" + } } else { imageURL = strings.TrimSpace(input.AuditImageURL) } @@ -267,6 +411,7 @@ func (s *Service) sendWithdrawalAuditNotice(ctx context.Context, input auditNoti "app_code": strings.TrimSpace(input.AppCode), "audit_transaction_id": strings.TrimSpace(input.AuditTransactionID), "decision": strings.TrimSpace(input.Decision), + "review_stage": string(input.Stage), "withdraw_amount": strings.TrimSpace(input.WithdrawAmount), "withdraw_method": strings.TrimSpace(input.WithdrawMethod), }) @@ -282,7 +427,7 @@ func (s *Service) sendWithdrawalAuditNotice(ctx context.Context, input auditNoti }, TargetUserId: input.UserID, Producer: "admin-server", - ProducerEventId: withdrawalAuditNotificationEventID(input.ApplicationID, input.Decision), + ProducerEventId: withdrawalAuditNotificationEventID(input.ApplicationID, input.Stage, input.Decision), ProducerEventType: eventType, MessageType: "system", AggregateType: "user_withdrawal_application", @@ -300,14 +445,32 @@ func (s *Service) sendWithdrawalAuditNotice(ctx context.Context, input auditNoti return nil } -func withdrawalAuditNotificationEventID(id uint, decision string) string { - return fmt.Sprintf("finance-withdrawal:%d:%s", id, strings.TrimSpace(decision)) +func withdrawalAuditNotificationEventID(id uint, stage repository.WithdrawalApplicationReviewStage, decision string) string { + if stage == repository.WithdrawalApplicationReviewStageFinance { + // 旧财务通知可能已成功而 admin 申请仍 pending;继续使用原 event id,部署后重试才不会重复发用户通知。 + return fmt.Sprintf("finance-withdrawal:%d:%s", id, strings.TrimSpace(decision)) + } + return fmt.Sprintf("operations-withdrawal:%d:%s", id, strings.TrimSpace(decision)) } func canAuditWithdrawal(permissions []string) bool { + return hasWithdrawalPermission(permissions, permissionAuditWithdrawalApplications) +} + +func canAuditOperationsWithdrawal(permissions []string) bool { + return hasWithdrawalPermission(permissions, permissionAuditOperationsWithdrawals) +} + +func canAuditWithdrawalStage(stage repository.WithdrawalApplicationReviewStage, permissions []string) bool { + if stage == repository.WithdrawalApplicationReviewStageOperations { + return canAuditOperationsWithdrawal(permissions) + } + return canAuditWithdrawal(permissions) +} + +func hasWithdrawalPermission(permissions []string, expected string) bool { for _, permission := range permissions { - switch strings.TrimSpace(permission) { - case permissionAuditWithdrawalApplications: + if strings.TrimSpace(permission) == expected { return true } } diff --git a/server/admin/internal/modules/financewithdrawal/service_test.go b/server/admin/internal/modules/financewithdrawal/service_test.go index 30c95036..12e12fe6 100644 --- a/server/admin/internal/modules/financewithdrawal/service_test.go +++ b/server/admin/internal/modules/financewithdrawal/service_test.go @@ -2,14 +2,229 @@ package financewithdrawal import ( "context" + "errors" "testing" + "time" + "hyapp-admin-server/internal/appctx" + "hyapp-admin-server/internal/integration/activityclient" "hyapp-admin-server/internal/integration/walletclient" "hyapp-admin-server/internal/model" "hyapp-admin-server/internal/modules/shared" + "hyapp-admin-server/internal/repository" + activityv1 "hyapp.local/api/proto/activity/v1" walletv1 "hyapp.local/api/proto/wallet/v1" + + "github.com/DATA-DOG/go-sqlmock" + "gorm.io/driver/mysql" + "gorm.io/gorm" ) +func TestOperationsApprovalMovesToFinanceWithoutWalletOrUserNotice(t *testing.T) { + svc, mock, wallet, activity, closeService := newWithdrawalAuditServiceTest(t) + defer closeService() + expectWithdrawalMoneyAccess(mock, 8, "lalu") + expectWithdrawalReviewLock(mock, model.WithdrawalApplicationStatusPending, model.WithdrawalOperationsStatusPending) + mock.ExpectExec("UPDATE `admin_user_withdrawal_applications` SET").WillReturnResult(sqlmock.NewResult(0, 1)) + mock.ExpectCommit() + + dto, err := svc.ApproveOperationsApplication(appctx.WithContext(context.Background(), "lalu"), shared.Actor{ + UserID: 8, Username: "operations", Permissions: []string{permissionAuditOperationsWithdrawals}, + }, 77, "资料无误", "request-ops-approve") + if err != nil { + t.Fatalf("approve operations withdrawal failed: %v", err) + } + if dto.Status != model.WithdrawalApplicationStatusPending || dto.OperationsStatus != model.WithdrawalOperationsStatusApproved || dto.OperationsReviewerName != "operations" { + t.Fatalf("operations approval state mismatch: %+v", dto) + } + if wallet.settleSalary != nil || wallet.releaseSalary != nil || wallet.settlePoint != nil || wallet.releasePoint != nil || activity.calls != 0 { + t.Fatalf("operations approval must not touch wallet or send final notice: wallet=%+v notice_calls=%d", wallet, activity.calls) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} + +func TestOperationsRejectionReleasesFrozenBalanceAndSendsFinalNotice(t *testing.T) { + svc, mock, wallet, activity, closeService := newWithdrawalAuditServiceTest(t) + defer closeService() + expectWithdrawalMoneyAccess(mock, 8, "lalu") + expectWithdrawalRejectionClaim(mock, model.WithdrawalOperationsStatusPending) + expectWithdrawalRejectionFinalize(mock) + + dto, err := svc.RejectOperationsApplication(appctx.WithContext(context.Background(), "lalu"), shared.Actor{ + UserID: 8, Username: "operations", Permissions: []string{permissionAuditOperationsWithdrawals}, + }, 77, "收款资料不符", "request-ops-reject") + if err != nil { + t.Fatalf("reject operations withdrawal failed: %v", err) + } + if wallet.releaseSalary == nil || wallet.releaseSalary.GetCommandId() != "salary-withdrawal:77:operations" || wallet.releaseSalary.GetSalaryUsdMinor() != 5000 { + t.Fatalf("operations rejection release mismatch: %+v", wallet.releaseSalary) + } + if wallet.settleSalary != nil || wallet.settlePoint != nil || wallet.releasePoint != nil { + t.Fatalf("operations rejection must only release matching salary asset: %+v", wallet) + } + if activity.calls != 1 || activity.last.GetProducerEventId() != "operations-withdrawal:77:rejected" || activity.last.GetProducerEventType() != "operations_withdrawal_rejected" { + t.Fatalf("operations rejection final notice mismatch: calls=%d request=%+v", activity.calls, activity.last) + } + if dto.Status != model.WithdrawalApplicationStatusRejected || dto.OperationsStatus != model.WithdrawalOperationsStatusRejected || dto.OperationsAuditTransactionID != "salary-release-tx" { + t.Fatalf("operations rejection state mismatch: %+v", dto) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} + +func TestOperationsRejectionNoticeFailureStaysRejectingAndRetryKeepsFirstAuditContext(t *testing.T) { + svc, mock, wallet, activity, closeService := newWithdrawalAuditServiceTest(t) + defer closeService() + noticeFailure := errors.New("activity unavailable") + activity.failures = []error{noticeFailure, nil} + + expectWithdrawalMoneyAccess(mock, 8, "lalu") + expectWithdrawalRejectionClaim(mock, model.WithdrawalOperationsStatusPending) + _, err := svc.RejectOperationsApplication(appctx.WithContext(context.Background(), "lalu"), shared.Actor{ + UserID: 8, Username: "first-operator", Permissions: []string{permissionAuditOperationsWithdrawals}, + }, 77, "first rejection reason", "request-ops-reject-first") + if !errors.Is(err, noticeFailure) { + t.Fatalf("first rejection must surface notice failure, got %v", err) + } + + // 第二个运营人员重试时只能沿用第一次 claim 快照;数据库 rejecting 行禁止改点通过,也不允许改写拒绝原因。 + expectWithdrawalMoneyAccess(mock, 18, "lalu") + expectWithdrawalRejectionRetryClaim(mock, 8, "first-operator", "first rejection reason") + expectWithdrawalRejectionFinalizeWithContext(mock, 8, "first-operator", "first rejection reason") + dto, err := svc.RejectOperationsApplication(appctx.WithContext(context.Background(), "lalu"), shared.Actor{ + UserID: 18, Username: "retry-operator", Permissions: []string{permissionAuditOperationsWithdrawals}, + }, 77, "changed retry reason", "request-ops-reject-retry") + if err != nil { + t.Fatalf("retry rejecting withdrawal failed: %v", err) + } + if dto.OperationsStatus != model.WithdrawalOperationsStatusRejected || wallet.releaseSalary.GetOperatorUserId() != 8 || wallet.releaseSalary.GetReason() != "first rejection reason" { + t.Fatalf("retry must preserve first claim context: dto=%+v wallet=%+v", dto, wallet.releaseSalary) + } + if activity.calls != 2 || activity.last == nil || activity.last.GetBody() != "Your withdrawal request has been rejected. Reason: first rejection reason" { + t.Fatalf("retry notice must preserve first rejection reason: calls=%d request=%+v", activity.calls, activity.last) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} + +func TestOperationsApprovalRejectsDurableRejectingClaimBeforeWalletOrNotice(t *testing.T) { + svc, mock, wallet, activity, closeService := newWithdrawalAuditServiceTest(t) + defer closeService() + expectWithdrawalMoneyAccess(mock, 18, "lalu") + mock.ExpectBegin() + mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`.*FOR UPDATE"). + WithArgs("lalu", uint(77), 1). + WillReturnRows(withdrawalAuditRowsWithOperationsContext(model.WithdrawalApplicationStatusPending, model.WithdrawalOperationsStatusRejecting, 8, "first-operator", "first rejection reason")) + mock.ExpectRollback() + + _, err := svc.ApproveOperationsApplication(appctx.WithContext(context.Background(), "lalu"), shared.Actor{ + UserID: 18, Username: "retry-operator", Permissions: []string{permissionAuditOperationsWithdrawals}, + }, 77, "改为通过", "request-ops-approve-after-reject") + if !errors.Is(err, repository.ErrWithdrawalApplicationStageNotReviewable) { + t.Fatalf("rejecting claim must block operations approval, got %v", err) + } + if wallet.settleSalary != nil || wallet.releaseSalary != nil || wallet.settlePoint != nil || wallet.releasePoint != nil || activity.calls != 0 { + t.Fatalf("rejecting gate must run before integrations: wallet=%+v notices=%d", wallet, activity.calls) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} + +func TestFinanceReviewRejectsOperationsPendingBeforeWalletOrNotice(t *testing.T) { + svc, mock, wallet, activity, closeService := newWithdrawalAuditServiceTest(t) + defer closeService() + expectWithdrawalMoneyAccess(mock, 9, "lalu") + mock.ExpectBegin() + mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`.*FOR UPDATE"). + WithArgs("lalu", uint(77), 1). + WillReturnRows(withdrawalAuditRows(model.WithdrawalApplicationStatusPending, model.WithdrawalOperationsStatusPending)) + mock.ExpectRollback() + + _, err := svc.ApproveApplication(appctx.WithContext(context.Background(), "lalu"), shared.Actor{ + UserID: 9, Username: "finance", Permissions: []string{permissionAuditWithdrawalApplications}, + }, 77, "已打款", "https://example.com/proof.png", "request-finance-approve") + if !errors.Is(err, repository.ErrWithdrawalApplicationStageNotReviewable) { + t.Fatalf("finance must reject operations-pending application, got %v", err) + } + if wallet.settleSalary != nil || wallet.releaseSalary != nil || wallet.settlePoint != nil || wallet.releasePoint != nil || activity.calls != 0 { + t.Fatalf("stage gate must run before wallet or notice: wallet=%+v notice_calls=%d", wallet, activity.calls) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} + +func TestOperationsListRejectsExplicitAppOutsideMoneyScope(t *testing.T) { + svc, mock, wallet, activity, closeService := newWithdrawalAuditServiceTest(t) + defer closeService() + expectWithdrawalMoneyAccess(mock, 8, "lalu") + + _, _, err := svc.ListOperationsApplications(shared.Actor{UserID: 8}, repository.WithdrawalApplicationListOptions{AppCode: "huwaa"}) + if !errors.Is(err, errWithdrawalMoneyScopeForbidden) { + t.Fatalf("out-of-scope list must be forbidden, got %v", err) + } + if wallet.settleSalary != nil || wallet.releaseSalary != nil || activity.calls != 0 { + t.Fatalf("out-of-scope list must not call integrations: wallet=%+v notices=%d", wallet, activity.calls) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} + +func TestOperationsListWithoutAppRestrictsToMoneyScopeApps(t *testing.T) { + svc, mock, _, _, closeService := newWithdrawalAuditServiceTest(t) + defer closeService() + expectWithdrawalMoneyAccess(mock, 8, "lalu", "fami") + mock.ExpectQuery("SELECT count\\(\\*\\) FROM `admin_user_withdrawal_applications`.*app_code IN.*operations_status <> \\?"). + WithArgs("fami", "lalu", model.WithdrawalOperationsStatusSkipped). + WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0)) + mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`.*app_code IN.*operations_status <> \\?"). + WithArgs("fami", "lalu", model.WithdrawalOperationsStatusSkipped, 20). + WillReturnRows(sqlmock.NewRows([]string{"id"})) + + items, total, err := svc.ListOperationsApplications(shared.Actor{UserID: 8}, repository.WithdrawalApplicationListOptions{Page: 1, PageSize: 20}) + if err != nil || total != 0 || len(items) != 0 { + t.Fatalf("money-scoped operations list mismatch: total=%d items=%+v err=%v", total, items, err) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} + +func TestFinanceAuditRejectsHeaderAppOutsideMoneyScopeBeforeWallet(t *testing.T) { + svc, mock, wallet, activity, closeService := newWithdrawalAuditServiceTest(t) + defer closeService() + expectWithdrawalMoneyAccess(mock, 9, "fami") + + _, err := svc.ApproveApplication(appctx.WithContext(context.Background(), "lalu"), shared.Actor{ + UserID: 9, Username: "finance", Permissions: []string{permissionAuditWithdrawalApplications}, + }, 77, "paid", "https://example.com/proof.png", "request-out-of-scope") + if !errors.Is(err, errWithdrawalMoneyScopeForbidden) { + t.Fatalf("out-of-scope audit must be forbidden, got %v", err) + } + if wallet.settleSalary != nil || wallet.releaseSalary != nil || wallet.settlePoint != nil || wallet.releasePoint != nil || activity.calls != 0 { + t.Fatalf("money scope gate must run before row lock, wallet, or notice: wallet=%+v notices=%d", wallet, activity.calls) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} + +func TestWithdrawalAuditNotificationEventIDPreservesFinanceCompatibility(t *testing.T) { + t.Parallel() + if got := withdrawalAuditNotificationEventID(77, repository.WithdrawalApplicationReviewStageFinance, model.WithdrawalApplicationStatusApproved); got != "finance-withdrawal:77:approved" { + t.Fatalf("finance event id = %q", got) + } + if got := withdrawalAuditNotificationEventID(77, repository.WithdrawalApplicationReviewStageOperations, model.WithdrawalApplicationStatusRejected); got != "operations-withdrawal:77:rejected" { + t.Fatalf("operations event id = %q", got) + } +} + func TestApplyWalletDecisionRoutesPointApprovalToPointSettlement(t *testing.T) { wallet := &fakeAuditWalletClient{} svc := &Service{wallet: wallet} @@ -120,3 +335,121 @@ func (f *fakeAuditWalletClient) ReleaseSalaryWithdrawal(_ context.Context, req * f.releaseSalary = req return &walletv1.ReleaseSalaryWithdrawalResponse{TransactionId: "salary-release-tx"}, nil } + +type fakeAuditActivityClient struct { + activityclient.Client + last *activityv1.CreateInboxMessageRequest + calls int + failures []error +} + +func (f *fakeAuditActivityClient) CreateInboxMessage(_ context.Context, req *activityv1.CreateInboxMessageRequest) (*activityv1.CreateInboxMessageResponse, error) { + f.last = req + f.calls++ + if index := f.calls - 1; index < len(f.failures) && f.failures[index] != nil { + return nil, f.failures[index] + } + return &activityv1.CreateInboxMessageResponse{}, nil +} + +func newWithdrawalAuditServiceTest(t *testing.T) (*Service, sqlmock.Sqlmock, *fakeAuditWalletClient, *fakeAuditActivityClient, func()) { + t.Helper() + sqlDB, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("create sql mock failed: %v", err) + } + gormDB, err := gorm.Open(mysql.New(mysql.Config{Conn: sqlDB, SkipInitializeWithVersion: true}), &gorm.Config{}) + if err != nil { + _ = sqlDB.Close() + t.Fatalf("create gorm db failed: %v", err) + } + wallet := &fakeAuditWalletClient{} + activity := &fakeAuditActivityClient{} + svc := &Service{ + store: repository.New(gormDB), wallet: wallet, activity: activity, + now: func() time.Time { return time.UnixMilli(1_700_000_300_000).UTC() }, + } + return svc, mock, wallet, activity, func() { _ = sqlDB.Close() } +} + +func expectWithdrawalReviewLock(mock sqlmock.Sqlmock, status string, operationsStatus string) { + mock.ExpectBegin() + mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`.*FOR UPDATE"). + WithArgs("lalu", uint(77), 1). + WillReturnRows(withdrawalAuditRows(status, operationsStatus)) +} + +func expectWithdrawalRejectionClaim(mock sqlmock.Sqlmock, operationsStatus string) { + mock.ExpectBegin() + mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`.*FOR UPDATE"). + WithArgs("lalu", uint(77), 1). + WillReturnRows(withdrawalAuditRows(model.WithdrawalApplicationStatusPending, operationsStatus)) + if operationsStatus == model.WithdrawalOperationsStatusPending { + mock.ExpectExec("UPDATE `admin_user_withdrawal_applications` SET").WillReturnResult(sqlmock.NewResult(0, 1)) + } + mock.ExpectCommit() +} + +func expectWithdrawalRejectionRetryClaim(mock sqlmock.Sqlmock, reviewerID uint, reviewerName string, remark string) { + mock.ExpectBegin() + mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`.*FOR UPDATE"). + WithArgs("lalu", uint(77), 1). + WillReturnRows(withdrawalAuditRowsWithOperationsContext(model.WithdrawalApplicationStatusPending, model.WithdrawalOperationsStatusRejecting, reviewerID, reviewerName, remark)) + mock.ExpectCommit() +} + +func expectWithdrawalRejectionFinalize(mock sqlmock.Sqlmock) { + expectWithdrawalRejectionFinalizeWithContext(mock, 8, "operations", "收款资料不符") +} + +func expectWithdrawalRejectionFinalizeWithContext(mock sqlmock.Sqlmock, reviewerID uint, reviewerName string, remark string) { + mock.ExpectBegin() + mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`.*FOR UPDATE"). + WithArgs("lalu", uint(77), 1). + WillReturnRows(withdrawalAuditRowsWithOperationsContext(model.WithdrawalApplicationStatusPending, model.WithdrawalOperationsStatusRejecting, reviewerID, reviewerName, remark)) + mock.ExpectExec("UPDATE `admin_user_withdrawal_applications` SET").WillReturnResult(sqlmock.NewResult(0, 1)) + mock.ExpectCommit() +} + +func expectWithdrawalMoneyAccess(mock sqlmock.Sqlmock, userID uint, appCodes ...string) { + mock.ExpectQuery("SELECT \\* FROM `admin_users` WHERE `admin_users`.`id` = \\? ORDER BY `admin_users`.`id` LIMIT \\?"). + WillReturnRows(sqlmock.NewRows([]string{"id", "username", "name", "status"}).AddRow(userID, "reviewer", "Reviewer", "active")) + mock.ExpectQuery("SELECT \\* FROM `admin_user_roles` WHERE `admin_user_roles`.`user_id` = \\?"). + WillReturnRows(sqlmock.NewRows([]string{"user_id", "role_id"})) + rows := sqlmock.NewRows([]string{"id", "user_id", "app_code", "region_id", "created_at_ms", "updated_at_ms"}) + for index, appCode := range appCodes { + rows.AddRow(index+1, userID, appCode, 0, int64(1_700_000_000_000), int64(1_700_000_000_000)) + } + mock.ExpectQuery("SELECT \\* FROM `admin_user_money_scopes` WHERE user_id = \\? ORDER BY app_code ASC, region_id ASC"). + WillReturnRows(rows) +} + +func withdrawalAuditRows(status string, operationsStatus string) *sqlmock.Rows { + return withdrawalAuditRowsWithOperationsContext(status, operationsStatus, 0, "", "") +} + +func withdrawalAuditRowsWithOperationsContext(status string, operationsStatus string, reviewerID uint, reviewerName string, remark string) *sqlmock.Rows { + var storedReviewerID any + var reviewedAtMS any + operationsCommandID := "" + if reviewerID > 0 { + storedReviewerID = reviewerID + reviewedAtMS = int64(1_700_000_300_000) + operationsCommandID = "salary-withdrawal:77:operations" + } + return sqlmock.NewRows([]string{ + "id", "app_code", "user_id", "salary_asset_type", "withdraw_amount", "withdraw_amount_minor", + "withdraw_method", "withdraw_address", "freeze_command_id", "freeze_transaction_id", + "audit_command_id", "audit_transaction_id", "status", "operations_status", + "approver_user_id", "approver_name", "audit_remark", "audit_image_url", "approved_at_ms", + "operations_reviewer_user_id", "operations_reviewer_name", "operations_audit_remark", + "operations_audit_command_id", "operations_audit_transaction_id", "operations_reviewed_at_ms", + "created_at_ms", "updated_at_ms", + }).AddRow( + 77, "lalu", "42001", "HOST_SALARY_USD", "50.00", int64(5000), + "usdt_trc20", "TRON-address", "freeze-command", "freeze-tx", + "", "", status, operationsStatus, nil, "", "", "", nil, + storedReviewerID, reviewerName, remark, operationsCommandID, "", reviewedAtMS, + int64(1_700_000_000_000), int64(1_700_000_000_000), + ) +} diff --git a/server/admin/internal/modules/payment/aslan_paid_coin_seller_source.go b/server/admin/internal/modules/payment/aslan_paid_coin_seller_source.go new file mode 100644 index 00000000..3193df27 --- /dev/null +++ b/server/admin/internal/modules/payment/aslan_paid_coin_seller_source.go @@ -0,0 +1,391 @@ +package payment + +import ( + "context" + "fmt" + "strconv" + "strings" + "time" + + "hyapp-admin-server/internal/appctx" + "hyapp-admin-server/internal/config" + + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" +) + +// financePaidCoinSellerRechargeSource 只暴露支付系统已经成功落单的币商充值事实。 +// WebConsole 手工填写的 USDT/金币和 legacy 钱包发货流水不实现这个接口,避免运营输入进入财务口径。 +type financePaidCoinSellerRechargeSource interface { + financePaidCoinSellerRechargeStats(context.Context, financeCoinSellerRechargeQuery) (financeCoinSellerRechargeStats, error) + listFinancePaidCoinSellerRechargeBills(context.Context, financeCoinSellerRechargeQuery, int) ([]rechargeBillDTO, int64, error) +} + +func (h *Handler) financePaidCoinSellerRechargeSource(appCode string) financePaidCoinSellerRechargeSource { + if h == nil || appctx.Normalize(appCode) != "aslan" { + return nil + } + // 目前只有 Aslan legacy H5 的 FREIGHT_GOLD 真实支付单需要从 Mongo 补齐; + // 其他 App 继续使用自己的已校验后台订单或新 wallet H5 订单,避免无依据扩大旧平台口径。 + source, ok := h.billSources["aslan"] + if !ok || source == nil { + return nil + } + paidSource, _ := source.(financePaidCoinSellerRechargeSource) + return paidSource +} + +// financePaidCoinSellerFilter 只匹配有支付订单号、支付渠道、正数美元金额且已经成功的 FREIGHT_GOLD 单。 +// 这组字段来自 in_app_purchase_details 支付事实,不读取 user_freight_balance_running_water 的发货金额。 +func (s *MongoRechargeBillSource) financePaidCoinSellerFilter(ctx context.Context, query financeCoinSellerRechargeQuery) (bson.M, []string, bool, error) { + if s == nil || s.collection == nil || appctx.Normalize(s.config.AppCode) != "aslan" { + return nil, nil, false, nil + } + filter := bson.M{ + "sysOrigin": s.config.SysOrigin, + "status": "SUCCESS", + "trialPeriod": bson.M{"$ne": true}, + "amountUsd": bson.M{"$gt": 0}, + "orderId": bson.M{"$type": "string", "$ne": ""}, + "factory.factoryCode": bson.M{"$type": "string", "$ne": ""}, + } + conditions := bson.A{bson.M{"$or": legacyFreightCommodityMatchConditions()}} + if query.TargetUserID > 0 { + filter["acceptUserId"] = query.TargetUserID + } + if keyword := strings.TrimSpace(query.Keyword); keyword != "" { + keywordConditions := bson.A{ + bson.M{"_id": keyword}, + bson.M{"orderId": keyword}, + } + if userID, err := strconv.ParseInt(keyword, 10, 64); err == nil && userID > 0 { + keywordConditions = append(keywordConditions, bson.M{"_id": userID}, bson.M{"acceptUserId": userID}) + } + conditions = append(conditions, bson.M{"$or": keywordConditions}) + } + paidAt := legacyPaidCoinSellerAtExpression() + timeConditions := bson.A{} + if query.StartAtMS > 0 { + timeConditions = append(timeConditions, bson.M{"$gte": bson.A{paidAt, time.UnixMilli(query.StartAtMS)}}) + } + if query.EndAtMS > 0 { + timeConditions = append(timeConditions, bson.M{"$lt": bson.A{paidAt, time.UnixMilli(query.EndAtMS)}}) + } + if len(timeConditions) == 1 { + conditions = append(conditions, bson.M{"$expr": timeConditions[0]}) + } else if len(timeConditions) > 1 { + conditions = append(conditions, bson.M{"$expr": bson.M{"$and": timeConditions}}) + } + filter["$and"] = conditions + + if query.RegionID <= 0 { + return filter, nil, true, nil + } + codes, handled, err := s.regionCountryCodes(ctx, query.RegionID) + if err != nil { + return nil, nil, false, err + } + if !handled || len(codes) == 0 { + return nil, nil, false, nil + } + return filter, codes, true, nil +} + +func legacyFreightCommodityMatchConditions() bson.A { + conditions := make(bson.A, 0, len(legacyFreightCommodityFields)) + for _, field := range legacyFreightCommodityFields { + conditions = append(conditions, bson.M{field: bson.M{"$in": legacyFreightCommodityTypes}}) + } + return conditions +} + +// updateTime 是支付回调把订单推进 SUCCESS 的时间;旧单缺失时才依次回退 purchaseDateMs/createTime。 +func legacyPaidCoinSellerAtExpression() bson.M { + return bson.M{"$ifNull": bson.A{ + "$updateTime", + bson.M{"$ifNull": bson.A{"$purchaseDateMs", "$createTime"}}, + }} +} + +func legacyFreightCoinAggregateExpression() bson.M { + typedTotal := bson.M{"$reduce": bson.M{ + "input": bson.M{"$ifNull": bson.A{"$products", bson.A{}}}, + "initialValue": int64(0), + "in": bson.M{"$add": bson.A{ + "$$value", + bson.M{"$cond": bson.A{ + bson.M{"$or": bson.A{ + bson.M{"$in": bson.A{"$$this.code", legacyFreightCommodityTypes}}, + bson.M{"$in": bson.A{"$$this.name", legacyFreightCommodityTypes}}, + }}, + bson.M{"$convert": bson.M{"input": "$$this.content", "to": "long", "onError": int64(0), "onNull": int64(0)}}, + int64(0), + }}, + }}, + }} + allNumericTotal := bson.M{"$reduce": bson.M{ + "input": bson.M{"$ifNull": bson.A{"$products", bson.A{}}}, + "initialValue": int64(0), + "in": bson.M{"$add": bson.A{ + "$$value", + bson.M{"$convert": bson.M{"input": "$$this.content", "to": "long", "onError": int64(0), "onNull": int64(0)}}, + }}, + }} + return bson.M{"$let": bson.M{ + "vars": bson.M{"typedTotal": typedTotal, "allNumericTotal": allNumericTotal}, + "in": bson.M{"$cond": bson.A{ + bson.M{"$gt": bson.A{"$$typedTotal", 0}}, + "$$typedTotal", + bson.M{"$cond": bson.A{ + bson.M{"$in": bson.A{"$trackCommodityType", legacyFreightCommodityTypes}}, + "$$allNumericTotal", + int64(0), + }}, + }}, + }} +} + +func (s *MongoRechargeBillSource) financePaidCoinSellerRechargeStats(ctx context.Context, query financeCoinSellerRechargeQuery) (financeCoinSellerRechargeStats, error) { + stats := financeCoinSellerRechargeStats{Daily: map[string]rechargeBillSummaryBucketDTO{}} + filter, regionCodes, matchable, err := s.financePaidCoinSellerFilter(ctx, query) + if err != nil || !matchable { + return stats, err + } + base := mongo.Pipeline{bson.D{{Key: "$match", Value: filter}}} + if len(regionCodes) > 0 { + base = append(base, legacyRegionLookupStages(regionCodes)...) + } else { + base = append(base, legacyCountryResolveStages()...) + } + tzOffsetMinutes := query.TzOffsetMinutes + if tzOffsetMinutes == 0 { + tzOffsetMinutes = defaultLegacyFinanceTZOffsetMinutes + } + pipeline := append(base, + bson.D{{Key: "$addFields", Value: bson.M{ + "financePaidAt": legacyPaidCoinSellerAtExpression(), + "financeCoinAmount": legacyFreightCoinAggregateExpression(), + }}}, + bson.D{{Key: "$facet", Value: bson.M{ + "total": mongo.Pipeline{ + bson.D{{Key: "$group", Value: bson.M{ + "_id": nil, + "billCount": bson.M{"$sum": 1}, + "usd": bson.M{"$sum": bson.M{"$ifNull": bson.A{"$amountUsd", 0}}}, + "coin": bson.M{"$sum": "$financeCoinAmount"}, + }}}, + }, + "daily": mongo.Pipeline{ + bson.D{{Key: "$group", Value: bson.M{ + "_id": bson.M{"$dateToString": bson.M{ + "format": "%Y-%m-%d", + "date": "$financePaidAt", + "timezone": legacyTimezoneOffset(tzOffsetMinutes), + }}, + "billCount": bson.M{"$sum": 1}, + "usd": bson.M{"$sum": bson.M{"$ifNull": bson.A{"$amountUsd", 0}}}, + "coin": bson.M{"$sum": "$financeCoinAmount"}, + }}}, + }, + "regions": mongo.Pipeline{ + bson.D{{Key: "$group", Value: bson.M{ + "_id": "$legacyBillCountry", + "billCount": bson.M{"$sum": 1}, + "usd": bson.M{"$sum": bson.M{"$ifNull": bson.A{"$amountUsd", 0}}}, + }}}, + }, + }}}, + ) + cursor, err := s.collection.Aggregate(ctx, pipeline) + if err != nil { + return stats, fmt.Errorf("aggregate Aslan paid coin seller bills: %w", err) + } + defer cursor.Close(ctx) + type bucketRow struct { + Date string `bson:"_id"` + BillCount int64 `bson:"billCount"` + USD any `bson:"usd"` + Coin int64 `bson:"coin"` + } + type regionRow struct { + Country string `bson:"_id"` + BillCount int64 `bson:"billCount"` + USD any `bson:"usd"` + } + var result struct { + Total []bucketRow `bson:"total"` + Daily []bucketRow `bson:"daily"` + Regions []regionRow `bson:"regions"` + } + if cursor.Next(ctx) { + if err := cursor.Decode(&result); err != nil { + return stats, fmt.Errorf("decode Aslan paid coin seller stats: %w", err) + } + } + if err := cursor.Err(); err != nil { + return stats, fmt.Errorf("iterate Aslan paid coin seller stats: %w", err) + } + if len(result.Total) > 0 { + stats.addBucket(rechargeBillSummaryBucketDTO{ + BillCount: result.Total[0].BillCount, + CoinAmount: result.Total[0].Coin, + USDMinorAmount: legacyDecimalToMinor(result.Total[0].USD), + }) + } + for _, row := range result.Daily { + stats.addDaily(row.Date, rechargeBillSummaryBucketDTO{ + BillCount: row.BillCount, + CoinAmount: row.Coin, + USDMinorAmount: legacyDecimalToMinor(row.USD), + }) + } + countryToRegion := s.legacyCountryRegionIndex(ctx) + for _, row := range result.Regions { + region, ok := countryToRegion[strings.ToUpper(strings.TrimSpace(row.Country))] + if !ok { + continue + } + stats.addRegion(region.RegionID, row.BillCount, legacyDecimalToMinor(row.USD)) + } + return stats, nil +} + +func (s *MongoRechargeBillSource) listFinancePaidCoinSellerRechargeBills(ctx context.Context, query financeCoinSellerRechargeQuery, limit int) ([]rechargeBillDTO, int64, error) { + filter, regionCodes, matchable, err := s.financePaidCoinSellerFilter(ctx, query) + if err != nil || !matchable { + return []rechargeBillDTO{}, 0, err + } + base := mongo.Pipeline{bson.D{{Key: "$match", Value: filter}}} + var total int64 + if len(regionCodes) == 0 { + total, err = s.collection.CountDocuments(ctx, filter) + } else { + base = append(base, legacyRegionLookupStages(regionCodes)...) + countCursor, countErr := s.collection.Aggregate(ctx, append(clonePipeline(base), bson.D{{Key: "$count", Value: "n"}})) + if countErr != nil { + return nil, 0, fmt.Errorf("count Aslan paid coin seller bills by region: %w", countErr) + } + if countCursor.Next(ctx) { + var row struct { + N int64 `bson:"n"` + } + if decodeErr := countCursor.Decode(&row); decodeErr != nil { + countCursor.Close(ctx) + return nil, 0, fmt.Errorf("decode Aslan paid coin seller bill count: %w", decodeErr) + } + total = row.N + } + if countErr := countCursor.Err(); countErr != nil { + countCursor.Close(ctx) + return nil, 0, fmt.Errorf("iterate Aslan paid coin seller bill count: %w", countErr) + } + countCursor.Close(ctx) + } + if err != nil { + return nil, 0, fmt.Errorf("count Aslan paid coin seller bills: %w", err) + } + if total == 0 || limit < 1 { + return []rechargeBillDTO{}, total, nil + } + base = append(base, + bson.D{{Key: "$addFields", Value: bson.M{"financePaidAt": legacyPaidCoinSellerAtExpression()}}}, + bson.D{{Key: "$sort", Value: bson.D{{Key: "financePaidAt", Value: -1}, {Key: "_id", Value: -1}}}}, + bson.D{{Key: "$limit", Value: int64(limit)}}, + ) + if len(regionCodes) == 0 { + // 无区域筛选时先分页再查用户国家,避免为整段历史订单执行 $lookup。 + base = append(base, legacyCountryResolveStages()...) + } + cursor, err := s.collection.Aggregate(ctx, base, options.Aggregate().SetAllowDiskUse(false)) + if err != nil { + return nil, 0, fmt.Errorf("query Aslan paid coin seller bills: %w", err) + } + defer cursor.Close(ctx) + countryToRegion := s.legacyCountryRegionIndex(ctx) + items := make([]rechargeBillDTO, 0, limit) + for cursor.Next(ctx) { + var document legacyPurchaseDocument + if err := cursor.Decode(&document); err != nil { + return nil, 0, fmt.Errorf("decode Aslan paid coin seller bill: %w", err) + } + item := legacyPaidCoinSellerRechargeBillDTO(s.config, document) + if region, ok := countryToRegion[strings.ToUpper(strings.TrimSpace(document.LegacyBillCountry))]; ok { + item.SellerRegionID = region.RegionID + item.TargetRegionID = region.RegionID + } + items = append(items, item) + } + if err := cursor.Err(); err != nil { + return nil, 0, fmt.Errorf("iterate Aslan paid coin seller bills: %w", err) + } + return items, total, nil +} + +func legacyPaidCoinSellerRechargeBillDTO(sourceConfig config.FinanceBillSourceConfig, document legacyPurchaseDocument) rechargeBillDTO { + paidAtMS := legacyPaidCoinSellerAtMS(document) + factoryCode := strings.ToUpper(strings.TrimSpace(document.Factory.FactoryCode)) + paidCurrency := strings.ToUpper(strings.TrimSpace(document.Currency)) + if paidCurrency == "" { + paidCurrency = "USD" + } + return rechargeBillDTO{ + AppCode: sourceConfig.AppCode, + TransactionID: legacyDocumentID(document.ID), + RechargeType: "coin_seller", + Status: "succeeded", + ExternalRef: strings.TrimSpace(document.OrderID), + SellerUserID: document.AcceptUserID, + CurrencyCode: "USD", + CoinAmount: legacyFreightCoinAmount(document), + USDMinorAmount: legacyDecimalToMinor(document.AmountUSD), + ProviderAmountMinor: legacyDecimalToMinor(document.Amount), + CreatedAtMS: paidAtMS, + ProviderCode: legacyProviderCode(factoryCode), + UserPaidCurrencyCode: paidCurrency, + UserPaidAmountMicro: legacyDecimalToMicro(document.Amount), + PaidSyncedAtMS: paidAtMS, + PolicyVersion: strings.ToUpper(strings.TrimSpace(document.TrackCommodityType)), + } +} + +func legacyPaidCoinSellerAtMS(document legacyPurchaseDocument) int64 { + for _, value := range []time.Time{document.UpdateTime, document.PurchaseDateMS, document.CreateTime} { + if !value.IsZero() { + return value.UnixMilli() + } + } + return 0 +} + +func legacyFreightCoinAmount(document legacyPurchaseDocument) int64 { + var typedTotal int64 + var allNumericTotal int64 + for _, product := range document.Products { + amount, err := strconv.ParseInt(strings.TrimSpace(product.Content), 10, 64) + if err != nil || amount <= 0 { + continue + } + allNumericTotal += amount + if legacyFreightCommodityType(product.Code) || legacyFreightCommodityType(product.Name) { + typedTotal += amount + } + } + if typedTotal > 0 { + return typedTotal + } + // 极老订单只在顶层 trackCommodityType 写类型;此时产品中的正数 content 才能作为该账单的发货金币。 + if legacyFreightCommodityType(document.TrackCommodityType) { + return allNumericTotal + } + return 0 +} + +func legacyFreightCommodityType(value string) bool { + switch strings.ToUpper(strings.TrimSpace(value)) { + case "FREIGHT_GOLD", "FREIGHT_GOLD_SUPER": + return true + default: + return false + } +} diff --git a/server/admin/internal/modules/payment/aslan_paid_coin_seller_source_test.go b/server/admin/internal/modules/payment/aslan_paid_coin_seller_source_test.go new file mode 100644 index 00000000..bb0274c5 --- /dev/null +++ b/server/admin/internal/modules/payment/aslan_paid_coin_seller_source_test.go @@ -0,0 +1,209 @@ +package payment + +import ( + "context" + "testing" + "time" + + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" +) + +func TestAslanPaidCoinSellerFilterUsesPaymentFacts(t *testing.T) { + source := &MongoRechargeBillSource{ + collection: &mongo.Collection{}, + config: aslanBillSourceConfig(), + regionResolvers: []legacyRegionCountryResolver{staticLegacyRegionResolver{ + codes: []string{"eg"}, handled: true, + }}, + } + filter, regionCodes, matchable, err := source.financePaidCoinSellerFilter(context.Background(), financeCoinSellerRechargeQuery{ + Keyword: "x5ctfib7800289mrkm5fco0A10001910", + RegionID: 1001, + StartAtMS: 1_784_000_000_000, + EndAtMS: 1_785_000_000_000, + TargetUserID: 2_070_458_148_788_715_521, + }) + if err != nil || !matchable { + t.Fatalf("financePaidCoinSellerFilter err=%v matchable=%v", err, matchable) + } + if filter["sysOrigin"] != "ATYOU" || filter["status"] != "SUCCESS" { + t.Fatalf("payment status boundary missing: %#v", filter) + } + if filter["acceptUserId"] != int64(2_070_458_148_788_715_521) { + t.Fatalf("seller filter missing: %#v", filter) + } + if len(regionCodes) != 1 || regionCodes[0] != "EG" { + t.Fatalf("region code mismatch: %#v", regionCodes) + } + conditions, ok := filter["$and"].(bson.A) + if !ok || len(conditions) != 3 { + t.Fatalf("freight/keyword/time conditions missing: %#v", filter) + } + if got := len(legacyFreightCommodityMatchConditions()); got != len(legacyFreightCommodityFields) { + t.Fatalf("freight compatibility fields=%d want=%d", got, len(legacyFreightCommodityFields)) + } + if _, exists := filter["recharge_type"]; exists { + t.Fatalf("wallet running-water recharge_type must not enter Mongo bill filter: %#v", filter) + } +} + +func TestLegacyPaidCoinSellerRechargeBillDTOUsesOriginalBillAmounts(t *testing.T) { + providerAmount, err := bson.ParseDecimal128("4726") + if err != nil { + t.Fatalf("parse provider amount: %v", err) + } + usdAmount, err := bson.ParseDecimal128("100.00") + if err != nil { + t.Fatalf("parse usd amount: %v", err) + } + createdAt := time.Date(2026, 7, 14, 12, 14, 26, 499_000_000, time.UTC) + paidAt := time.Date(2026, 7, 14, 12, 15, 14, 777_000_000, time.UTC) + document := legacyPurchaseDocument{ + ID: int64(2_077_003_764_199_862_273), + OrderID: "x5ctfib7800289mrkm5fco0A10001910", + AcceptUserID: 2_070_458_148_788_715_521, + CountryCode: "EG", + Currency: "EGP", + Amount: providerAmount, + AmountUSD: usdAmount, + Status: "SUCCESS", + TrackCommodityType: "FREIGHT_GOLD", + Factory: legacyPurchaseFactory{Platform: "H5", FactoryCode: "MIFA_PAY"}, + Products: []legacyPurchaseProduct{{Code: "FREIGHT_GOLD", Name: "FREIGHT_GOLD", Content: "8800000"}}, + CreateTime: createdAt, + UpdateTime: paidAt, + LegacyBillCountry: "EG", + } + dto := legacyPaidCoinSellerRechargeBillDTO(aslanBillSourceConfig(), document) + if dto.RechargeType != "coin_seller" || dto.Status != "succeeded" { + t.Fatalf("coin seller bill identity mismatch: %+v", dto) + } + if dto.ExternalRef != document.OrderID || dto.SellerUserID != document.AcceptUserID { + t.Fatalf("provider/seller identity mismatch: %+v", dto) + } + if dto.USDMinorAmount != 10_000 || dto.CoinAmount != 8_800_000 { + t.Fatalf("must use original bill USD/product amount: %+v", dto) + } + if dto.ProviderAmountMinor != 472_600 || dto.UserPaidCurrencyCode != "EGP" || dto.UserPaidAmountMicro != 4_726_000_000 { + t.Fatalf("provider paid amount mismatch: %+v", dto) + } + if dto.CreatedAtMS != paidAt.UnixMilli() || dto.PaidSyncedAtMS != paidAt.UnixMilli() { + t.Fatalf("successful payment time mismatch: %+v", dto) + } + if dto.PolicyVersion != "FREIGHT_GOLD" { + t.Fatalf("commodity type mismatch: %+v", dto) + } +} + +func TestLegacyFreightCoinAmountFallsBackToTopLevelType(t *testing.T) { + document := legacyPurchaseDocument{ + TrackCommodityType: "FREIGHT_GOLD", + Products: []legacyPurchaseProduct{ + {Name: "LEGACY_PRODUCT", Content: "8800000"}, + {Name: "PROPS", Content: "not-a-number"}, + }, + } + if got := legacyFreightCoinAmount(document); got != 8_800_000 { + t.Fatalf("legacy freight coin amount=%d", got) + } +} + +type fakeAslanPaidCoinSellerSource struct { + stats financeCoinSellerRechargeStats + items []rechargeBillDTO + total int64 + statsCalls int + listCalls int +} + +func (s *fakeAslanPaidCoinSellerSource) AppCode() string { return "aslan" } +func (s *fakeAslanPaidCoinSellerSource) AppName() string { return "Aslan" } +func (s *fakeAslanPaidCoinSellerSource) ListRechargeBills(context.Context, legacyRechargeBillQuery) ([]rechargeBillDTO, int64, error) { + return []rechargeBillDTO{}, 0, nil +} +func (s *fakeAslanPaidCoinSellerSource) SummarizeRechargeBills(context.Context, legacyRechargeBillQuery) (rechargeBillSummaryDTO, error) { + return rechargeBillSummaryDTO{}, nil +} +func (s *fakeAslanPaidCoinSellerSource) SupportsGooglePaidSync() bool { return false } +func (s *fakeAslanPaidCoinSellerSource) ListPendingGooglePaidTransactionIDs(context.Context, int) ([]string, error) { + return []string{}, nil +} +func (s *fakeAslanPaidCoinSellerSource) RefreshGooglePaidDetails(context.Context, []string) ([]googleRechargePaidDTO, error) { + return []googleRechargePaidDTO{}, nil +} +func (s *fakeAslanPaidCoinSellerSource) Overview(context.Context, legacyRechargeBillQuery, int32) (rechargeBillOverviewDTO, error) { + return rechargeBillOverviewDTO{Daily: []rechargeBillDailyBucketDTO{}, Regions: []rechargeBillRegionBucketDTO{}}, nil +} +func (s *fakeAslanPaidCoinSellerSource) financePaidCoinSellerRechargeStats(context.Context, financeCoinSellerRechargeQuery) (financeCoinSellerRechargeStats, error) { + s.statsCalls++ + return s.stats, nil +} +func (s *fakeAslanPaidCoinSellerSource) listFinancePaidCoinSellerRechargeBills(context.Context, financeCoinSellerRechargeQuery, int) ([]rechargeBillDTO, int64, error) { + s.listCalls++ + return append([]rechargeBillDTO(nil), s.items...), s.total, nil +} + +func TestFinanceCoinSellerIncludesAslanPaidBills(t *testing.T) { + source := &fakeAslanPaidCoinSellerSource{ + stats: financeCoinSellerRechargeStats{ + Total: rechargeBillSummaryBucketDTO{BillCount: 1, CoinAmount: 8_800_000, USDMinorAmount: 10_000}, + Daily: map[string]rechargeBillSummaryBucketDTO{ + "2026-07-14": {BillCount: 1, CoinAmount: 8_800_000, USDMinorAmount: 10_000}, + }, + Regions: []rechargeBillRegionBucketDTO{{RegionID: 9, BillCount: 1, UsdMinorAmount: 10_000}}, + }, + items: []rechargeBillDTO{{ + AppCode: "aslan", TransactionID: "2077003764199862273", ExternalRef: "x5ctfib7800289mrkm5fco0A10001910", + RechargeType: "coin_seller", ProviderCode: "mifa_pay", USDMinorAmount: 10_000, CoinAmount: 8_800_000, + }}, + total: 1, + } + handler := New(nil, nil, nil, nil, nil, WithRechargeBillSources(source)) + stats, err := handler.financeCoinSellerRechargeStats(context.Background(), "aslan", financeCoinSellerRechargeQuery{}) + if err != nil { + t.Fatalf("financeCoinSellerRechargeStats: %v", err) + } + if stats.Total.USDMinorAmount != 10_000 || stats.Total.CoinAmount != 8_800_000 || stats.Total.BillCount != 1 { + t.Fatalf("paid bill stats missing: %+v", stats.Total) + } + if stats.Daily["2026-07-14"].USDMinorAmount != 10_000 || len(stats.Regions) != 1 || stats.Regions[0].RegionID != 9 { + t.Fatalf("paid bill dimensions missing: %+v", stats) + } + items, total, err := handler.listFinanceCoinSellerRechargeBills(context.Background(), "aslan", financeCoinSellerRechargeQuery{Page: 1, PageSize: 20}) + if err != nil { + t.Fatalf("listFinanceCoinSellerRechargeBills: %v", err) + } + if total != 1 || len(items) != 1 || items[0].USDMinorAmount != 10_000 || items[0].ExternalRef != "x5ctfib7800289mrkm5fco0A10001910" { + t.Fatalf("paid bill list mismatch: total=%d items=%+v", total, items) + } + if source.statsCalls != 1 || source.listCalls != 1 { + t.Fatalf("paid source calls mismatch: stats=%d list=%d", source.statsCalls, source.listCalls) + } +} + +func TestFinanceCoinSellerBillDedupKeepsOriginalPaymentBill(t *testing.T) { + original := rechargeBillDTO{TransactionID: "mongo", ExternalRef: "ORDER-1", ProviderCode: "MIFA_PAY", USDMinorAmount: 10_000} + operatorBound := rechargeBillDTO{TransactionID: "admin", ExternalRef: "order-1", ProviderCode: "mifapay", USDMinorAmount: 11_000} + items, duplicateCount := deduplicateFinanceCoinSellerRechargeBills([]rechargeBillDTO{original, operatorBound}) + if duplicateCount != 1 || len(items) != 1 { + t.Fatalf("dedup mismatch: duplicates=%d items=%+v", duplicateCount, items) + } + if items[0].TransactionID != "mongo" || items[0].USDMinorAmount != 10_000 { + t.Fatalf("original payment bill must win: %+v", items[0]) + } +} + +func TestFinancePaidCoinSellerSourceIsAslanOnly(t *testing.T) { + source := &fakeAslanPaidCoinSellerSource{} + handler := New(nil, nil, nil, nil, nil, WithRechargeBillSources(source)) + if handler.financePaidCoinSellerRechargeSource("aslan") == nil { + t.Fatalf("Aslan paid source should be registered") + } + if handler.financePaidCoinSellerRechargeSource("yumi") != nil { + t.Fatalf("Aslan paid source must not expand to Yumi") + } +} + +var _ RechargeBillSource = (*fakeAslanPaidCoinSellerSource)(nil) +var _ financePaidCoinSellerRechargeSource = (*fakeAslanPaidCoinSellerSource)(nil) diff --git a/server/admin/internal/modules/payment/finance_coin_seller_recharge.go b/server/admin/internal/modules/payment/finance_coin_seller_recharge.go index dae7a98d..7a52d287 100644 --- a/server/admin/internal/modules/payment/finance_coin_seller_recharge.go +++ b/server/admin/internal/modules/payment/finance_coin_seller_recharge.go @@ -145,6 +145,21 @@ func (h *Handler) financeCoinSellerRechargeStats(ctx context.Context, appCode st return stats, nil } query.RegionID = h.normalizeFinanceCoinSellerRegionID(ctx, appCode, query.RegionID) + if paidSource := h.financePaidCoinSellerRechargeSource(appCode); paidSource != nil { + paidStats, err := paidSource.financePaidCoinSellerRechargeStats(ctx, query) + if err != nil { + return stats, err + } + // Aslan legacy H5 的 SUCCESS/FREIGHT_GOLD Mongo 订单是支付账单事实; + // 这里只合并该事实,不读取 WebConsole 手填金额或钱包发货流水。 + stats.addBucket(paidStats.Total) + for date, bucket := range paidStats.Daily { + stats.addDaily(date, bucket) + } + for _, region := range paidStats.Regions { + stats.addRegion(region.RegionID, region.BillCount, region.UsdMinorAmount) + } + } if h != nil && h.store != nil { repoStats, err := h.store.CoinSellerRechargeOrderStats(repository.CoinSellerRechargeOrderStatsOptions{ AppCode: appCode, @@ -286,6 +301,15 @@ func (h *Handler) listFinanceCoinSellerRechargeBills(ctx context.Context, appCod prefetch := financeRechargePrefetch(page, pageSize, query.MaxPageSize) items := make([]rechargeBillDTO, 0, prefetch*2) var total int64 + if paidSource := h.financePaidCoinSellerRechargeSource(appCode); paidSource != nil { + paidItems, paidTotal, err := paidSource.listFinancePaidCoinSellerRechargeBills(ctx, query, prefetch) + if err != nil { + return nil, 0, err + } + // 真实 H5 账单先进入结果;若同一个支付订单后来又被后台绑定,去重时保留原始账单金额和商品金币。 + items = append(items, paidItems...) + total += paidTotal + } if h != nil && h.store != nil { orders, orderTotal, err := h.store.ListCoinSellerRechargeOrders(repository.CoinSellerRechargeOrderListOptions{ Page: 1, @@ -318,6 +342,14 @@ func (h *Handler) listFinanceCoinSellerRechargeBills(ctx context.Context, appCod total += h5Total items = append(items, h5Items...) } + var duplicateCount int + items, duplicateCount = deduplicateFinanceCoinSellerRechargeBills(items) + if duplicateCount > 0 { + total -= int64(duplicateCount) + if total < 0 { + total = 0 + } + } sortRechargeBills(items) offset := (page - 1) * pageSize if offset >= len(items) { @@ -330,6 +362,39 @@ func (h *Handler) listFinanceCoinSellerRechargeBills(ctx context.Context, appCod return items[offset:end], total, nil } +func deduplicateFinanceCoinSellerRechargeBills(items []rechargeBillDTO) ([]rechargeBillDTO, int) { + seen := make(map[string]struct{}, len(items)) + out := make([]rechargeBillDTO, 0, len(items)) + duplicates := 0 + for _, item := range items { + identity := financeCoinSellerRechargeBillIdentity(item) + if identity == "" { + out = append(out, item) + continue + } + if _, exists := seen[identity]; exists { + duplicates++ + continue + } + seen[identity] = struct{}{} + out = append(out, item) + } + return out, duplicates +} + +func financeCoinSellerRechargeBillIdentity(item rechargeBillDTO) string { + externalRef := strings.ToLower(strings.TrimSpace(item.ExternalRef)) + if externalRef != "" { + provider := strings.NewReplacer("_", "", "-", "", " ", "").Replace(strings.ToLower(strings.TrimSpace(item.ProviderCode))) + return "provider:" + provider + ":" + externalRef + } + transactionID := strings.ToLower(strings.TrimSpace(item.TransactionID)) + if transactionID == "" { + return "" + } + return "transaction:" + transactionID +} + func (h *Handler) listFinanceAllRechargeBills(ctx context.Context, appCode string, source RechargeBillSource, query financeCoinSellerRechargeQuery) ([]rechargeBillDTO, int64, error) { page, pageSize := financeCoinSellerPage(query.Page, query.PageSize, query.MaxPageSize) prefetch := financeRechargePrefetch(page, pageSize, query.MaxPageSize) diff --git a/server/admin/internal/modules/payment/handler_test.go b/server/admin/internal/modules/payment/handler_test.go index d12c34da..26d3ccde 100644 --- a/server/admin/internal/modules/payment/handler_test.go +++ b/server/admin/internal/modules/payment/handler_test.go @@ -6,6 +6,7 @@ import ( "encoding/json" "net/http" "net/http/httptest" + "slices" "testing" "hyapp-admin-server/internal/appctx" @@ -20,6 +21,21 @@ import ( "gorm.io/gorm" ) +func TestMoneyScopeReadPermissionsIncludeWithdrawalWorkspaces(t *testing.T) { + t.Parallel() + for _, permission := range []string{ + financeViewPermission, + "finance-withdrawal:view", + "finance-withdrawal:audit", + "operations-withdrawal:view", + "operations-withdrawal:audit", + } { + if !slices.Contains(moneyScopeReadPermissions, permission) { + t.Fatalf("money scope read permission missing %s", permission) + } + } +} + func TestListRechargeBillsResolvesDisplayIDsBeforeWalletFilter(t *testing.T) { db, sqlMock, err := sqlmock.New() if err != nil { diff --git a/server/admin/internal/modules/payment/legacy_bill_source.go b/server/admin/internal/modules/payment/legacy_bill_source.go index 41e2e979..4687f088 100644 --- a/server/admin/internal/modules/payment/legacy_bill_source.go +++ b/server/admin/internal/modules/payment/legacy_bill_source.go @@ -308,18 +308,20 @@ func (s dashboardCoinSellerRechargeStatsSource) CoinSellerRechargeStats(ctx cont // legacyPurchaseDocument 对应 chatapp3-java 的 InAppPurchaseDetails Mongo 文档(只取展示需要的字段)。 type legacyPurchaseDocument struct { - ID any `bson:"_id"` - OrderID string `bson:"orderId"` - AcceptUserID int64 `bson:"acceptUserId"` - CountryCode string `bson:"countryCode"` - Currency string `bson:"currency"` - Amount any `bson:"amount"` - AmountUSD any `bson:"amountUsd"` - Status string `bson:"status"` - Factory legacyPurchaseFactory `bson:"factory"` - Products []legacyPurchaseProduct `bson:"products"` - CreateTime time.Time `bson:"createTime"` - PurchaseDateMS time.Time `bson:"purchaseDateMs"` + ID any `bson:"_id"` + OrderID string `bson:"orderId"` + AcceptUserID int64 `bson:"acceptUserId"` + CountryCode string `bson:"countryCode"` + Currency string `bson:"currency"` + Amount any `bson:"amount"` + AmountUSD any `bson:"amountUsd"` + Status string `bson:"status"` + TrackCommodityType string `bson:"trackCommodityType"` + Factory legacyPurchaseFactory `bson:"factory"` + Products []legacyPurchaseProduct `bson:"products"` + CreateTime time.Time `bson:"createTime"` + UpdateTime time.Time `bson:"updateTime"` + PurchaseDateMS time.Time `bson:"purchaseDateMs"` // LegacyBillCountry 由聚合阶段(legacyCountryResolveStages)解析:账单国家码优先,回退付款用户资料。 LegacyBillCountry string `bson:"legacyBillCountry"` } @@ -330,6 +332,7 @@ type legacyPurchaseFactory struct { } type legacyPurchaseProduct struct { + Code string `bson:"code"` Name string `bson:"name"` Content string `bson:"content"` } diff --git a/server/admin/internal/modules/payment/routes.go b/server/admin/internal/modules/payment/routes.go index 43a44d86..c1638e6f 100644 --- a/server/admin/internal/modules/payment/routes.go +++ b/server/admin/internal/modules/payment/routes.go @@ -6,6 +6,14 @@ import ( "github.com/gin-gonic/gin" ) +var moneyScopeReadPermissions = []string{ + financeViewPermission, + "finance-withdrawal:view", + "finance-withdrawal:audit", + "operations-withdrawal:view", + "operations-withdrawal:audit", +} + func RegisterRoutes(workspaceProtected *gin.RouterGroup, appProtected *gin.RouterGroup, h *Handler) { if h == nil { return @@ -19,7 +27,8 @@ func RegisterRoutes(workspaceProtected *gin.RouterGroup, appProtected *gin.Route workspaceProtected.POST("/admin/payment/recharge-bills/google-paid/refresh", middleware.RequirePermission("payment-bill:refresh"), h.RefreshGoogleRechargePaidDetails) workspaceProtected.GET("/admin/payment/recharge-regions", middleware.RequirePermission("payment-bill:view"), h.ListRechargeBillRegions) workspaceProtected.GET("/admin/payment/recharge-apps", middleware.RequirePermission("payment-bill:view"), h.ListRechargeBillApps) - workspaceProtected.GET("/admin/finance/scope", middleware.RequirePermission(financeViewPermission), h.GetMoneyScope) + // 用户提现的运营/财务页共用 MoneyAccess App 目录;这里只放开范围读取,不会赋予任何支付或审核写权限。 + workspaceProtected.GET("/admin/finance/scope", middleware.RequireAnyPermission(moneyScopeReadPermissions...), h.GetMoneyScope) workspaceProtected.GET("/admin/money/scope", middleware.RequireAnyPermission(financeViewPermission, legacyMoneyViewPermission), h.GetMoneyScope) workspaceProtected.GET("/admin/money/performance", middleware.RequireAnyPermission(financeViewPermission, legacyMoneyViewPermission), h.GetMoneyPerformance) workspaceProtected.GET("/admin/payment/temporary-links", middleware.RequirePermission("payment-temporary-link:view"), h.ListTemporaryPaymentLinks) diff --git a/server/admin/internal/modules/resource/handler.go b/server/admin/internal/modules/resource/handler.go index 53ce8041..e8ddd647 100644 --- a/server/admin/internal/modules/resource/handler.go +++ b/server/admin/internal/modules/resource/handler.go @@ -65,6 +65,47 @@ func (h *Handler) ListResources(c *gin.Context) { response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: resp.GetTotal()}) } +// ListExternalGrantResources exposes only the owner-approved manager grant catalog. +// VIP trial cards remain on their dedicated API because a generic entitlement grant +// would not update the VIP state projection. The external route requires the complete +// grant permission bundle before this handler is reached. +func (h *Handler) ListExternalGrantResources(c *gin.Context) { + options := shared.ListOptions(c) + 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")), + Keyword: options.Keyword, + Page: int32(options.Page), + PageSize: int32(options.PageSize), + ActiveOnly: true, + ManagerGrantOnly: true, + }) + if err != nil { + response.ServerError(c, "获取可发放资源失败") + return + } + items := make([]resourceDTO, 0, len(resp.GetResources())) + excluded := int64(0) + for _, item := range resp.GetResources() { + if item.GetResourceType() == resourceTypeVIPTrialCard { + excluded++ + continue + } + items = append(items, resourceFromProto(item)) + } + // ManagerGrantOnly is indexed owner data; excluding a dedicated-flow item here is + // defense in depth. Total can only be reduced by rows observed on this page because + // the wallet contract does not expose a negative type filter. + total := resp.GetTotal() - excluded + if total < int64(len(items)) { + total = int64(len(items)) + } + response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: total}) +} + func (h *Handler) GetResource(c *gin.Context) { resourceID, ok := parseID(c, "resource_id") if !ok { @@ -629,6 +670,17 @@ func (h *Handler) DisableGift(c *gin.Context) { } func (h *Handler) GrantResource(c *gin.Context) { + h.grantResource(c, false) +} + +// GrantExternalResource keeps main-admin behavior unchanged while closing the ID +// bypass on the external portal: callers may only submit an active resource that the +// owner explicitly marked grantable for managers. +func (h *Handler) GrantExternalResource(c *gin.Context) { + h.grantResource(c, true) +} + +func (h *Handler) grantResource(c *gin.Context, external bool) { var req grantResourceRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "资源赠送参数不正确") @@ -639,10 +691,17 @@ func (h *Handler) GrantResource(c *gin.Context) { response.BadRequest(c, err.Error()) return } - if err := h.validateGenericGrantResource(c, req.ResourceID); err != nil { + if err := h.validateGenericGrantResource(c, req.ResourceID, external); err != nil { response.BadRequest(c, err.Error()) return } + grantSource := "admin" + if external { + // Wallet atomically rechecks manager_grant_enabled for manager_center at grant + // time. This closes the GetResource/GrantResource race and records the actual + // external operator channel in the entitlement ledger. + grantSource = grantSourceManagerCenter + } resp, err := h.wallet.GrantResource(c.Request.Context(), &walletv1.GrantResourceRequest{ CommandId: strings.TrimSpace(req.CommandID), AppCode: appctx.FromContext(c.Request.Context()), @@ -652,7 +711,7 @@ func (h *Handler) GrantResource(c *gin.Context) { DurationMs: req.DurationMS, Reason: strings.TrimSpace(req.Reason), OperatorUserId: actorID(c), - GrantSource: "admin", + GrantSource: grantSource, }) if err != nil { response.BadRequest(c, err.Error()) @@ -696,7 +755,7 @@ func (h *Handler) GrantResourceGroup(c *gin.Context) { response.Created(c, grant) } -func (h *Handler) validateGenericGrantResource(c *gin.Context, resourceID int64) error { +func (h *Handler) validateGenericGrantResource(c *gin.Context, resourceID int64, requireManagerGrant bool) error { resp, err := h.wallet.GetResource(c.Request.Context(), &walletv1.GetResourceRequest{ RequestId: middleware.CurrentRequestID(c), AppCode: appctx.FromContext(c.Request.Context()), @@ -705,6 +764,9 @@ func (h *Handler) validateGenericGrantResource(c *gin.Context, resourceID int64) if err != nil { return err } + if requireManagerGrant && (resp.GetResource().GetStatus() != "active" || !resp.GetResource().GetGrantable() || !resp.GetResource().GetManagerGrantEnabled()) { + return fmt.Errorf("该资源未开放外管发放") + } // VIP 体验卡除了资源权益,还必须同步写入卡片等级、独立失效时间和 VIP 状态投影; // 通用资源赠送只会创建 entitlement,放行会产生“背包可见但无法生效”的半成品数据。 if resp.GetResource().GetResourceType() == resourceTypeVIPTrialCard { @@ -765,6 +827,48 @@ func (h *Handler) RevokeResourceGrant(c *gin.Context) { response.OK(c, grant) } +func (h *Handler) RevokeUserResource(c *gin.Context) { + userID, err := strconv.ParseInt(strings.TrimSpace(c.Param("user_id")), 10, 64) + if err != nil || userID <= 0 { + response.BadRequest(c, "用户 ID 不正确") + return + } + entitlementID := strings.TrimSpace(c.Param("entitlement_id")) + if entitlementID == "" { + response.BadRequest(c, "用户素材权益不存在") + return + } + var req revokeUserResourceRequest + if err := c.ShouldBindJSON(&req); err != nil || strings.TrimSpace(req.Reason) == "" { + response.BadRequest(c, "请填写素材撤回原因") + return + } + + resp, err := h.wallet.RevokeUserResource(c.Request.Context(), &walletv1.RevokeUserResourceRequest{ + RequestId: middleware.CurrentRequestID(c), + AppCode: appctx.FromContext(c.Request.Context()), + UserId: userID, + EntitlementId: entitlementID, + Reason: strings.TrimSpace(req.Reason), + OperatorUserId: actorID(c), + }) + if err != nil { + response.BadRequest(c, err.Error()) + return + } + resource := resp.GetResource() + // 审计对象使用 entitlement 而不是 source grant:同一资源组发放可包含多个素材,必须能追溯本次只撤回了哪一个。 + h.auditLog(c, "revoke-user-resource", "user_resource_entitlements", entitlementID, "success", fmt.Sprintf("target_user_id=%d resource_id=%d", userID, resource.GetResourceId())) + response.OK(c, gin.H{ + "entitlementId": resource.GetEntitlementId(), + "resourceId": resource.GetResourceId(), + "status": resource.GetStatus(), + "remainingQuantity": resource.GetRemainingQuantity(), + "equipped": resource.GetEquipped(), + "updatedAtMs": resource.GetUpdatedAtMs(), + }) +} + func (h *Handler) LookupResourceGrantTarget(c *gin.Context) { keyword := strings.TrimSpace(firstQuery(c, "user_id", "userId", "keyword")) if keyword == "" { diff --git a/server/admin/internal/modules/resource/handler_test.go b/server/admin/internal/modules/resource/handler_test.go index 5924530e..268e0bdc 100644 --- a/server/admin/internal/modules/resource/handler_test.go +++ b/server/admin/internal/modules/resource/handler_test.go @@ -235,6 +235,83 @@ func TestGenericResourceGrantRejectsVIPTrialCard(t *testing.T) { } } +func TestExternalResourceGrantRejectsIDOutsideManagerGrantCatalog(t *testing.T) { + wallet := &mockResourceWallet{resources: map[int64]*walletv1.Resource{ + 11: {AppCode: "lalu", ResourceId: 11, ResourceType: "badge", Status: "active", Grantable: true, ManagerGrantEnabled: true}, + 12: {AppCode: "lalu", ResourceId: 12, ResourceType: "badge", Status: "active", Grantable: true, ManagerGrantEnabled: false}, + }} + handler := New(wallet, nil, nil, time.Second, nil) + router := gin.New() + router.Use(func(c *gin.Context) { + c.Request = c.Request.WithContext(appctx.WithContext(c.Request.Context(), "lalu")) + c.Set(middleware.ContextRequestID, "external-grant-test") + c.Set(middleware.ContextUserID, uint(7)) + c.Next() + }) + router.POST("/external-grant", handler.GrantExternalResource) + + denied := httptest.NewRecorder() + deniedRequest := httptest.NewRequest(http.MethodPost, "/external-grant", strings.NewReader(`{"commandId":"grant-denied","targetUserId":"318705991371722752","resourceId":12,"quantity":1,"durationMs":0,"reason":"manual"}`)) + deniedRequest.Header.Set("Content-Type", "application/json") + router.ServeHTTP(denied, deniedRequest) + if denied.Code != http.StatusBadRequest || !strings.Contains(denied.Body.String(), "未开放外管发放") || len(wallet.grantRequests) != 0 { + t.Fatalf("catalog bypass was not rejected: status=%d body=%s grants=%d", denied.Code, denied.Body.String(), len(wallet.grantRequests)) + } + + allowed := httptest.NewRecorder() + allowedRequest := httptest.NewRequest(http.MethodPost, "/external-grant", strings.NewReader(`{"commandId":"grant-allowed","targetUserId":"318705991371722752","resourceId":11,"quantity":1,"durationMs":0,"reason":"manual"}`)) + allowedRequest.Header.Set("Content-Type", "application/json") + router.ServeHTTP(allowed, allowedRequest) + if allowed.Code != http.StatusCreated || len(wallet.grantRequests) != 1 || wallet.grantRequests[0].GetResourceId() != 11 || wallet.grantRequests[0].GetGrantSource() != "manager_center" { + t.Fatalf("manager grantable resource failed: status=%d body=%s grants=%+v", allowed.Code, allowed.Body.String(), wallet.grantRequests) + } +} + +func TestMainAdminResourceGrantKeepsAdminSource(t *testing.T) { + wallet := &mockResourceWallet{resources: map[int64]*walletv1.Resource{ + 11: {AppCode: "lalu", ResourceId: 11, ResourceType: "badge", Status: "active", Grantable: true}, + }} + handler := New(wallet, nil, nil, time.Second, nil) + router := gin.New() + router.Use(func(c *gin.Context) { + c.Request = c.Request.WithContext(appctx.WithContext(c.Request.Context(), "lalu")) + c.Set(middleware.ContextRequestID, "admin-grant-source-test") + c.Set(middleware.ContextUserID, uint(7)) + c.Next() + }) + router.POST("/admin-grant", handler.GrantResource) + recorder := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodPost, "/admin-grant", strings.NewReader(`{"commandId":"grant-admin","targetUserId":"318705991371722752","resourceId":11,"quantity":1,"reason":"manual"}`)) + request.Header.Set("Content-Type", "application/json") + router.ServeHTTP(recorder, request) + if recorder.Code != http.StatusCreated || len(wallet.grantRequests) != 1 || wallet.grantRequests[0].GetGrantSource() != "admin" { + t.Fatalf("main admin grant source changed: status=%d request=%+v body=%s", recorder.Code, wallet.grantRequests, recorder.Body.String()) + } +} + +func TestExternalResourceListUsesManagerCatalogAndHidesVIPTrialCard(t *testing.T) { + wallet := &mockResourceWallet{listedResources: []*walletv1.Resource{ + {AppCode: "lalu", ResourceId: 11, ResourceType: "badge", Status: "active", Grantable: true, ManagerGrantEnabled: true}, + {AppCode: "lalu", ResourceId: 99, ResourceType: resourceTypeVIPTrialCard, Status: "active", Grantable: true, ManagerGrantEnabled: true}, + }} + handler := New(wallet, nil, nil, time.Second, nil) + router := gin.New() + router.Use(func(c *gin.Context) { + c.Request = c.Request.WithContext(appctx.WithContext(c.Request.Context(), "lalu")) + c.Set(middleware.ContextRequestID, "external-resource-list-test") + c.Next() + }) + router.GET("/external-resources", handler.ListExternalGrantResources) + recorder := httptest.NewRecorder() + router.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/external-resources?page=1&page_size=20", nil)) + if recorder.Code != http.StatusOK || strings.Contains(recorder.Body.String(), `"id":99`) { + t.Fatalf("external list status=%d body=%s", recorder.Code, recorder.Body.String()) + } + if len(wallet.listResourceRequests) != 1 || !wallet.listResourceRequests[0].GetActiveOnly() || !wallet.listResourceRequests[0].GetManagerGrantOnly() { + t.Fatalf("external list did not use manager catalog: %+v", wallet.listResourceRequests) + } +} + func TestGenericResourceGroupGrantRejectsVIPTrialCardItem(t *testing.T) { wallet := &mockResourceWallet{resourceGroups: map[int64]*walletv1.ResourceGroup{ 88: { @@ -332,6 +409,29 @@ func TestListResourceGrantsResolvesDisplayIDBeforeWalletFilter(t *testing.T) { } } +func TestRevokeUserResourceTargetsOneEntitlement(t *testing.T) { + wallet := &mockResourceWallet{} + router := newResourceHandlerTestRouter(New(wallet, nil, nil, time.Second, nil)) + recorder := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodPost, "/admin/users/318705991371722752/resources/ent-host-badge/revoke", strings.NewReader(`{"reason":"remove host badge"}`)) + request.Header.Set("Content-Type", "application/json") + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("revoke user resource status mismatch: %d %s", recorder.Code, recorder.Body.String()) + } + if len(wallet.revokeUserResourceRequests) != 1 { + t.Fatalf("expected one precise revoke request, got %d", len(wallet.revokeUserResourceRequests)) + } + req := wallet.revokeUserResourceRequests[0] + if req.GetUserId() != 318705991371722752 || req.GetEntitlementId() != "ent-host-badge" || req.GetReason() != "remove host badge" || req.GetOperatorUserId() != 7 { + t.Fatalf("precise revoke request mismatch: %+v", req) + } + if !strings.Contains(recorder.Body.String(), `"entitlementId":"ent-host-badge"`) || !strings.Contains(recorder.Body.String(), `"status":"revoked"`) { + t.Fatalf("precise revoke response mismatch: %s", recorder.Body.String()) + } +} + func newResourceHandlerTestRouter(handler *Handler) *gin.Engine { gin.SetMode(gin.TestMode) router := gin.New() @@ -370,14 +470,43 @@ func newResourceHandlerTestRouter(handler *Handler) *gin.Engine { type mockResourceWallet struct { walletclient.Client - resources map[int64]*walletv1.Resource - resourceGroups map[int64]*walletv1.ResourceGroup - updates []*walletv1.UpdateResourceRequest - deletedResources []*walletv1.DeleteResourceRequest - batchDeletedResources []*walletv1.BatchDeleteResourcesRequest - batchCreatedGifts []*walletv1.BatchCreateGiftConfigsRequest - deletedGifts []*walletv1.DeleteGiftConfigRequest - listGrantRequests []*walletv1.ListResourceGrantsRequest + resources map[int64]*walletv1.Resource + resourceGroups map[int64]*walletv1.ResourceGroup + updates []*walletv1.UpdateResourceRequest + deletedResources []*walletv1.DeleteResourceRequest + batchDeletedResources []*walletv1.BatchDeleteResourcesRequest + batchCreatedGifts []*walletv1.BatchCreateGiftConfigsRequest + deletedGifts []*walletv1.DeleteGiftConfigRequest + listGrantRequests []*walletv1.ListResourceGrantsRequest + listResourceRequests []*walletv1.ListResourcesRequest + listedResources []*walletv1.Resource + grantRequests []*walletv1.GrantResourceRequest + revokeUserResourceRequests []*walletv1.RevokeUserResourceRequest +} + +func (m *mockResourceWallet) ListResources(_ context.Context, req *walletv1.ListResourcesRequest) (*walletv1.ListResourcesResponse, error) { + m.listResourceRequests = append(m.listResourceRequests, req) + return &walletv1.ListResourcesResponse{Resources: m.listedResources, Total: int64(len(m.listedResources))}, nil +} + +func (m *mockResourceWallet) GrantResource(_ context.Context, req *walletv1.GrantResourceRequest) (*walletv1.ResourceGrantResponse, error) { + m.grantRequests = append(m.grantRequests, req) + return &walletv1.ResourceGrantResponse{Grant: &walletv1.ResourceGrant{ + AppCode: req.GetAppCode(), GrantId: "grant-result", CommandId: req.GetCommandId(), TargetUserId: req.GetTargetUserId(), + GrantSource: req.GetGrantSource(), GrantSubjectType: "resource", GrantSubjectId: fmt.Sprint(req.GetResourceId()), Status: "succeeded", + }}, nil +} + +func (m *mockResourceWallet) RevokeUserResource(_ context.Context, req *walletv1.RevokeUserResourceRequest) (*walletv1.RevokeUserResourceResponse, error) { + m.revokeUserResourceRequests = append(m.revokeUserResourceRequests, req) + return &walletv1.RevokeUserResourceResponse{Resource: &walletv1.UserResourceEntitlement{ + EntitlementId: req.GetEntitlementId(), + UserId: req.GetUserId(), + ResourceId: 91, + Status: "revoked", + RemainingQuantity: 0, + Equipped: false, + }}, nil } func (m *mockResourceWallet) GetResource(ctx context.Context, req *walletv1.GetResourceRequest) (*walletv1.GetResourceResponse, error) { diff --git a/server/admin/internal/modules/resource/request.go b/server/admin/internal/modules/resource/request.go index c10ae0be..b96e45eb 100644 --- a/server/admin/internal/modules/resource/request.go +++ b/server/admin/internal/modules/resource/request.go @@ -235,6 +235,10 @@ type grantGroupRequest struct { Reason string `json:"reason"` } +type revokeUserResourceRequest struct { + Reason string `json:"reason"` +} + type resourceShopItemsRequest struct { Items []resourceShopItemRequest `json:"items"` } @@ -244,6 +248,7 @@ type resourceShopItemRequest struct { ResourceID int64 `json:"resourceId"` Status string `json:"status"` DurationDays int32 `json:"durationDays"` + CoinPrice int64 `json:"coinPrice"` EffectiveFromMS int64 `json:"effectiveFromMs"` EffectiveToMS int64 `json:"effectiveToMs"` SortOrder int32 `json:"sortOrder"` @@ -558,6 +563,7 @@ func resourceShopItemInputs(items []resourceShopItemRequest) []*walletv1.Resourc ResourceId: item.ResourceID, Status: strings.TrimSpace(item.Status), DurationDays: item.DurationDays, + CoinPrice: item.CoinPrice, EffectiveFromMs: item.EffectiveFromMS, EffectiveToMs: item.EffectiveToMS, SortOrder: item.SortOrder, diff --git a/server/admin/internal/modules/resource/routes.go b/server/admin/internal/modules/resource/routes.go index 0c4b6e76..facddfe7 100644 --- a/server/admin/internal/modules/resource/routes.go +++ b/server/admin/internal/modules/resource/routes.go @@ -49,6 +49,7 @@ func RegisterRoutes(protected *gin.RouterGroup, h *Handler) { protected.POST("/admin/resource-grants/resource", middleware.RequirePermission("resource-grant:create"), h.GrantResource) protected.POST("/admin/resource-grants/group", middleware.RequirePermission("resource-grant:create"), h.GrantResourceGroup) protected.POST("/admin/resource-grants/:grant_id/revoke", middleware.RequirePermission("resource-grant:revoke"), h.RevokeResourceGrant) + protected.POST("/admin/users/:user_id/resources/:entitlement_id/revoke", middleware.RequirePermission("resource-grant:revoke"), h.RevokeUserResource) // VIP 赠送复用同一目标用户解析入口;仅有 vip-config:grant 的运营也必须能把短号解析成内部 user_id。 protected.GET("/admin/resource-grants/target", middleware.RequireAnyPermission("resource-grant:create", "vip-config:grant"), h.LookupResourceGrantTarget) protected.GET("/admin/resource-grants", middleware.RequirePermission("resource-grant:view"), h.ListResourceGrants) diff --git a/server/admin/internal/modules/vipconfig/handler.go b/server/admin/internal/modules/vipconfig/handler.go index d0bf5a66..cecbfe1d 100644 --- a/server/admin/internal/modules/vipconfig/handler.go +++ b/server/admin/internal/modules/vipconfig/handler.go @@ -120,20 +120,45 @@ type vipProgramConfigDTO struct { } type vipBenefitDTO struct { - BenefitCode string `json:"benefitCode"` - Name string `json:"name"` - BenefitType string `json:"benefitType"` - UnlockLevel int32 `json:"unlockLevel"` - Status string `json:"status"` - TrialEnabled bool `json:"trialEnabled"` - ResourceID int64 `json:"resourceId"` - ResourceType string `json:"resourceType"` - ExecutionScope string `json:"executionScope"` - AutoEquip bool `json:"autoEquip"` - SortOrder int32 `json:"sortOrder"` - MetadataJSON string `json:"metadataJson"` - CreatedAtMS int64 `json:"createdAtMs"` - UpdatedAtMS int64 `json:"updatedAtMs"` + BenefitCode string `json:"benefitCode"` + Name string `json:"name"` + BenefitType string `json:"benefitType"` + UnlockLevel int32 `json:"unlockLevel"` + Status string `json:"status"` + TrialEnabled bool `json:"trialEnabled"` + ResourceID int64 `json:"resourceId"` + ResourceType string `json:"resourceType"` + ExecutionScope string `json:"executionScope"` + AutoEquip bool `json:"autoEquip"` + SortOrder int32 `json:"sortOrder"` + MetadataJSON string `json:"metadataJson"` + CreatedAtMS int64 `json:"createdAtMs"` + UpdatedAtMS int64 `json:"updatedAtMs"` + Presentation *vipBenefitPresentationDTO `json:"presentation"` +} + +type vipBenefitPresentationDTO struct { + Description string `json:"description"` + PreviewItems []vipBenefitPreviewItemDTO `json:"previewItems"` + NumericReward *vipBenefitNumericRewardDTO `json:"numericReward"` +} + +type vipBenefitPreviewItemDTO struct { + PreviewID string `json:"previewId"` + Title string `json:"title"` + MediaType string `json:"mediaType"` + AssetURL string `json:"assetUrl"` + PreviewURL string `json:"previewUrl"` + AnimationURL string `json:"animationUrl"` + CompositionType string `json:"compositionType"` + SortOrder int32 `json:"sortOrder"` +} + +type vipBenefitNumericRewardDTO struct { + Label string `json:"label"` + Value int64 `json:"value"` + Unit string `json:"unit"` + Period string `json:"period"` } type vipTrialCardDTO struct { @@ -163,6 +188,18 @@ type vipStateDTO struct { EffectiveBenefits []vipBenefitDTO `json:"effectiveBenefits"` EvaluatedAtMS int64 `json:"evaluatedAtMs"` ProgramConfig vipProgramConfigDTO `json:"programConfig"` + UserSettings vipUserSettingsDTO `json:"userSettings"` +} + +type vipUserSettingsDTO struct { + AppCode string `json:"appCode"` + UserID string `json:"userId"` + RoomEntryNoticeEnabled bool `json:"roomEntryNoticeEnabled"` + OnlineGlobalNoticeEnabled bool `json:"onlineGlobalNoticeEnabled"` + HideProfileDataEnabled bool `json:"hideProfileDataEnabled"` + AnonymousProfileVisitEnabled bool `json:"anonymousProfileVisitEnabled"` + LeaderboardInvisibleEnabled bool `json:"leaderboardInvisibleEnabled"` + UpdatedAtMS int64 `json:"updatedAtMs"` } type vipRewardItemDTO struct { @@ -244,6 +281,17 @@ func (h *Handler) ListLevels(c *gin.Context) { } func (h *Handler) GrantVIP(c *gin.Context) { + h.grantVIP(c, "admin_grant", "admin_vip_grant:") +} + +// GrantExternalVIP uses Wallet's manager-center source so the owner service +// atomically applies its external-manager grant policy instead of trusting only +// this gateway's route permission. +func (h *Handler) GrantExternalVIP(c *gin.Context) { + h.grantVIP(c, "manager_center", "external_vip_grant:") +} + +func (h *Handler) grantVIP(c *gin.Context, grantSource string, defaultCommandPrefix string) { var req grantVipRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "VIP 赠送参数不正确") @@ -261,14 +309,14 @@ func (h *Handler) GrantVIP(c *gin.Context) { } commandID := strings.TrimSpace(req.CommandID) if commandID == "" { - commandID = "admin_vip_grant:" + middleware.CurrentRequestID(c) + commandID = defaultCommandPrefix + middleware.CurrentRequestID(c) } resp, err := h.wallet.GrantVip(c.Request.Context(), &walletv1.GrantVipRequest{ CommandId: commandID, AppCode: appctx.FromContext(c.Request.Context()), TargetUserId: targetUserID, Level: req.Level, - GrantSource: "admin_grant", + GrantSource: grantSource, OperatorUserId: int64(middleware.CurrentUserID(c)), Reason: reason, }) @@ -281,6 +329,17 @@ func (h *Handler) GrantVIP(c *gin.Context) { } func (h *Handler) GrantVIPTrialCard(c *gin.Context) { + h.grantVIPTrialCard(c, "admin_grant", "admin_vip_trial_card_grant:") +} + +// GrantExternalVIPTrialCard keeps duration/resource enforcement in Wallet's +// manager-center transaction, including the authoritative ManagerGrantEnabled +// check for an explicitly selected trial-card resource. +func (h *Handler) GrantExternalVIPTrialCard(c *gin.Context) { + h.grantVIPTrialCard(c, "manager_center", "external_vip_trial_card_grant:") +} + +func (h *Handler) grantVIPTrialCard(c *gin.Context, grantSource string, defaultCommandPrefix string) { var req grantVipTrialCardRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "VIP 体验卡赠送参数不正确") @@ -298,7 +357,7 @@ func (h *Handler) GrantVIPTrialCard(c *gin.Context) { } commandID := strings.TrimSpace(req.CommandID) if commandID == "" { - commandID = "admin_vip_trial_card_grant:" + middleware.CurrentRequestID(c) + commandID = defaultCommandPrefix + middleware.CurrentRequestID(c) } resp, err := h.wallet.GrantVipTrialCard(c.Request.Context(), &walletv1.GrantVipTrialCardRequest{ CommandId: commandID, @@ -307,7 +366,7 @@ func (h *Handler) GrantVIPTrialCard(c *gin.Context) { Level: req.Level, DurationMs: req.DurationMS, ResourceId: req.ResourceID, - GrantSource: "admin_grant", + GrantSource: grantSource, OperatorUserId: int64(middleware.CurrentUserID(c)), Reason: reason, }) @@ -448,6 +507,7 @@ func vipBenefitsFromProto(items []*walletv1.VipBenefit) []vipBenefitDTO { MetadataJSON: item.GetMetadataJson(), CreatedAtMS: item.GetCreatedAtMs(), UpdatedAtMS: item.GetUpdatedAtMs(), + Presentation: vipBenefitPresentationFromProto(item.GetPresentation()), }) } return benefits @@ -467,9 +527,61 @@ func (item vipBenefitDTO) toProto() *walletv1.VipBenefit { AutoEquip: item.AutoEquip, SortOrder: item.SortOrder, MetadataJson: strings.TrimSpace(item.MetadataJSON), + Presentation: item.Presentation.toProto(), } } +func vipBenefitPresentationFromProto(item *walletv1.VipBenefitPresentation) *vipBenefitPresentationDTO { + if item == nil { + return nil + } + result := &vipBenefitPresentationDTO{ + Description: item.GetDescription(), + PreviewItems: make([]vipBenefitPreviewItemDTO, 0, len(item.GetPreviewItems())), + } + for _, preview := range item.GetPreviewItems() { + if preview == nil { + continue + } + result.PreviewItems = append(result.PreviewItems, vipBenefitPreviewItemDTO{ + PreviewID: preview.GetPreviewId(), Title: preview.GetTitle(), MediaType: preview.GetMediaType(), + AssetURL: preview.GetAssetUrl(), PreviewURL: preview.GetPreviewUrl(), AnimationURL: preview.GetAnimationUrl(), + CompositionType: preview.GetCompositionType(), SortOrder: preview.GetSortOrder(), + }) + } + if reward := item.GetNumericReward(); reward != nil { + result.NumericReward = &vipBenefitNumericRewardDTO{ + Label: reward.GetLabel(), Value: reward.GetValue(), Unit: reward.GetUnit(), Period: reward.GetPeriod(), + } + } + return result +} + +func (item *vipBenefitPresentationDTO) toProto() *walletv1.VipBenefitPresentation { + if item == nil { + return nil + } + result := &walletv1.VipBenefitPresentation{ + Description: strings.TrimSpace(item.Description), + PreviewItems: make([]*walletv1.VipBenefitPreviewItem, 0, len(item.PreviewItems)), + } + for _, preview := range item.PreviewItems { + result.PreviewItems = append(result.PreviewItems, &walletv1.VipBenefitPreviewItem{ + PreviewId: strings.TrimSpace(preview.PreviewID), Title: strings.TrimSpace(preview.Title), + MediaType: strings.TrimSpace(preview.MediaType), AssetUrl: strings.TrimSpace(preview.AssetURL), + PreviewUrl: strings.TrimSpace(preview.PreviewURL), AnimationUrl: strings.TrimSpace(preview.AnimationURL), + CompositionType: strings.TrimSpace(preview.CompositionType), SortOrder: preview.SortOrder, + }) + } + if item.NumericReward != nil { + result.NumericReward = &walletv1.VipBenefitNumericReward{ + Label: strings.TrimSpace(item.NumericReward.Label), Value: item.NumericReward.Value, + Unit: strings.TrimSpace(item.NumericReward.Unit), Period: strings.TrimSpace(item.NumericReward.Period), + } + } + return result +} + func grantVipFromProto(resp *walletv1.GrantVipResponse) grantVipDTO { if resp == nil { return grantVipDTO{} @@ -546,6 +658,22 @@ func vipStateFromProto(item *walletv1.VipState) vipStateDTO { EffectiveBenefits: vipBenefitsFromProto(item.GetEffectiveBenefits()), EvaluatedAtMS: item.GetEvaluatedAtMs(), ProgramConfig: vipProgramConfigFromProto(item.GetProgramConfig()), + UserSettings: vipUserSettingsFromProto(item.GetUserSettings()), + } +} + +func vipUserSettingsFromProto(item *walletv1.VipUserSettings) vipUserSettingsDTO { + if item == nil { + return vipUserSettingsDTO{} + } + return vipUserSettingsDTO{ + AppCode: item.GetAppCode(), UserID: strconv.FormatInt(item.GetUserId(), 10), + RoomEntryNoticeEnabled: item.GetRoomEntryNoticeEnabled(), + OnlineGlobalNoticeEnabled: item.GetOnlineGlobalNoticeEnabled(), + HideProfileDataEnabled: item.GetHideProfileDataEnabled(), + AnonymousProfileVisitEnabled: item.GetAnonymousProfileVisitEnabled(), + LeaderboardInvisibleEnabled: item.GetLeaderboardInvisibleEnabled(), + UpdatedAtMS: item.GetUpdatedAtMs(), } } diff --git a/server/admin/internal/modules/vipconfig/handler_test.go b/server/admin/internal/modules/vipconfig/handler_test.go index 514c2746..6a6346d3 100644 --- a/server/admin/internal/modules/vipconfig/handler_test.go +++ b/server/admin/internal/modules/vipconfig/handler_test.go @@ -45,6 +45,12 @@ func TestGetProgramReturnsCamelCaseCompleteConfigAndBenefits(t *testing.T) { MetadataJson: "{}", CreatedAtMs: 101, UpdatedAtMs: 201, + Presentation: &walletv1.VipBenefitPresentation{ + Description: "普通房管无法踢出", + PreviewItems: []*walletv1.VipBenefitPreviewItem{{ + PreviewId: "anti-kick", MediaType: "image", PreviewUrl: "https://cdn.example/anti-kick.png", CompositionType: "none", + }}, + }, }}, ServerTimeMs: 300, }, @@ -60,6 +66,8 @@ func TestGetProgramReturnsCamelCaseCompleteConfigAndBenefits(t *testing.T) { `"updatedByAdminId":77`, `"benefitCode":"anti_kick"`, `"executionScope":"room"`, + `"description":"普通房管无法踢出"`, + `"compositionType":"none"`, `"serverTimeMs":300`, } { if !strings.Contains(body, fragment) { @@ -105,7 +113,7 @@ func TestUpdateLevelsForwardsExplicitBenefitsAndReturnsProgram(t *testing.T) { ProgramConfig: &walletv1.VipProgramConfig{AppCode: "fami", ProgramType: "tiered_privilege_v1", LevelCount: 9}, ServerTimeMs: 500, }} - body := `{"levels":[{"level":2,"name":"VIP2","status":"active","priceCoin":2000,"durationMs":2592000000,"rewardResourceGroupId":22,"sortOrder":20,"requiredRechargeCoinAmount":123,"benefits":[{"benefitCode":"room_entry_notice","name":"进房通知","benefitType":"function","unlockLevel":2,"status":"active","trialEnabled":true,"resourceId":0,"resourceType":"","executionScope":"room","autoEquip":false,"sortOrder":10,"metadataJson":"{}"}]}]}` + body := `{"levels":[{"level":2,"name":"VIP2","status":"active","priceCoin":2000,"durationMs":2592000000,"rewardResourceGroupId":22,"sortOrder":20,"requiredRechargeCoinAmount":123,"benefits":[{"benefitCode":"room_entry_notice","name":"进房通知","benefitType":"function","unlockLevel":2,"status":"active","trialEnabled":true,"resourceId":0,"resourceType":"","executionScope":"room","autoEquip":false,"sortOrder":10,"metadataJson":"{}","presentation":{"description":"当前房间进房动效","previewItems":[{"previewId":"entry-main","mediaType":"animation","animationUrl":"https://cdn.example/entry.svga","compositionType":"user_avatar_center","sortOrder":10}]}}]}]}` recorder := serveVIPConfigRequest(t, wallet, http.MethodPut, "/admin/activity/vip-levels", body) if recorder.Code != http.StatusOK { t.Fatalf("update levels status = %d, body=%s", recorder.Code, recorder.Body.String()) @@ -118,6 +126,10 @@ func TestUpdateLevelsForwardsExplicitBenefitsAndReturnsProgram(t *testing.T) { if level.GetRequiredRechargeCoinAmount() != 0 || len(level.GetBenefits()) != 1 || level.GetBenefits()[0].GetBenefitCode() != "room_entry_notice" { t.Fatalf("explicit level benefits mismatch: %+v", level) } + presentation := level.GetBenefits()[0].GetPresentation() + if presentation.GetDescription() != "当前房间进房动效" || len(presentation.GetPreviewItems()) != 1 || presentation.GetPreviewItems()[0].GetCompositionType() != "user_avatar_center" { + t.Fatalf("structured benefit presentation mismatch: %+v", presentation) + } if !strings.Contains(recorder.Body.String(), `"programConfig":{"appCode":"fami","programType":"tiered_privilege_v1","levelCount":9`) { t.Fatalf("level response must include program config: %s", recorder.Body.String()) } @@ -135,7 +147,7 @@ func TestGrantTrialCardLeavesOptionalResourceUnsetAndUsesAuthenticatedOperator(t t.Fatalf("grant trial card status = %d, body=%s", recorder.Code, recorder.Body.String()) } req := wallet.grantTrialRequest - if req.GetCommandId() != "admin_vip_trial_card_grant:vip-config-test" || req.GetAppCode() != "fami" || req.GetOperatorUserId() != 77 { + if req.GetCommandId() != "admin_vip_trial_card_grant:vip-config-test" || req.GetAppCode() != "fami" || req.GetOperatorUserId() != 77 || req.GetGrantSource() != "admin_grant" { t.Fatalf("trial grant command context mismatch: %+v", req) } if req.ResourceId != nil || req.GetTargetUserId() != 318705991371722752 || req.GetDurationMs() != 1_728_000_000 { @@ -146,6 +158,59 @@ func TestGrantTrialCardLeavesOptionalResourceUnsetAndUsesAuthenticatedOperator(t } } +func TestExternalVIPGrantsUseManagerCenterOwnerPolicySource(t *testing.T) { + wallet := &fakeVIPConfigWallet{ + grantVIPResponse: &walletv1.GrantVipResponse{TransactionId: "vip-external"}, + grantTrialResponse: &walletv1.GrantVipTrialCardResponse{ + TrialCard: &walletv1.VipTrialCard{TrialCardId: "trial-external"}, + }, + } + gintest := func(path string, body string, handler gin.HandlerFunc) *httptest.ResponseRecorder { + router := gin.New() + router.Use(func(c *gin.Context) { + c.Request = c.Request.WithContext(appctx.WithContext(c.Request.Context(), "fami")) + c.Set(middleware.ContextRequestID, "external-vip-test") + c.Set(middleware.ContextUserID, uint(77)) + c.Next() + }) + router.POST(path, handler) + recorder := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodPost, path, strings.NewReader(body)) + request.Header.Set("Content-Type", "application/json") + router.ServeHTTP(recorder, request) + return recorder + } + handler := New(wallet, nil) + vipRecorder := gintest("/external-vip", `{"targetUserId":"318705991371722752","level":5,"reason":"manual"}`, handler.GrantExternalVIP) + if vipRecorder.Code != http.StatusCreated || wallet.grantVIPRequest == nil || wallet.grantVIPRequest.GetGrantSource() != "manager_center" || wallet.grantVIPRequest.GetCommandId() != "external_vip_grant:external-vip-test" { + t.Fatalf("external VIP source mismatch: status=%d request=%+v body=%s", vipRecorder.Code, wallet.grantVIPRequest, vipRecorder.Body.String()) + } + trialRecorder := gintest("/external-trial", `{"targetUserId":"318705991371722752","level":5,"durationMs":86400000,"resourceId":99,"reason":"manual"}`, handler.GrantExternalVIPTrialCard) + if trialRecorder.Code != http.StatusCreated || wallet.grantTrialRequest == nil || wallet.grantTrialRequest.GetGrantSource() != "manager_center" || wallet.grantTrialRequest.GetCommandId() != "external_vip_trial_card_grant:external-vip-test" { + t.Fatalf("external trial source mismatch: status=%d request=%+v body=%s", trialRecorder.Code, wallet.grantTrialRequest, trialRecorder.Body.String()) + } +} + +func TestMainAdminVIPGrantKeepsAdminSource(t *testing.T) { + wallet := &fakeVIPConfigWallet{grantVIPResponse: &walletv1.GrantVipResponse{TransactionId: "vip-admin"}} + handler := New(wallet, nil) + router := gin.New() + router.Use(func(c *gin.Context) { + c.Request = c.Request.WithContext(appctx.WithContext(c.Request.Context(), "fami")) + c.Set(middleware.ContextRequestID, "admin-vip-test") + c.Set(middleware.ContextUserID, uint(77)) + c.Next() + }) + router.POST("/admin-vip", handler.GrantVIP) + recorder := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodPost, "/admin-vip", strings.NewReader(`{"targetUserId":"318705991371722752","level":5,"reason":"manual"}`)) + request.Header.Set("Content-Type", "application/json") + router.ServeHTTP(recorder, request) + if recorder.Code != http.StatusCreated || wallet.grantVIPRequest == nil || wallet.grantVIPRequest.GetGrantSource() != "admin_grant" || wallet.grantVIPRequest.GetCommandId() != "admin_vip_grant:admin-vip-test" { + t.Fatalf("main admin VIP source changed: status=%d request=%+v body=%s", recorder.Code, wallet.grantVIPRequest, recorder.Body.String()) + } +} + func serveVIPConfigRequest(t *testing.T, wallet walletclient.Client, method string, path string, body string) *httptest.ResponseRecorder { t.Helper() gin.SetMode(gin.TestMode) @@ -174,10 +239,12 @@ type fakeVIPConfigWallet struct { updateProgramResponse *walletv1.UpdateAdminVipProgramConfigResponse updateLevelsResponse *walletv1.UpdateAdminVipLevelsResponse grantTrialResponse *walletv1.GrantVipTrialCardResponse + grantVIPResponse *walletv1.GrantVipResponse getProgramRequest *walletv1.GetVipProgramConfigRequest updateProgramRequest *walletv1.UpdateAdminVipProgramConfigRequest updateLevelsRequest *walletv1.UpdateAdminVipLevelsRequest grantTrialRequest *walletv1.GrantVipTrialCardRequest + grantVIPRequest *walletv1.GrantVipRequest } func (f *fakeVIPConfigWallet) GetVipProgramConfig(_ context.Context, req *walletv1.GetVipProgramConfigRequest) (*walletv1.GetVipProgramConfigResponse, error) { @@ -199,3 +266,8 @@ func (f *fakeVIPConfigWallet) GrantVipTrialCard(_ context.Context, req *walletv1 f.grantTrialRequest = req return f.grantTrialResponse, nil } + +func (f *fakeVIPConfigWallet) GrantVip(_ context.Context, req *walletv1.GrantVipRequest) (*walletv1.GrantVipResponse, error) { + f.grantVIPRequest = req + return f.grantVIPResponse, nil +} diff --git a/server/admin/internal/repository/app_scope_repository_test.go b/server/admin/internal/repository/app_scope_repository_test.go index b83c10bf..b2347b12 100644 --- a/server/admin/internal/repository/app_scope_repository_test.go +++ b/server/admin/internal/repository/app_scope_repository_test.go @@ -66,3 +66,31 @@ func TestReplaceUserAppScopesRejectsEmptySelected(t *testing.T) { t.Fatalf("sql expectations: %v", err) } } + +func TestCurrentAuthorizationForUserReadsAndDeduplicatesLivePermissions(t *testing.T) { + store, mock, closeStore := newRepositorySQLMock(t) + defer closeStore() + + mock.ExpectQuery("(?s)SELECT admin_users\\.username,.*FROM admin_users.*WHERE admin_users\\.id = \\?.*ORDER BY admin_permissions\\.code ASC"). + WithArgs(uint(7)). + WillReturnRows(sqlmock.NewRows([]string{"username", "status", "permission_code"}). + AddRow("ops", model.UserStatusActive, "operations-withdrawal:audit"). + AddRow("ops", model.UserStatusActive, "operations-withdrawal:audit"). + AddRow("ops", model.UserStatusActive, "operations-withdrawal:view")) + + authorization, err := store.CurrentAuthorizationForUser(7) + if err != nil { + t.Fatalf("resolve current authorization: %v", err) + } + if authorization.Username != "ops" || authorization.Status != model.UserStatusActive { + t.Fatalf("unexpected current user state: %+v", authorization) + } + if len(authorization.Permissions) != 2 || + authorization.Permissions[0] != "operations-withdrawal:audit" || + authorization.Permissions[1] != "operations-withdrawal:view" { + t.Fatalf("unexpected live permissions: %+v", authorization.Permissions) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations: %v", err) + } +} diff --git a/server/admin/internal/repository/auth_repository.go b/server/admin/internal/repository/auth_repository.go index 3f8a9598..76b573e3 100644 --- a/server/admin/internal/repository/auth_repository.go +++ b/server/admin/internal/repository/auth_repository.go @@ -1,12 +1,28 @@ package repository import ( - "hyapp-admin-server/internal/model" "time" + "hyapp-admin-server/internal/model" + "gorm.io/gorm" ) +// UserAuthorization is the current server-side authorization state used for +// every protected request. JWT claims identify the session, but never own RBAC +// state because role changes must take effect before a long-lived token expires. +type UserAuthorization struct { + Username string + Status string + Permissions []string +} + +type userAuthorizationRow struct { + Username string + Status string + PermissionCode *string +} + func (s *Store) FindUserByUsername(username string) (*model.User, error) { var user model.User err := s.db.Preload("Roles.Permissions").Preload("TeamRecord").Where("username = ?", username).First(&user).Error @@ -27,6 +43,54 @@ func (s *Store) FindUserByID(id uint) (*model.User, error) { return &user, nil } +func (s *Store) CurrentAuthorizationForUser(userID uint) (UserAuthorization, error) { + if userID == 0 { + return UserAuthorization{}, gorm.ErrRecordNotFound + } + + var rows []userAuthorizationRow + // The query starts from admin_users.id and follows the two composite-primary-key + // relation tables. It therefore resolves live permissions in one indexed query + // without loading the full user/role models on every protected HTTP request. + result := s.db.Raw(` + SELECT admin_users.username, + admin_users.status, + admin_permissions.code AS permission_code + FROM admin_users + LEFT JOIN admin_user_roles + ON admin_user_roles.user_id = admin_users.id + LEFT JOIN admin_role_permissions + ON admin_role_permissions.role_id = admin_user_roles.role_id + LEFT JOIN admin_permissions + ON admin_permissions.id = admin_role_permissions.permission_id + WHERE admin_users.id = ? + ORDER BY admin_permissions.code ASC + `, userID).Scan(&rows) + if result.Error != nil { + return UserAuthorization{}, result.Error + } + if len(rows) == 0 { + return UserAuthorization{}, gorm.ErrRecordNotFound + } + + authorization := UserAuthorization{ + Username: rows[0].Username, + Status: rows[0].Status, + } + seen := make(map[string]struct{}, len(rows)) + for _, row := range rows { + if row.PermissionCode == nil || *row.PermissionCode == "" { + continue + } + if _, ok := seen[*row.PermissionCode]; ok { + continue + } + seen[*row.PermissionCode] = struct{}{} + authorization.Permissions = append(authorization.Permissions, *row.PermissionCode) + } + return authorization, nil +} + func PermissionsForUser(user model.User) []string { set := map[string]struct{}{} for _, role := range user.Roles { diff --git a/server/admin/internal/repository/money_scope_repository.go b/server/admin/internal/repository/money_scope_repository.go index 8ab9c5d1..26b0c6c3 100644 --- a/server/admin/internal/repository/money_scope_repository.go +++ b/server/admin/internal/repository/money_scope_repository.go @@ -2,6 +2,7 @@ package repository import ( "errors" + "sort" "strconv" "strings" "time" @@ -64,9 +65,24 @@ func (access MoneyAccess) AppCodes() []string { for appCode := range set { out = append(out, appCode) } + sort.Strings(out) return out } +// AllowsApp 用于没有 region 维度的资金事实(例如用户提现):任一归属该 App 的财务范围都可查看和审核该 App 申请。 +func (access MoneyAccess) AllowsApp(appCode string) bool { + if access.All { + return true + } + appCode = appctx.Normalize(appCode) + for _, allowed := range access.AppCodes() { + if allowed == appCode { + return true + } + } + return false +} + func (s *Store) MoneyAccessForUser(userID uint) (MoneyAccess, error) { if userID == 0 { return MoneyAccess{All: true}, nil diff --git a/server/admin/internal/repository/money_scope_repository_test.go b/server/admin/internal/repository/money_scope_repository_test.go index 149c05e3..4318c7b1 100644 --- a/server/admin/internal/repository/money_scope_repository_test.go +++ b/server/admin/internal/repository/money_scope_repository_test.go @@ -135,3 +135,17 @@ func TestMoneyAccessAllowsRoundedRegion(t *testing.T) { t.Fatalf("unrelated region must stay denied") } } + +func TestMoneyAccessAllowsAppIgnoresRegionButKeepsAppBoundary(t *testing.T) { + t.Parallel() + access := MoneyAccess{UserID: 7, Scopes: []model.UserMoneyScope{ + {UserID: 7, AppCode: "lalu", RegionID: 9}, + {UserID: 7, AppCode: "fami", RegionID: 0}, + }} + if !access.AllowsApp("LALU") || !access.AllowsApp("fami") || access.AllowsApp("huwaa") { + t.Fatalf("unexpected app-level money access: %+v", access) + } + if got := access.AppCodes(); len(got) != 2 || got[0] != "fami" || got[1] != "lalu" { + t.Fatalf("money scope app codes must be stable and sorted: %v", got) + } +} diff --git a/server/admin/internal/repository/repository.go b/server/admin/internal/repository/repository.go index 95733b16..84650eb2 100644 --- a/server/admin/internal/repository/repository.go +++ b/server/admin/internal/repository/repository.go @@ -92,6 +92,10 @@ func (s *Store) AutoMigrate() error { &model.CoinSellerRechargeOrder{}, &model.UserWithdrawalApplication{}, &model.AdminJob{}, + &model.ExternalAdminAccount{}, + &model.ExternalAdminSession{}, + &model.ExternalAdminLoginLog{}, + &model.ExternalAdminOperationLog{}, ) } diff --git a/server/admin/internal/repository/role_permission_matrix.go b/server/admin/internal/repository/role_permission_matrix.go index 2c4a1a72..6cba25fc 100644 --- a/server/admin/internal/repository/role_permission_matrix.go +++ b/server/admin/internal/repository/role_permission_matrix.go @@ -32,8 +32,8 @@ var ( "finance-order:coin-seller-recharge:verify", "finance-order:coin-seller-recharge:grant", "finance-order:usdt-address:update", - "finance-withdrawal:view", - "finance-withdrawal:audit", + "operations-withdrawal:view", + "operations-withdrawal:audit", } workbenchFinance = []string{ "finance:view", @@ -160,6 +160,12 @@ var ( geoRead = []string{"country:view", "region:view"} geoManage = []string{"country:create", "country:update", "country:status", "region:create", "region:update", "region:status"} + + // 运营岗位只能查看和停用外管账号。创建、重置密码会签发或接管一组固定的 + // 高权限外管能力,必须收口到 platform-admin,避免运营角色委派自身并不具备的权限。 + externalAdminUserOperate = []string{ + "external-admin-user:view", "external-admin-user:status", + } ) // defaultRolePermissionCodes 只组合表格中明确勾选的模块。相同页面曾复用 game:* 或 @@ -175,6 +181,7 @@ func defaultRolePermissionCodes(code string) []string { []string{"app-config:view"}, appConfigManage, resourceRead, resourceManage, operationsRead, operationsLeadManage, luckyGiftPoolManage, + externalAdminUserOperate, paymentRead, paymentBillExport, paymentBillRefresh, paymentOperationsManage, activityRead, activityManage, gameRead, gameManage, @@ -189,6 +196,7 @@ func defaultRolePermissionCodes(code string) []string { []string{"app-config:view"}, appConfigManage, resourceRead, resourceManage, operationsRead, + externalAdminUserOperate, paymentRead, paymentBillExport, paymentBillRefresh, activityRead, gameRead, gameOperationsSpecialistManage, diff --git a/server/admin/internal/repository/seed.go b/server/admin/internal/repository/seed.go index 42b430b6..c1b9d3a9 100644 --- a/server/admin/internal/repository/seed.go +++ b/server/admin/internal/repository/seed.go @@ -16,6 +16,11 @@ var defaultPermissions = []model.Permission{ {Name: "用户状态", Code: "user:status", Kind: "button"}, {Name: "用户重置密码", Code: "user:reset-password", Kind: "button"}, {Name: "用户导出", Code: "user:export", Kind: "button"}, + {Name: "外管用户查看", Code: "external-admin-user:view", Kind: "menu", Description: "查看当前 App 的外管用户"}, + {Name: "外管用户创建", Code: "external-admin-user:create", Kind: "button", Description: "按当前 App 用户短 ID 创建外管账号"}, + {Name: "外管用户状态", Code: "external-admin-user:status", Kind: "button", Description: "启用或停用当前 App 的外管账号"}, + {Name: "外管用户重置密码", Code: "external-admin-user:reset-password", Kind: "button", Description: "重置当前 App 的外管账号密码并撤销全部会话"}, + {Name: "外管用户权限配置", Code: "external-admin-user:permissions", Kind: "button", Description: "配置当前 App 外管用户权限并撤销其现有会话"}, {Name: "团队查看", Code: "team:view", Kind: "menu"}, {Name: "团队创建", Code: "team:create", Kind: "button"}, {Name: "团队更新", Code: "team:update", Kind: "button"}, @@ -143,8 +148,10 @@ var defaultPermissions = []model.Permission{ {Name: "币商充值订单校验", Code: "finance-order:coin-seller-recharge:verify", Kind: "button"}, {Name: "币商充值订单发放", Code: "finance-order:coin-seller-recharge:grant", Kind: "button"}, {Name: "USDT 收款地址编辑", Code: "finance-order:usdt-address:update", Kind: "button", Description: "允许按 APP 新增或修改 USDT 收款地址"}, - {Name: "用户提现申请查看", Code: "finance-withdrawal:view", Kind: "menu"}, - {Name: "用户提现申请审核", Code: "finance-withdrawal:audit", Kind: "button"}, + {Name: "用户提现财务审核", Code: "finance-withdrawal:view", Kind: "menu"}, + {Name: "用户提现财务审核操作", Code: "finance-withdrawal:audit", Kind: "button"}, + {Name: "用户提现运营审核", Code: "operations-withdrawal:view", Kind: "menu"}, + {Name: "用户提现运营审核操作", Code: "operations-withdrawal:audit", Kind: "button"}, {Name: "内购配置查看", Code: "payment-product:view", Kind: "menu"}, {Name: "内购配置创建", Code: "payment-product:create", Kind: "button"}, {Name: "内购配置更新", Code: "payment-product:update", Kind: "button"}, @@ -364,6 +371,7 @@ func (s *Store) seedMenus() error { {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-external-admin-users", Path: "/operations/external-admin-users", Icon: "shield", PermissionCode: "external-admin-user:view", Sort: 72, Visible: true}, {ParentID: &operationsID, Title: "举报列表", Code: "operation-reports", Path: "/operations/reports", Icon: "flag", PermissionCode: "report:view", Sort: 73, Visible: true}, {ParentID: &operationsID, Title: "礼物钻石", Code: "operation-gift-diamond", Path: "/operations/gift-diamonds", Icon: "diamond", PermissionCode: "gift-diamond:view", Sort: 74, Visible: true}, {ParentID: &operationsID, Title: "收益政策模板", Code: "policy-template", Path: "/policy/templates", Icon: "settings", PermissionCode: "policy-template:view", Sort: 88, Visible: true}, diff --git a/server/admin/internal/repository/seed_test.go b/server/admin/internal/repository/seed_test.go index 0be742ba..68930ea6 100644 --- a/server/admin/internal/repository/seed_test.go +++ b/server/admin/internal/repository/seed_test.go @@ -25,6 +25,9 @@ func TestDefaultPermissionSeedUsesFinancePermissions(t *testing.T) { "payment-temporary-link:create", "finance:view", "finance-withdrawal:view", + "finance-withdrawal:audit", + "operations-withdrawal:view", + "operations-withdrawal:audit", "host-withdrawal:view", } { if _, ok := permissions[code]; !ok { @@ -53,6 +56,8 @@ func TestDefaultRoleFinancePermissionTemplates(t *testing.T) { for _, code := range []string{ "payment-bill:export", "host-withdrawal:view", + "operations-withdrawal:view", + "operations-withdrawal:audit", } { if _, ok := opsPermissions[code]; !ok { t.Fatalf("ops-admin default permissions missing %s", code) @@ -61,6 +66,8 @@ func TestDefaultRoleFinancePermissionTemplates(t *testing.T) { for _, code := range []string{ "finance:view", + "finance-withdrawal:view", + "finance-withdrawal:audit", "payment-temporary-link:create", "payment-third-party:update-rate", "payment-third-party:sync-rates", @@ -126,12 +133,12 @@ func TestManagedDefaultRolePermissionMatrix(t *testing.T) { func TestManagedDefaultRoleModuleBoundaries(t *testing.T) { assertRolePermissions(t, roleCodeOperationsLead, - []string{"app-config:update", "payment-third-party:sync-methods", "game-catalog:update", "country:update"}, - []string{"app-version:view", "finance:view", "payment-third-party:update-rate", "role:view"}, + []string{"app-config:update", "payment-third-party:sync-methods", "game-catalog:update", "country:update", "external-admin-user:view", "external-admin-user:status", "operations-withdrawal:view", "operations-withdrawal:audit"}, + []string{"app-version:view", "finance:view", "finance-withdrawal:view", "finance-withdrawal:audit", "payment-third-party:update-rate", "role:view", "external-admin-user:create", "external-admin-user:reset-password", "external-admin-user:permissions"}, ) assertRolePermissions(t, roleCodeOperationsSpecialist, - []string{"room:update", "game-robot:update", "room-rps-config:update", "payment-bill:export"}, - []string{"activity:update", "daily-task:update", "game-catalog:update", "self-game:update", "coin-adjustment:create"}, + []string{"room:update", "game-robot:update", "room-rps-config:update", "payment-bill:export", "external-admin-user:view", "external-admin-user:status", "operations-withdrawal:view", "operations-withdrawal:audit"}, + []string{"activity:update", "daily-task:update", "game-catalog:update", "self-game:update", "coin-adjustment:create", "finance-withdrawal:view", "finance-withdrawal:audit", "external-admin-user:create", "external-admin-user:reset-password", "external-admin-user:permissions"}, ) assertRolePermissions(t, roleCodeProductLead, []string{"app-version:update", "daily-task:update", "game-catalog:update", "resource:update"}, @@ -149,7 +156,7 @@ func TestManagedDefaultRoleModuleBoundaries(t *testing.T) { } assertRolePermissions(t, roleCodeFinanceLead, []string{"finance:view", "payment-bill:view", "payment-bill:export", "finance-withdrawal:audit", "room-rps-order:view"}, - []string{"game-catalog:view", "room-rps-config:view", "app-user:view", "daily-task:view"}, + []string{"operations-withdrawal:view", "operations-withdrawal:audit", "game-catalog:view", "room-rps-config:view", "app-user:view", "daily-task:view"}, ) } @@ -195,6 +202,33 @@ func TestRolePermissionMigrationMatchesManagedMatrix(t *testing.T) { } assertMigrationPermissionCodes(t, roleCodeFinanceLead, financeMatches[1]) assertMigrationPermissionCodes(t, roleCodeFinanceSpecialist, financeMatches[1]) + + correction, err := os.ReadFile("../../migrations/102_user_withdrawal_operations_review.sql") + if err != nil { + t.Fatalf("read withdrawal review correction migration: %v", err) + } + correctionSQL := string(correction) + for _, token := range []string{ + "schema_migration_checkpoints", + "COALESCE(MAX(id), 0)", + "DEFAULT ''pending''", + "application.id <= checkpoint.checkpoint_value", + "application.status IN ('approved', 'rejected')", + "application.operations_status = 'pending'", + "ALGORITHM=INPLACE, LOCK=NONE", + "DELETE role_permission", + "'ops-admin', 'operations-specialist'", + "'finance-withdrawal:view', 'finance-withdrawal:audit'", + "'platform-admin', 'ops-admin', 'operations-specialist'", + "'operations-withdrawal:view', 'operations-withdrawal:audit'", + } { + if !strings.Contains(correctionSQL, token) { + t.Fatalf("withdrawal review correction migration missing %s", token) + } + } + if strings.Contains(correctionSQL, "DEFAULT ''skipped''") || strings.Contains(correctionSQL, "DEFAULT 'skipped'") { + t.Fatal("withdrawal operations database default must be pending so old gateway inserts cannot bypass initial review") + } } func TestGiftRecordPermissionMigrationExtendsOperationsReadRoles(t *testing.T) { @@ -236,6 +270,78 @@ func TestActivityTemplatePermissionMigrationExtendsManagedRoles(t *testing.T) { } } +func TestExternalAdminMigrationSeedsIsolatedPortalAndOperationsMenu(t *testing.T) { + content, err := os.ReadFile("../../migrations/098_external_admin_portal.sql") + if err != nil { + t.Fatalf("read external admin migration: %v", err) + } + sqlText := string(content) + for _, token := range []string{ + "external_admin_accounts", "external_admin_sessions", "external_admin_login_logs", "external_admin_operation_logs", + "uk_external_admin_accounts_app_username", "uk_external_admin_accounts_app_linked_user", + "'external-admin-user:view'", "'external-admin-user:create'", "'external-admin-user:status'", "'external-admin-user:reset-password'", + "'operation-external-admin-users'", "'/operations/external-admin-users'", + "WHERE role.code = 'platform-admin'", "WHERE role.code IN ('ops-admin', 'operations-specialist')", + } { + if !strings.Contains(sqlText, token) { + t.Fatalf("external admin migration missing %s", token) + } + } + // 创建和重置密码会让操作者控制固定的全能力外管账号;迁移必须把这两项 + // 仅授予平台管理员,运营岗位只保留日常查看和启停能力。 + platformBlock := regexp.MustCompile(`(?s)WHERE role\.code = 'platform-admin'\s+AND permission\.code IN \((.*?)\);`).FindStringSubmatch(sqlText) + if len(platformBlock) != 2 || !strings.Contains(platformBlock[1], "'external-admin-user:create'") || !strings.Contains(platformBlock[1], "'external-admin-user:reset-password'") { + t.Fatal("external admin credential permissions must be granted to platform-admin") + } + opsBlock := regexp.MustCompile(`(?s)WHERE role\.code IN \('ops-admin', 'operations-specialist'\)\s+AND permission\.code IN \((.*?)\);`).FindStringSubmatch(sqlText) + if len(opsBlock) != 2 || !strings.Contains(opsBlock[1], "'external-admin-user:view'") || !strings.Contains(opsBlock[1], "'external-admin-user:status'") { + t.Fatal("external admin operations permissions missing for operations roles") + } + if strings.Contains(opsBlock[1], "'external-admin-user:create'") || strings.Contains(opsBlock[1], "'external-admin-user:reset-password'") { + t.Fatal("operations roles must not receive external admin credential permissions") + } +} + +func TestExternalAdminCredentialDelegationCorrectionMigration(t *testing.T) { + content, err := os.ReadFile("../../migrations/099_external_admin_credential_delegation.sql") + if err != nil { + t.Fatalf("read external admin delegation migration: %v", err) + } + sqlText := string(content) + for _, token := range []string{ + "DELETE role_permission", "admin_role_permissions", "'ops-admin'", "'operations-specialist'", + "'external-admin-user:create'", "'external-admin-user:reset-password'", + } { + if !strings.Contains(sqlText, token) { + t.Fatalf("external admin delegation migration missing %s", token) + } + } +} + +func TestExternalAdminPermissionAssignmentMigrationIsIncrementalAndPlatformOnly(t *testing.T) { + content, err := os.ReadFile("../../migrations/101_external_admin_permission_assignment.sql") + if err != nil { + t.Fatalf("read external admin permission assignment migration: %v", err) + } + sqlText := string(content) + for _, token := range []string{ + "'external-admin-user:permissions'", "WHERE role.code = 'platform-admin'", + "admin_role_permissions", "admin_permissions permission", "ADD COLUMN permission_revision", + "BIGINT UNSIGNED NOT NULL DEFAULT 1", "ALGORITHM=INPLACE", "LOCK=NONE", + } { + if !strings.Contains(sqlText, token) { + t.Fatalf("external admin permission assignment migration missing %s", token) + } + } + if strings.Contains(sqlText, "'ops-admin'") || strings.Contains(sqlText, "'operations-specialist'") { + t.Fatal("external permission delegation must not be seeded to operations roles") + } + upperSQL := strings.ToUpper(sqlText) + if strings.Contains(upperSQL, "UPDATE EXTERNAL_ADMIN_ACCOUNTS") || strings.Contains(upperSQL, "DELETE FROM EXTERNAL_ADMIN_ACCOUNTS") { + t.Fatal("permission revision migration must not rewrite account rows in application SQL") + } +} + func TestLuckyGiftPoolAdjustmentPermissionMigrationRepairsManagedRoles(t *testing.T) { content, err := os.ReadFile("../../migrations/098_lucky_gift_pool_adjust_permissions.sql") if err != nil { @@ -261,14 +367,20 @@ func assertMigrationPermissionCodes(t *testing.T, roleCode string, sqlList strin actual = append(actual, match[1]) } expected := append([]string(nil), defaultRolePermissionCodes(roleCode)...) - // 093 已在生产执行,不能为了新增页面回写旧迁移;095/096 以增量方式补充页面权限。 + // 093 已在生产执行,不能为了新增页面回写旧迁移;095/096/102 以增量方式补充或收紧页面权限。 // 这里仍校验 093 的原始精确矩阵,新权限由上面的专项迁移测试锁定。 expected = stringSetDifference(expected, []string{ "gift-record:view", "activity-template:view", "activity-template:create", "activity-template:update", "activity-template:publish", "activity-template:delete", "activity-template:data", "activity-template:export", "activity-template:retry", + "external-admin-user:view", "external-admin-user:create", "external-admin-user:status", "external-admin-user:reset-password", "lucky-gift:view", "lucky-gift:update", "lucky-gift:pool-credit", "lucky-gift:pool-debit", }) + if roleCode == roleCodeOperationsLead || roleCode == roleCodeOperationsSpecialist { + // 093 仍记录旧的财务提现权限;102 才把固定运营岗位切换到独立运营审核权限。 + expected = stringSetDifference(expected, []string{"operations-withdrawal:view", "operations-withdrawal:audit"}) + expected = append(expected, "finance-withdrawal:view", "finance-withdrawal:audit") + } sort.Strings(actual) sort.Strings(expected) if !reflect.DeepEqual(actual, expected) { diff --git a/server/admin/internal/repository/withdrawal_application_repository.go b/server/admin/internal/repository/withdrawal_application_repository.go index dcf63654..0b49fc31 100644 --- a/server/admin/internal/repository/withdrawal_application_repository.go +++ b/server/admin/internal/repository/withdrawal_application_repository.go @@ -10,16 +10,30 @@ import ( "gorm.io/gorm/clause" ) -var ErrWithdrawalApplicationAlreadyAudited = errors.New("withdrawal application already audited") +var ( + ErrWithdrawalApplicationAlreadyAudited = errors.New("withdrawal application already audited") + ErrWithdrawalApplicationStageNotReviewable = errors.New("withdrawal application is not ready for this review stage") +) + +type WithdrawalApplicationReviewStage string + +const ( + WithdrawalApplicationReviewStageFinance WithdrawalApplicationReviewStage = "finance" + WithdrawalApplicationReviewStageOperations WithdrawalApplicationReviewStage = "operations" +) type WithdrawalApplicationListOptions struct { - Page int - PageSize int - AppCode string - Keyword string + Page int + PageSize int + AppCode string + AllowedAppCodes []string + RestrictAppCodes bool + Keyword string + Stage WithdrawalApplicationReviewStage } type WithdrawalApplicationAuditInput struct { + Stage WithdrawalApplicationReviewStage Decision string ApproverUserID uint ApproverName string @@ -30,6 +44,19 @@ type WithdrawalApplicationAuditInput struct { ApprovedAtMS int64 } +// WithdrawalApplicationAuditEffect 是持行锁期间完成的钱包命令结果。 +// 运营通过没有资金副作用,因此允许返回空 command/transaction;任一拒绝和财务通过都会保存可追溯的账务事实。 +type WithdrawalApplicationAuditEffect struct { + CommandID string + TransactionID string +} + +type WithdrawalApplicationAuditAction func(application model.UserWithdrawalApplication) (WithdrawalApplicationAuditEffect, error) + +// WithdrawalApplicationClaimValidator 在拒绝 claim 提交前校验钱包释放所需的冻结快照。 +// 校验必须留在持行锁的短事务内,避免坏数据先进入 rejecting 后再永久卡住人工流程。 +type WithdrawalApplicationClaimValidator func(application model.UserWithdrawalApplication) error + func (s *Store) GetWithdrawalApplication(id uint) (*model.UserWithdrawalApplication, error) { var application model.UserWithdrawalApplication if err := s.db.First(&application, id).Error; err != nil { @@ -56,7 +83,7 @@ func (s *Store) ListWithdrawalApplications(options WithdrawalApplicationListOpti return nil, 0, err } var applications []model.UserWithdrawalApplication - // 提现申请是财务审核场景,默认按最新申请优先展示;id 作为同毫秒写入时的稳定次序,避免分页翻页时记录抖动。 + // 提现申请用于运营初审和财务终审,默认按最新申请优先展示;id 作为同毫秒写入时的稳定次序,避免分页翻页时记录抖动。 err := query. Order("created_at_ms DESC, id DESC"). Limit(pageSize). @@ -66,20 +93,168 @@ func (s *Store) ListWithdrawalApplications(options WithdrawalApplicationListOpti } func (s *Store) AuditWithdrawalApplication(id uint, input WithdrawalApplicationAuditInput) (*model.UserWithdrawalApplication, error) { - return s.AuditWithdrawalApplicationForApp("", id, input) + return s.ReviewWithdrawalApplicationForApp("", id, input, nil) } func (s *Store) AuditWithdrawalApplicationForApp(appCode string, id uint, input WithdrawalApplicationAuditInput) (*model.UserWithdrawalApplication, error) { + return s.ReviewWithdrawalApplicationForApp(appCode, id, input, nil) +} + +// ClaimWithdrawalOperationsRejectionForApp 先独立提交 rejecting,再允许调用 wallet/inbox。 +// 这个持久门禁覆盖“钱包释放成功、但通知或 admin 最终提交失败”的窗口:后续运营通过和财务审核都会被 rejecting 拒绝, +// 只有相同阶段 command 的拒绝重试可以继续,且审核人、拒绝原因以第一次 claim 的快照为准。 +func (s *Store) ClaimWithdrawalOperationsRejectionForApp(appCode string, id uint, input WithdrawalApplicationAuditInput, validate WithdrawalApplicationClaimValidator) (*model.UserWithdrawalApplication, error) { if id == 0 { return nil, errors.New("withdrawal application id is required") } - if input.Decision != model.WithdrawalApplicationStatusApproved && input.Decision != model.WithdrawalApplicationStatusRejected { - return nil, errors.New("withdrawal application decision is invalid") + if input.Stage != WithdrawalApplicationReviewStageOperations || input.Decision != model.WithdrawalApplicationStatusRejected { + return nil, errors.New("withdrawal application rejection claim is invalid") + } + input.AuditCommandID = strings.TrimSpace(input.AuditCommandID) + if input.AuditCommandID == "" || input.ApproverUserID == 0 || strings.TrimSpace(input.AuditRemark) == "" || input.ApprovedAtMS <= 0 { + return nil, errors.New("withdrawal application rejection claim is incomplete") } var application model.UserWithdrawalApplication err := s.db.Transaction(func(tx *gorm.DB) error { - // 审核只能从 pending 进入终态;行锁阻止两个财务同时覆盖同一张提现单的执行结果。 + query := tx.Clauses(clause.Locking{Strength: "UPDATE"}) + if strings.TrimSpace(appCode) != "" { + query = query.Where("app_code = ?", strings.TrimSpace(appCode)) + } + if err := query.First(&application, id).Error; err != nil { + return err + } + + operationsStatus := strings.TrimSpace(application.OperationsStatus) + if application.Status == model.WithdrawalApplicationStatusRejected && operationsStatus == model.WithdrawalOperationsStatusRejected { + // 已完成拒绝是终态幂等响应;不能再次触发 wallet 或 notice。 + return nil + } + if application.Status != model.WithdrawalApplicationStatusPending { + return ErrWithdrawalApplicationAlreadyAudited + } + switch operationsStatus { + case model.WithdrawalOperationsStatusPending: + if validate != nil { + if err := validate(application); err != nil { + return err + } + } + updates := map[string]any{ + "operations_status": model.WithdrawalOperationsStatusRejecting, + "operations_reviewer_user_id": input.ApproverUserID, + "operations_reviewer_name": strings.TrimSpace(input.ApproverName), + "operations_audit_remark": strings.TrimSpace(input.AuditRemark), + "operations_audit_command_id": input.AuditCommandID, + "operations_reviewed_at_ms": input.ApprovedAtMS, + "updated_at_ms": input.ApprovedAtMS, + } + if err := tx.Model(&application).Updates(updates).Error; err != nil { + return err + } + application.OperationsStatus = model.WithdrawalOperationsStatusRejecting + application.OperationsReviewerUserID = &input.ApproverUserID + application.OperationsReviewerName = strings.TrimSpace(input.ApproverName) + application.OperationsAuditRemark = strings.TrimSpace(input.AuditRemark) + application.OperationsAuditCommandID = input.AuditCommandID + application.OperationsReviewedAtMS = &input.ApprovedAtMS + application.UpdatedAtMS = input.ApprovedAtMS + return nil + case model.WithdrawalOperationsStatusRejecting: + // 重试不能改写第一次审核的上下文,否则钱包 metadata、通知原因和后台审计记录会彼此矛盾。 + if strings.TrimSpace(application.OperationsAuditCommandID) != input.AuditCommandID { + return ErrWithdrawalApplicationStageNotReviewable + } + if validate != nil { + return validate(application) + } + return nil + default: + return ErrWithdrawalApplicationStageNotReviewable + } + }) + if err != nil { + return nil, err + } + return &application, nil +} + +// FinalizeWithdrawalOperationsRejectionForApp 只把已持久 claim 的 rejecting 收敛到双重 rejected 终态。 +// wallet transaction id 非空且 stage command 必须与 claim 一致,防止其他流程借最终更新覆盖资金事实。 +func (s *Store) FinalizeWithdrawalOperationsRejectionForApp(appCode string, id uint, commandID string, transactionID string, completedAtMS int64) (*model.UserWithdrawalApplication, error) { + commandID = strings.TrimSpace(commandID) + transactionID = strings.TrimSpace(transactionID) + if id == 0 || commandID == "" || transactionID == "" || completedAtMS <= 0 { + return nil, errors.New("withdrawal application rejection finalization is incomplete") + } + + var application model.UserWithdrawalApplication + err := s.db.Transaction(func(tx *gorm.DB) error { + query := tx.Clauses(clause.Locking{Strength: "UPDATE"}) + if strings.TrimSpace(appCode) != "" { + query = query.Where("app_code = ?", strings.TrimSpace(appCode)) + } + if err := query.First(&application, id).Error; err != nil { + return err + } + + operationsStatus := strings.TrimSpace(application.OperationsStatus) + if application.Status == model.WithdrawalApplicationStatusRejected && operationsStatus == model.WithdrawalOperationsStatusRejected { + if strings.TrimSpace(application.OperationsAuditCommandID) != commandID || strings.TrimSpace(application.OperationsAuditTransactionID) != transactionID { + return ErrWithdrawalApplicationStageNotReviewable + } + return nil + } + if application.Status != model.WithdrawalApplicationStatusPending || operationsStatus != model.WithdrawalOperationsStatusRejecting || strings.TrimSpace(application.OperationsAuditCommandID) != commandID { + return ErrWithdrawalApplicationStageNotReviewable + } + updates := map[string]any{ + "status": model.WithdrawalApplicationStatusRejected, + "operations_status": model.WithdrawalOperationsStatusRejected, + "operations_audit_transaction_id": transactionID, + "updated_at_ms": completedAtMS, + } + if err := tx.Model(&application).Updates(updates).Error; err != nil { + return err + } + application.Status = model.WithdrawalApplicationStatusRejected + application.OperationsStatus = model.WithdrawalOperationsStatusRejected + application.OperationsAuditTransactionID = transactionID + application.UpdatedAtMS = completedAtMS + return nil + }) + if err != nil { + return nil, err + } + return &application, nil +} + +// ReviewWithdrawalApplicationForApp 把普通阶段校验、跨服务资金/通知动作和本地状态更新收敛在同一把申请行锁内。 +// 提现审核是低 QPS、高价值资金边界;这里有意在钱包和 inbox 网络调用期间持有行锁,让运营通过及财务通过/拒绝严格串行。 +// 外部动作必须使用阶段固定的幂等 command/event id:事务回滚后重试不会重复扣款或通知,而相反决策会以同一 command id 的请求哈希冲突失败。 +// 运营拒绝不能走本函数:它必须先用 Claim... 独立提交 rejecting,再在外部动作成功后用 Finalize... 收敛终态。 +func (s *Store) ReviewWithdrawalApplicationForApp(appCode string, id uint, input WithdrawalApplicationAuditInput, action WithdrawalApplicationAuditAction) (*model.UserWithdrawalApplication, error) { + if id == 0 { + return nil, errors.New("withdrawal application id is required") + } + if input.Stage == "" { + // 保留 repository 旧调用者的财务审核语义;新业务入口必须显式传阶段。 + input.Stage = WithdrawalApplicationReviewStageFinance + } + if input.Stage != WithdrawalApplicationReviewStageFinance && input.Stage != WithdrawalApplicationReviewStageOperations { + return nil, errors.New("withdrawal application review stage is invalid") + } + if input.Decision != model.WithdrawalApplicationStatusApproved && input.Decision != model.WithdrawalApplicationStatusRejected { + return nil, errors.New("withdrawal application decision is invalid") + } + if input.Stage == WithdrawalApplicationReviewStageOperations && input.Decision == model.WithdrawalApplicationStatusRejected { + // 运营拒绝必须先提交 rejecting claim;禁止旧调用者继续把钱包释放和本地终态放在一个可整体回滚的事务里。 + return nil, errors.New("operations withdrawal rejection must use durable claim") + } + + var application model.UserWithdrawalApplication + err := s.db.Transaction(func(tx *gorm.DB) error { + // 行锁保护当前阶段门禁:同一申请的运营通过/拒绝与后续财务通过/拒绝按提交顺序串行,不能跨阶段覆盖审核结果。 query := tx.Clauses(clause.Locking{Strength: "UPDATE"}) if strings.TrimSpace(appCode) != "" { // 后台按当前 App 上下文审核,不能只凭全局自增 ID 跨 App 锁定和审核提现单。 @@ -88,28 +263,107 @@ func (s *Store) AuditWithdrawalApplicationForApp(appCode string, id uint, input if err := query.First(&application, id).Error; err != nil { return err } - if application.Status != model.WithdrawalApplicationStatusPending { - return ErrWithdrawalApplicationAlreadyAudited + if reviewErr := withdrawalApplicationReviewError(application, input.Stage); reviewErr != nil { + return reviewErr } - return tx.Model(&application).Updates(map[string]any{ - "status": input.Decision, - "approver_user_id": input.ApproverUserID, - "approver_name": strings.TrimSpace(input.ApproverName), - "audit_remark": strings.TrimSpace(input.AuditRemark), - "audit_image_url": strings.TrimSpace(input.AuditImageURL), - "audit_command_id": strings.TrimSpace(input.AuditCommandID), - "audit_transaction_id": strings.TrimSpace(input.AuditTransactionID), - "approved_at_ms": input.ApprovedAtMS, - "updated_at_ms": input.ApprovedAtMS, - }).Error + effect := WithdrawalApplicationAuditEffect{ + CommandID: strings.TrimSpace(input.AuditCommandID), + TransactionID: strings.TrimSpace(input.AuditTransactionID), + } + if action != nil { + var err error + effect, err = action(application) + if err != nil { + return err + } + } + updates := withdrawalApplicationReviewUpdates(input, effect) + if err := tx.Model(&application).Updates(updates).Error; err != nil { + return err + } + applyWithdrawalApplicationReview(&application, input, effect) + return nil }) if err != nil { return nil, err } - if strings.TrimSpace(appCode) != "" { - return s.GetWithdrawalApplicationForApp(appCode, id) + return &application, nil +} + +func withdrawalApplicationReviewError(application model.UserWithdrawalApplication, stage WithdrawalApplicationReviewStage) error { + if application.Status != model.WithdrawalApplicationStatusPending { + return ErrWithdrawalApplicationAlreadyAudited } - return s.GetWithdrawalApplication(id) + operationsStatus := strings.TrimSpace(application.OperationsStatus) + if operationsStatus == "" { + // 数据库迁移只把历史终态行填成 skipped;空值只兼容迁移前构造的模型和旧测试夹具。 + operationsStatus = model.WithdrawalOperationsStatusSkipped + } + switch stage { + case WithdrawalApplicationReviewStageOperations: + if operationsStatus == model.WithdrawalOperationsStatusPending { + return nil + } + case WithdrawalApplicationReviewStageFinance: + if operationsStatus == model.WithdrawalOperationsStatusApproved || operationsStatus == model.WithdrawalOperationsStatusSkipped { + return nil + } + } + return ErrWithdrawalApplicationStageNotReviewable +} + +func withdrawalApplicationReviewUpdates(input WithdrawalApplicationAuditInput, effect WithdrawalApplicationAuditEffect) map[string]any { + updates := map[string]any{"updated_at_ms": input.ApprovedAtMS} + if input.Stage == WithdrawalApplicationReviewStageOperations { + updates["operations_status"] = input.Decision + updates["operations_reviewer_user_id"] = input.ApproverUserID + updates["operations_reviewer_name"] = strings.TrimSpace(input.ApproverName) + updates["operations_audit_remark"] = strings.TrimSpace(input.AuditRemark) + updates["operations_audit_command_id"] = strings.TrimSpace(effect.CommandID) + updates["operations_audit_transaction_id"] = strings.TrimSpace(effect.TransactionID) + updates["operations_reviewed_at_ms"] = input.ApprovedAtMS + if input.Decision == model.WithdrawalApplicationStatusRejected { + updates["status"] = model.WithdrawalApplicationStatusRejected + } + return updates + } + updates["status"] = input.Decision + updates["approver_user_id"] = input.ApproverUserID + updates["approver_name"] = strings.TrimSpace(input.ApproverName) + updates["audit_remark"] = strings.TrimSpace(input.AuditRemark) + updates["audit_image_url"] = strings.TrimSpace(input.AuditImageURL) + updates["audit_command_id"] = strings.TrimSpace(effect.CommandID) + updates["audit_transaction_id"] = strings.TrimSpace(effect.TransactionID) + updates["approved_at_ms"] = input.ApprovedAtMS + return updates +} + +func applyWithdrawalApplicationReview(application *model.UserWithdrawalApplication, input WithdrawalApplicationAuditInput, effect WithdrawalApplicationAuditEffect) { + if application == nil { + return + } + application.UpdatedAtMS = input.ApprovedAtMS + if input.Stage == WithdrawalApplicationReviewStageOperations { + application.OperationsStatus = input.Decision + application.OperationsReviewerUserID = &input.ApproverUserID + application.OperationsReviewerName = strings.TrimSpace(input.ApproverName) + application.OperationsAuditRemark = strings.TrimSpace(input.AuditRemark) + application.OperationsAuditCommandID = strings.TrimSpace(effect.CommandID) + application.OperationsAuditTransactionID = strings.TrimSpace(effect.TransactionID) + application.OperationsReviewedAtMS = &input.ApprovedAtMS + if input.Decision == model.WithdrawalApplicationStatusRejected { + application.Status = model.WithdrawalApplicationStatusRejected + } + return + } + application.Status = input.Decision + application.ApproverUserID = &input.ApproverUserID + application.ApproverName = strings.TrimSpace(input.ApproverName) + application.AuditRemark = strings.TrimSpace(input.AuditRemark) + application.AuditImageURL = strings.TrimSpace(input.AuditImageURL) + application.AuditCommandID = strings.TrimSpace(effect.CommandID) + application.AuditTransactionID = strings.TrimSpace(effect.TransactionID) + application.ApprovedAtMS = &input.ApprovedAtMS } // ApprovedWithdrawalStats 按审批通过时间聚合用户提现申请的 USDT 金额。 @@ -147,11 +401,26 @@ func (s *Store) ApprovedWithdrawalStats(appCode string, startAtMS int64, endAtMS func applyWithdrawalApplicationFilters(query *gorm.DB, options WithdrawalApplicationListOptions) *gorm.DB { if appCode := strings.TrimSpace(options.AppCode); appCode != "" { query = query.Where("app_code = ?", appCode) + } else if options.RestrictAppCodes { + if len(options.AllowedAppCodes) == 0 { + // 有财务权限但未授予任何资金数据范围时必须返回空集,不能把空 IN 退化成全 App 查询。 + query = query.Where("1 = 0") + } else { + query = query.Where("app_code IN ?", options.AllowedAppCodes) + } } if keyword := strings.TrimSpace(options.Keyword); keyword != "" { like := "%" + keyword + "%" - // 关键词面向财务排查,覆盖用户、收款方式、收款地址和审批人;不做金额模糊,避免 decimal 隐式转换拖慢常规查询。 - query = query.Where("user_id LIKE ? OR withdraw_method LIKE ? OR withdraw_address LIKE ? OR approver_name LIKE ? OR CAST(id AS CHAR) LIKE ?", like, like, like, like, like) + // 关键词面向两级审核排查,覆盖用户、收款方式、收款地址和两阶段审核人;不做金额模糊,避免 decimal 隐式转换拖慢常规查询。 + query = query.Where("user_id LIKE ? OR withdraw_method LIKE ? OR withdraw_address LIKE ? OR approver_name LIKE ? OR operations_reviewer_name LIKE ? OR CAST(id AS CHAR) LIKE ?", like, like, like, like, like, like) + } + switch options.Stage { + case WithdrawalApplicationReviewStageFinance: + // skipped 是 102 迁移前的历史申请;它们保持原财务队列,不倒退补做运营初审。 + query = query.Where("operations_status IN ?", []string{model.WithdrawalOperationsStatusApproved, model.WithdrawalOperationsStatusSkipped}) + case WithdrawalApplicationReviewStageOperations: + // 运营页保留已审核历史,但永远不展示 skipped 旧单,避免把历史财务申请伪装成运营已审。 + query = query.Where("operations_status <> ?", model.WithdrawalOperationsStatusSkipped) } return query } diff --git a/server/admin/internal/repository/withdrawal_application_repository_test.go b/server/admin/internal/repository/withdrawal_application_repository_test.go index 80a2046f..830c93fe 100644 --- a/server/admin/internal/repository/withdrawal_application_repository_test.go +++ b/server/admin/internal/repository/withdrawal_application_repository_test.go @@ -1,21 +1,33 @@ package repository import ( + "database/sql" + "errors" + "fmt" + "os" + "strings" + "sync" "testing" + "time" + + "hyapp-admin-server/internal/model" "github.com/DATA-DOG/go-sqlmock" + mysqlDriver "github.com/go-sql-driver/mysql" + "gorm.io/driver/mysql" + "gorm.io/gorm" ) -func TestListWithdrawalApplicationsFiltersAndSorts(t *testing.T) { +func TestListWithdrawalApplicationsFiltersFinanceStageAndSorts(t *testing.T) { store, mock, closeStore := newRepositorySQLMock(t) defer closeStore() like := "%TRC20%" - mock.ExpectQuery("SELECT count\\(\\*\\) FROM `admin_user_withdrawal_applications`"). - WithArgs("lalu", like, like, like, like, like). + mock.ExpectQuery("SELECT count\\(\\*\\) FROM `admin_user_withdrawal_applications`.*operations_status IN"). + WithArgs("lalu", like, like, like, like, like, like, model.WithdrawalOperationsStatusApproved, model.WithdrawalOperationsStatusSkipped). WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(2)) - mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`"). - WithArgs("lalu", like, like, like, like, like, 50, 50). + mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`.*operations_status IN"). + WithArgs("lalu", like, like, like, like, like, like, model.WithdrawalOperationsStatusApproved, model.WithdrawalOperationsStatusSkipped, 50, 50). WillReturnRows(sqlmock.NewRows([]string{ "id", "app_code", @@ -24,18 +36,20 @@ func TestListWithdrawalApplicationsFiltersAndSorts(t *testing.T) { "withdraw_method", "withdraw_address", "status", + "operations_status", "approver_user_id", "approver_name", "approved_at_ms", "created_at_ms", "updated_at_ms", - }).AddRow(3, "lalu", "10003", "22.50", "USDT-TRC20", "addr-3", "approved", 9, "财务", int64(1700000200000), int64(1700000100000), int64(1700000200000))) + }).AddRow(3, "lalu", "10003", "22.50", "USDT-TRC20", "addr-3", "approved", "approved", 9, "财务", int64(1700000200000), int64(1700000100000), int64(1700000200000))) items, total, err := store.ListWithdrawalApplications(WithdrawalApplicationListOptions{ AppCode: " lalu ", Keyword: " TRC20 ", Page: 2, PageSize: 50, + Stage: WithdrawalApplicationReviewStageFinance, }) if err != nil { t.Fatalf("list withdrawal applications failed: %v", err) @@ -51,6 +65,312 @@ func TestListWithdrawalApplicationsFiltersAndSorts(t *testing.T) { } } +func TestListWithdrawalApplicationsOperationsStageExcludesLegacySkipped(t *testing.T) { + store, mock, closeStore := newRepositorySQLMock(t) + defer closeStore() + + mock.ExpectQuery("SELECT count\\(\\*\\) FROM `admin_user_withdrawal_applications`.*operations_status <> \\?"). + WithArgs("fami", model.WithdrawalOperationsStatusSkipped). + WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1)) + mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`.*operations_status <> \\?"). + WithArgs("fami", model.WithdrawalOperationsStatusSkipped, 20). + WillReturnRows(withdrawalApplicationRows(model.WithdrawalApplicationStatusPending, model.WithdrawalOperationsStatusPending)) + + items, total, err := store.ListWithdrawalApplications(WithdrawalApplicationListOptions{ + AppCode: "fami", Page: 1, PageSize: 20, Stage: WithdrawalApplicationReviewStageOperations, + }) + if err != nil { + t.Fatalf("list operations withdrawal applications failed: %v", err) + } + if total != 1 || len(items) != 1 || items[0].OperationsStatus != model.WithdrawalOperationsStatusPending { + t.Fatalf("operations withdrawal list mismatch: total=%d items=%+v", total, items) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} + +func TestReviewWithdrawalApplicationOperationsApprovalKeepsOverallPending(t *testing.T) { + store, mock, closeStore := newRepositorySQLMock(t) + defer closeStore() + + mock.ExpectBegin() + mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`.*FOR UPDATE"). + WithArgs("fami", uint(77), 1). + WillReturnRows(withdrawalApplicationRows(model.WithdrawalApplicationStatusPending, model.WithdrawalOperationsStatusPending)) + mock.ExpectExec("UPDATE `admin_user_withdrawal_applications` SET").WillReturnResult(sqlmock.NewResult(0, 1)) + mock.ExpectCommit() + + callbackCalls := 0 + item, err := store.ReviewWithdrawalApplicationForApp("fami", 77, WithdrawalApplicationAuditInput{ + Stage: WithdrawalApplicationReviewStageOperations, + Decision: model.WithdrawalApplicationStatusApproved, + ApproverUserID: 8, + ApproverName: "运营", + AuditRemark: "资料无误", + ApprovedAtMS: 1700000300000, + }, func(application model.UserWithdrawalApplication) (WithdrawalApplicationAuditEffect, error) { + callbackCalls++ + if application.OperationsStatus != model.WithdrawalOperationsStatusPending { + t.Fatalf("callback must observe operations pending row under lock: %+v", application) + } + return WithdrawalApplicationAuditEffect{}, nil + }) + if err != nil { + t.Fatalf("approve operations withdrawal failed: %v", err) + } + if callbackCalls != 1 || item.Status != model.WithdrawalApplicationStatusPending || item.OperationsStatus != model.WithdrawalOperationsStatusApproved || item.OperationsReviewerName != "运营" { + t.Fatalf("operations approval state mismatch: calls=%d item=%+v", callbackCalls, item) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} + +func TestReviewWithdrawalApplicationRefusesOperationsRejectionWithoutDurableClaim(t *testing.T) { + store, mock, closeStore := newRepositorySQLMock(t) + defer closeStore() + + callbackCalled := false + _, err := store.ReviewWithdrawalApplicationForApp("fami", 77, WithdrawalApplicationAuditInput{ + Stage: WithdrawalApplicationReviewStageOperations, Decision: model.WithdrawalApplicationStatusRejected, + ApproverUserID: 8, ApprovedAtMS: 1700000300000, + }, func(model.UserWithdrawalApplication) (WithdrawalApplicationAuditEffect, error) { + callbackCalled = true + return WithdrawalApplicationAuditEffect{}, nil + }) + if err == nil || !strings.Contains(err.Error(), "durable claim") || callbackCalled { + t.Fatalf("operations rejection must use durable claim path: err=%v callback=%t", err, callbackCalled) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("operations rejection bypass touched database: %v", err) + } +} + +func TestClaimAndFinalizeWithdrawalOperationsRejectionPersistsDurableIntermediateState(t *testing.T) { + store, mock, closeStore := newRepositorySQLMock(t) + defer closeStore() + + // claim 必须先独立提交 rejecting 和固定审核上下文,外部 wallet/notice 此后失败也不能把行回滚到 pending。 + mock.ExpectBegin() + mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`.*FOR UPDATE"). + WithArgs("fami", uint(77), 1). + WillReturnRows(withdrawalApplicationRows(model.WithdrawalApplicationStatusPending, model.WithdrawalOperationsStatusPending)) + mock.ExpectExec("UPDATE `admin_user_withdrawal_applications` SET").WillReturnResult(sqlmock.NewResult(0, 1)) + mock.ExpectCommit() + + validatorCalls := 0 + claimed, err := store.ClaimWithdrawalOperationsRejectionForApp("fami", 77, WithdrawalApplicationAuditInput{ + Stage: WithdrawalApplicationReviewStageOperations, Decision: model.WithdrawalApplicationStatusRejected, + ApproverUserID: 8, ApproverName: "运营", AuditRemark: "资料不符", + AuditCommandID: "salary-withdrawal:77:operations", ApprovedAtMS: 1700000300000, + }, func(application model.UserWithdrawalApplication) error { + validatorCalls++ + if application.FreezeTransactionID != "tx-freeze" { + t.Fatalf("claim validator must observe locked freeze snapshot: %+v", application) + } + return nil + }) + if err != nil { + t.Fatalf("claim operations rejection failed: %v", err) + } + if validatorCalls != 1 || claimed.Status != model.WithdrawalApplicationStatusPending || claimed.OperationsStatus != model.WithdrawalOperationsStatusRejecting || claimed.OperationsAuditCommandID != "salary-withdrawal:77:operations" { + t.Fatalf("operations rejection claim mismatch: validator_calls=%d item=%+v", validatorCalls, claimed) + } + + // wallet 与 notice 成功后只允许相同 command 把 rejecting 收敛成双重 rejected,并保存实际 release transaction。 + mock.ExpectBegin() + mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`.*FOR UPDATE"). + WithArgs("fami", uint(77), 1). + WillReturnRows(withdrawalApplicationRowsWithOperationsContext(model.WithdrawalApplicationStatusPending, model.WithdrawalOperationsStatusRejecting, 8, "运营", "资料不符")) + mock.ExpectExec("UPDATE `admin_user_withdrawal_applications` SET").WillReturnResult(sqlmock.NewResult(0, 1)) + mock.ExpectCommit() + + item, err := store.FinalizeWithdrawalOperationsRejectionForApp("fami", 77, "salary-withdrawal:77:operations", "release-tx", 1700000300001) + if err != nil { + t.Fatalf("finalize operations rejection failed: %v", err) + } + if item.Status != model.WithdrawalApplicationStatusRejected || item.OperationsStatus != model.WithdrawalOperationsStatusRejected || item.OperationsAuditTransactionID != "release-tx" || item.OperationsAuditRemark != "资料不符" { + t.Fatalf("operations rejection terminal state mismatch: %+v", item) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} + +func TestClaimWithdrawalOperationsRejectionRetryPreservesFirstAuditContext(t *testing.T) { + store, mock, closeStore := newRepositorySQLMock(t) + defer closeStore() + + mock.ExpectBegin() + mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`.*FOR UPDATE"). + WithArgs("fami", uint(77), 1). + WillReturnRows(withdrawalApplicationRowsWithOperationsContext(model.WithdrawalApplicationStatusPending, model.WithdrawalOperationsStatusRejecting, 8, "第一次运营", "第一次原因")) + mock.ExpectCommit() + + item, err := store.ClaimWithdrawalOperationsRejectionForApp("fami", 77, WithdrawalApplicationAuditInput{ + Stage: WithdrawalApplicationReviewStageOperations, Decision: model.WithdrawalApplicationStatusRejected, + ApproverUserID: 18, ApproverName: "重试运营", AuditRemark: "重试原因不能覆盖", + AuditCommandID: "salary-withdrawal:77:operations", ApprovedAtMS: 1700000400000, + }, nil) + if err != nil { + t.Fatalf("retry operations rejection claim failed: %v", err) + } + if item.OperationsReviewerUserID == nil || *item.OperationsReviewerUserID != 8 || item.OperationsReviewerName != "第一次运营" || item.OperationsAuditRemark != "第一次原因" { + t.Fatalf("retry claim overwrote first audit context: %+v", item) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} + +func TestWithdrawalOperationsRejectionClaimSerializesConcurrentFirstAndRetryRealMySQL(t *testing.T) { + baseDSN := strings.TrimSpace(os.Getenv("WITHDRAWAL_REVIEW_MYSQL_TEST_DSN")) + if baseDSN == "" { + t.Skip("set WITHDRAWAL_REVIEW_MYSQL_TEST_DSN to run the real MySQL rejection-claim concurrency test") + } + db := newWithdrawalReviewMySQLTestDB(t, baseDSN) + if _, err := db.Exec(`CREATE TABLE admin_user_withdrawal_applications ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + app_code VARCHAR(32) NOT NULL, + user_id VARCHAR(64) NOT NULL, + salary_asset_type VARCHAR(64) NOT NULL DEFAULT '', + withdraw_amount DECIMAL(18,2) NOT NULL DEFAULT 0, + withdraw_amount_minor BIGINT NOT NULL DEFAULT 0, + freeze_transaction_id VARCHAR(128) NOT NULL DEFAULT '', + status VARCHAR(32) NOT NULL DEFAULT 'pending', + operations_status VARCHAR(32) NOT NULL DEFAULT 'pending', + operations_reviewer_user_id BIGINT UNSIGNED NULL, + operations_reviewer_name VARCHAR(64) NOT NULL DEFAULT '', + operations_audit_remark TEXT NULL, + operations_audit_command_id VARCHAR(128) NOT NULL DEFAULT '', + operations_audit_transaction_id VARCHAR(128) NOT NULL DEFAULT '', + operations_reviewed_at_ms BIGINT NULL, + created_at_ms BIGINT NOT NULL, + updated_at_ms BIGINT NOT NULL, + PRIMARY KEY (id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`); err != nil { + t.Fatalf("create withdrawal claim fixture table: %v", err) + } + if _, err := db.Exec(`INSERT INTO admin_user_withdrawal_applications + (id, app_code, user_id, salary_asset_type, withdraw_amount, withdraw_amount_minor, freeze_transaction_id, status, operations_status, created_at_ms, updated_at_ms) + VALUES (77, 'lalu', '42001', 'HOST_SALARY_USD', 50.00, 5000, 'freeze-tx', 'pending', 'pending', 1700000000000, 1700000000000)`); err != nil { + t.Fatalf("seed withdrawal claim fixture: %v", err) + } + gormDB, err := gorm.Open(mysql.New(mysql.Config{Conn: db, SkipInitializeWithVersion: true}), &gorm.Config{}) + if err != nil { + t.Fatalf("open withdrawal claim gorm connection: %v", err) + } + store := New(gormDB) + + type claimResult struct { + item *model.UserWithdrawalApplication + err error + } + start := make(chan struct{}) + results := make(chan claimResult, 2) + var workers sync.WaitGroup + for index, reviewerID := range []uint{8, 18} { + index, reviewerID := index, reviewerID + workers.Add(1) + go func() { + defer workers.Done() + <-start + item, err := store.ClaimWithdrawalOperationsRejectionForApp("lalu", 77, WithdrawalApplicationAuditInput{ + Stage: WithdrawalApplicationReviewStageOperations, Decision: model.WithdrawalApplicationStatusRejected, + ApproverUserID: reviewerID, ApproverName: fmt.Sprintf("operator-%d", reviewerID), AuditRemark: fmt.Sprintf("reason-%d", reviewerID), + AuditCommandID: "salary-withdrawal:77:operations", ApprovedAtMS: int64(1700000300000 + index), + }, nil) + results <- claimResult{item: item, err: err} + }() + } + close(start) + workers.Wait() + close(results) + + var persistedReviewerID uint + for result := range results { + if result.err != nil { + t.Fatalf("concurrent rejection claim failed: %v", result.err) + } + if result.item == nil || result.item.OperationsStatus != model.WithdrawalOperationsStatusRejecting || result.item.OperationsReviewerUserID == nil { + t.Fatalf("concurrent rejection claim result mismatch: %+v", result.item) + } + if persistedReviewerID == 0 { + persistedReviewerID = *result.item.OperationsReviewerUserID + } else if persistedReviewerID != *result.item.OperationsReviewerUserID { + t.Fatalf("concurrent retry observed different claim owners: first=%d result=%+v", persistedReviewerID, result.item) + } + } + + // 两个请求都可能在外部幂等动作后并发 finalize;相同行锁和 command/transaction 校验必须让二者返回同一终态。 + finalizeResults := make(chan error, 2) + start = make(chan struct{}) + workers = sync.WaitGroup{} + for range 2 { + workers.Add(1) + go func() { + defer workers.Done() + <-start + _, err := store.FinalizeWithdrawalOperationsRejectionForApp("lalu", 77, "salary-withdrawal:77:operations", "release-tx", 1700000400000) + finalizeResults <- err + }() + } + close(start) + workers.Wait() + close(finalizeResults) + for err := range finalizeResults { + if err != nil { + t.Fatalf("concurrent rejection finalize failed: %v", err) + } + } + final, err := store.GetWithdrawalApplicationForApp("lalu", 77) + if err != nil { + t.Fatalf("read final rejection state: %v", err) + } + if final.Status != model.WithdrawalApplicationStatusRejected || final.OperationsStatus != model.WithdrawalOperationsStatusRejected || final.OperationsAuditTransactionID != "release-tx" || final.OperationsReviewerUserID == nil || *final.OperationsReviewerUserID != persistedReviewerID { + t.Fatalf("concurrent rejection terminal mismatch: %+v", final) + } +} + +func TestReviewWithdrawalApplicationFinanceRejectsOperationsPendingBeforeAction(t *testing.T) { + store, mock, closeStore := newRepositorySQLMock(t) + defer closeStore() + + mock.ExpectBegin() + mock.ExpectQuery("SELECT \\* FROM `admin_user_withdrawal_applications`.*FOR UPDATE"). + WithArgs("fami", uint(77), 1). + WillReturnRows(withdrawalApplicationRows(model.WithdrawalApplicationStatusPending, model.WithdrawalOperationsStatusPending)) + mock.ExpectRollback() + + callbackCalled := false + _, err := store.ReviewWithdrawalApplicationForApp("fami", 77, WithdrawalApplicationAuditInput{ + Stage: WithdrawalApplicationReviewStageFinance, Decision: model.WithdrawalApplicationStatusApproved, + ApproverUserID: 9, ApprovedAtMS: 1700000300000, + }, func(model.UserWithdrawalApplication) (WithdrawalApplicationAuditEffect, error) { + callbackCalled = true + return WithdrawalApplicationAuditEffect{}, nil + }) + if !errors.Is(err, ErrWithdrawalApplicationStageNotReviewable) || callbackCalled { + t.Fatalf("finance must reject operations-pending row before callback: err=%v callback=%t", err, callbackCalled) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} + +func TestWithdrawalApplicationReviewErrorAllowsLegacySkippedInFinanceStage(t *testing.T) { + t.Parallel() + + err := withdrawalApplicationReviewError(model.UserWithdrawalApplication{ + Status: model.WithdrawalApplicationStatusPending, + OperationsStatus: model.WithdrawalOperationsStatusSkipped, + }, WithdrawalApplicationReviewStageFinance) + if err != nil { + t.Fatalf("legacy skipped application must remain finance-reviewable: %v", err) + } +} + func TestGetWithdrawalApplicationForAppScopesByAppCode(t *testing.T) { store, mock, closeStore := newRepositorySQLMock(t) defer closeStore() @@ -112,3 +432,66 @@ func TestGetWithdrawalApplicationForAppScopesByAppCode(t *testing.T) { t.Fatalf("sql expectations mismatch: %v", err) } } + +func newWithdrawalReviewMySQLTestDB(t *testing.T, baseDSN string) *sql.DB { + t.Helper() + baseConfig, err := mysqlDriver.ParseDSN(baseDSN) + if err != nil { + t.Fatalf("parse withdrawal review MySQL test DSN: %v", err) + } + databaseName := fmt.Sprintf("hy_admin_withdrawal_review_%d", time.Now().UnixNano()) + adminConfig := baseConfig.Clone() + adminConfig.DBName = "" + adminDB, err := sql.Open("mysql", adminConfig.FormatDSN()) + if err != nil { + t.Fatalf("open withdrawal review MySQL admin connection: %v", err) + } + if _, err := adminDB.Exec("CREATE DATABASE `" + databaseName + "` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); err != nil { + _ = adminDB.Close() + t.Fatalf("create withdrawal review MySQL test database: %v", err) + } + testConfig := baseConfig.Clone() + testConfig.DBName = databaseName + db, err := sql.Open("mysql", testConfig.FormatDSN()) + if err != nil { + _, _ = adminDB.Exec("DROP DATABASE IF EXISTS `" + databaseName + "`") + _ = adminDB.Close() + t.Fatalf("open withdrawal review MySQL test connection: %v", err) + } + t.Cleanup(func() { + _ = db.Close() + _, _ = adminDB.Exec("DROP DATABASE IF EXISTS `" + databaseName + "`") + _ = adminDB.Close() + }) + return db +} + +func withdrawalApplicationRows(status string, operationsStatus string) *sqlmock.Rows { + return withdrawalApplicationRowsWithOperationsContext(status, operationsStatus, 0, "", "") +} + +func withdrawalApplicationRowsWithOperationsContext(status string, operationsStatus string, reviewerID uint, reviewerName string, remark string) *sqlmock.Rows { + var storedReviewerID any + var reviewedAtMS any + operationsCommandID := "" + if reviewerID > 0 { + storedReviewerID = reviewerID + reviewedAtMS = int64(1700000300000) + operationsCommandID = "salary-withdrawal:77:operations" + } + return sqlmock.NewRows([]string{ + "id", "app_code", "user_id", "salary_asset_type", "withdraw_amount", "withdraw_amount_minor", + "withdraw_method", "withdraw_address", "freeze_command_id", "freeze_transaction_id", + "audit_command_id", "audit_transaction_id", "status", "operations_status", + "approver_user_id", "approver_name", "audit_remark", "audit_image_url", "approved_at_ms", + "operations_reviewer_user_id", "operations_reviewer_name", "operations_audit_remark", + "operations_audit_command_id", "operations_audit_transaction_id", "operations_reviewed_at_ms", + "created_at_ms", "updated_at_ms", + }).AddRow( + 77, "fami", "42001", "POINT", "9.50", int64(1000000), + "usdt_trc20", "TQY9pFbZHuR4fUN9WgXPYj5nmB6nQiLQfF", "cmd-point-freeze", "tx-freeze", + "", "", status, operationsStatus, nil, "", "", "", nil, + storedReviewerID, reviewerName, remark, operationsCommandID, "", reviewedAtMS, + int64(1700000000000), int64(1700000000000), + ) +} diff --git a/server/admin/internal/response/codes.go b/server/admin/internal/response/codes.go index c6b16195..1277997e 100644 --- a/server/admin/internal/response/codes.go +++ b/server/admin/internal/response/codes.go @@ -7,5 +7,8 @@ const ( CodeForbidden = 40300 CodeNotFound = 40400 CodeConflict = 40900 + CodePayloadLarge = 41300 + CodeTooMany = 42900 CodeServerError = 50000 + CodeUnavailable = 50300 ) diff --git a/server/admin/internal/response/error.go b/server/admin/internal/response/error.go index 47662d8b..b1140239 100644 --- a/server/admin/internal/response/error.go +++ b/server/admin/internal/response/error.go @@ -30,6 +30,18 @@ func Conflict(c *gin.Context, message string) { Fail(c, http.StatusConflict, CodeConflict, message) } +func PayloadTooLarge(c *gin.Context, message string) { + Fail(c, http.StatusRequestEntityTooLarge, CodePayloadLarge, message) +} + +func TooManyRequests(c *gin.Context, message string) { + Fail(c, http.StatusTooManyRequests, CodeTooMany, message) +} + func ServerError(c *gin.Context, message string) { Fail(c, http.StatusInternalServerError, CodeServerError, message) } + +func ServiceUnavailable(c *gin.Context, message string) { + Fail(c, http.StatusServiceUnavailable, CodeUnavailable, message) +} diff --git a/server/admin/internal/router/router.go b/server/admin/internal/router/router.go index d1b3b74e..29216dea 100644 --- a/server/admin/internal/router/router.go +++ b/server/admin/internal/router/router.go @@ -1,6 +1,8 @@ package router import ( + "fmt" + "hyapp-admin-server/internal/config" "hyapp-admin-server/internal/middleware" "hyapp-admin-server/internal/modules/achievementconfig" @@ -20,6 +22,7 @@ import ( "hyapp-admin-server/internal/modules/dailytask" "hyapp-admin-server/internal/modules/dashboard" "hyapp-admin-server/internal/modules/databi" + "hyapp-admin-server/internal/modules/externaladmin" "hyapp-admin-server/internal/modules/financeorder" "hyapp-admin-server/internal/modules/financewithdrawal" "hyapp-admin-server/internal/modules/firstrechargereward" @@ -89,6 +92,7 @@ type Handlers struct { FirstRechargeReward *firstrechargereward.Handler FinanceOrder *financeorder.Handler FinanceWithdrawal *financewithdrawal.Handler + ExternalAdmin *externaladmin.Handler FullServerNotice *fullservernotice.Handler Game *gamemanagement.Handler GiftDiamond *giftdiamond.Handler @@ -131,6 +135,13 @@ type Handlers struct { func New(cfg config.Config, auth *service.AuthService, store *repository.Store, h Handlers) *gin.Engine { engine := gin.New() + // SetTrustedProxies must be called even for an empty list; otherwise Gin 1.10 + // trusts every proxy by default and client-controlled XFF can defeat IP limits. + // Config validation rejects malformed entries before startup; panic here catches + // only tests/manual constructors that bypass the normal validated load path. + if err := engine.SetTrustedProxies(cfg.TrustedProxies); err != nil { + panic(fmt.Sprintf("configure trusted proxies: %v", err)) + } engine.Use(middleware.RequestID(), middleware.AppCode(), logging.GinAccessLogger(), gin.Recovery(), middleware.CORS(cfg)) engine.GET("/healthz", h.Health.Health) @@ -138,11 +149,15 @@ func New(cfg config.Config, auth *service.AuthService, store *repository.Store, api := engine.Group("/api/v1") protected := api.Group("") - protected.Use(middleware.AuthRequired(auth), middleware.Audit(h.Audit)) + protected.Use(middleware.AuthRequired(auth, store), middleware.Audit(h.Audit)) appProtected := protected.Group("") appProtected.Use(middleware.RequireAppScope(store)) authroutes.RegisterRoutes(api, protected, h.Auth) + externaladmin.RegisterExternalRoutes(api, h.ExternalAdmin, externaladmin.BusinessHandlers{ + AppUser: h.AppUser, HostOrg: h.HostOrg, RoomAdmin: h.RoomAdmin, Resource: h.Resource, + PrettyID: h.PrettyID, AppConfig: h.AppConfig, VIPConfig: h.VIPConfig, Upload: h.Upload, + }) agencyopening.RegisterRoutes(appProtected, h.AgencyOpening) activitytemplate.RegisterRoutes(appProtected, h.ActivityTemplate) achievementconfig.RegisterRoutes(appProtected, h.AchievementConfig) @@ -153,6 +168,7 @@ func New(cfg config.Config, auth *service.AuthService, store *repository.Store, reportmodule.RegisterRoutes(appProtected, h.Report) resourcemodule.RegisterRoutes(appProtected, h.Resource) adminuser.RegisterRoutes(protected, h.AdminUser) + externaladmin.RegisterAdminRoutes(appProtected, h.ExternalAdmin) appuser.RegisterRoutes(appProtected, h.AppUser) appregistry.RegisterRoutes(protected, h.AppRegistry) appconfig.RegisterRoutes(appProtected, h.AppConfig) diff --git a/server/admin/internal/router/router_test.go b/server/admin/internal/router/router_test.go index 7f8fc91d..8823281b 100644 --- a/server/admin/internal/router/router_test.go +++ b/server/admin/internal/router/router_test.go @@ -8,10 +8,16 @@ import ( "time" "hyapp-admin-server/internal/config" + "hyapp-admin-server/internal/modules/appuser" + "hyapp-admin-server/internal/modules/externaladmin" "hyapp-admin-server/internal/modules/opscenter" + "hyapp-admin-server/internal/repository" "hyapp-admin-server/internal/service" + "github.com/DATA-DOG/go-sqlmock" "github.com/gin-gonic/gin" + "gorm.io/driver/mysql" + "gorm.io/gorm" ) func TestOpsCenterAppBootstrapDoesNotRequireAppCode(t *testing.T) { @@ -21,8 +27,21 @@ func TestOpsCenterAppBootstrapDoesNotRequireAppCode(t *testing.T) { if err != nil { t.Fatalf("generate access token: %v", err) } + sqlDB, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("create sql mock: %v", err) + } + defer sqlDB.Close() + gormDB, err := gorm.Open(mysql.New(mysql.Config{Conn: sqlDB, SkipInitializeWithVersion: true}), &gorm.Config{}) + if err != nil { + t.Fatalf("create gorm db: %v", err) + } + store := repository.New(gormDB) + mock.ExpectQuery("(?s)SELECT admin_users\\.username,.*FROM admin_users.*WHERE admin_users\\.id = \\?.*ORDER BY admin_permissions\\.code ASC"). + WithArgs(uint(7)). + WillReturnRows(sqlmock.NewRows([]string{"username", "status", "permission_code"}).AddRow("operator", "active", nil)) - engine := New(config.Config{}, auth, nil, Handlers{OpsCenter: opscenter.New(nil, nil)}) + engine := New(config.Config{}, auth, store, Handlers{OpsCenter: opscenter.New(nil, nil)}) request := httptest.NewRequest(http.MethodGet, "/api/v1/admin/ops-center/apps", nil) request.Header.Set("Authorization", "Bearer "+token) response := httptest.NewRecorder() @@ -43,4 +62,72 @@ func TestOpsCenterAppBootstrapDoesNotRequireAppCode(t *testing.T) { if unauthorized.Code != http.StatusUnauthorized { t.Fatalf("unauthorized status = %d body=%s", unauthorized.Code, unauthorized.Body.String()) } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("authorization sql expectations: %v", err) + } +} + +func TestExternalPortalRegistersOnlyExplicitAppUserWhitelist(t *testing.T) { + gin.SetMode(gin.TestMode) + auth := service.NewAuthService("external-router-test-secret", time.Hour) + externalHandler := externaladmin.New(nil, nil, externaladmin.Config{}, nil) + engine := New(config.Config{}, auth, nil, Handlers{ + ExternalAdmin: externalHandler, + AppUser: &appuser.Handler{}, + }) + + // The listed route exists and is protected by the isolated opaque session middleware. + allowed := httptest.NewRecorder() + engine.ServeHTTP(allowed, httptest.NewRequest(http.MethodGet, "/api/v1/external/app/users", nil)) + if allowed.Code != http.StatusUnauthorized { + t.Fatalf("whitelisted route status = %d body=%s", allowed.Code, allowed.Body.String()) + } + team := httptest.NewRecorder() + engine.ServeHTTP(team, httptest.NewRequest(http.MethodGet, "/api/v1/external/admin/my-team/agencies", nil)) + if team.Code != http.StatusUnauthorized { + t.Fatalf("my-team route must exist behind external session auth: status=%d body=%s", team.Code, team.Body.String()) + } + + for _, path := range []string{ + "/api/v1/external/app/users/1/password", + "/api/v1/external/app/users/1/access-token", + "/api/v1/external/exports/app-users", + } { + request := httptest.NewRequest(http.MethodPost, path, nil) + response := httptest.NewRecorder() + engine.ServeHTTP(response, request) + if response.Code != http.StatusNotFound { + t.Fatalf("non-whitelisted route %s status = %d body=%s", path, response.Code, response.Body.String()) + } + } +} + +func TestRouterDoesNotTrustForwardedIPFromDirectClient(t *testing.T) { + gin.SetMode(gin.TestMode) + engine := New(config.Config{TrustedProxies: []string{"127.0.0.0/8", "::1"}}, nil, nil, Handlers{}) + engine.GET("/__test_client_ip", func(c *gin.Context) { + c.String(http.StatusOK, c.ClientIP()) + }) + + // A direct caller is outside the configured ingress hop. Its XFF value must be + // ignored, otherwise it can rotate a forged address to bypass external-login limits. + directRequest := httptest.NewRequest(http.MethodGet, "/__test_client_ip", nil) + directRequest.RemoteAddr = "198.51.100.24:43210" + directRequest.Header.Set("X-Forwarded-For", "203.0.113.99") + directResponse := httptest.NewRecorder() + engine.ServeHTTP(directResponse, directRequest) + if got := directResponse.Body.String(); got != "198.51.100.24" { + t.Fatalf("direct client IP = %q, want socket peer", got) + } + + // The local Nginx hop is trusted, but Gin must stop at the right-most untrusted + // address. A prepended attacker-controlled value therefore cannot become identity. + proxiedRequest := httptest.NewRequest(http.MethodGet, "/__test_client_ip", nil) + proxiedRequest.RemoteAddr = "127.0.0.1:43210" + proxiedRequest.Header.Set("X-Forwarded-For", "203.0.113.99, 198.51.100.24") + proxiedResponse := httptest.NewRecorder() + engine.ServeHTTP(proxiedResponse, proxiedRequest) + if got := proxiedResponse.Body.String(); got != "198.51.100.24" { + t.Fatalf("proxied client IP = %q, want right-most untrusted hop", got) + } } diff --git a/server/admin/internal/security/security.go b/server/admin/internal/security/security.go index 1a855dab..70489bb2 100644 --- a/server/admin/internal/security/security.go +++ b/server/admin/internal/security/security.go @@ -13,7 +13,17 @@ func HashPassword(password string) (string, error) { if len(password) < 6 { return "", errors.New("password must contain at least 6 characters") } + return hashPassword(password) +} +// HashPasswordWithoutMinimum is reserved for credential domains that define their +// own policy before hashing. bcrypt still enforces its 72-byte maximum; keeping this +// separate prevents the external-admin exception from weakening main-admin passwords. +func HashPasswordWithoutMinimum(password string) (string, error) { + return hashPassword(password) +} + +func hashPassword(password string) (string, error) { hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return "", err diff --git a/server/admin/migrations/098_external_admin_portal.sql b/server/admin/migrations/098_external_admin_portal.sql new file mode 100644 index 00000000..cc19d5d0 --- /dev/null +++ b/server/admin/migrations/098_external_admin_portal.sql @@ -0,0 +1,136 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- 外管账号与主后台账号、App 用户账号完全隔离;所有唯一键都带 app_code,避免 Fami/Lalu 同名账号互相占用。 +-- 本迁移只创建小型认证/审计表并按唯一索引写权限元数据,不扫描 users、房间或钱包等大业务表。 +SET @now_ms = CAST(UNIX_TIMESTAMP(UTC_TIMESTAMP(3)) * 1000 AS UNSIGNED); + +CREATE TABLE IF NOT EXISTS external_admin_accounts ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '外管账号 ID', + app_code VARCHAR(32) NOT NULL COMMENT '固定 App 租户', + linked_app_user_id BIGINT NOT NULL COMMENT '绑定的 App 内部用户 ID', + username VARCHAR(64) NOT NULL COMMENT '外管登录账号,服务端统一转小写', + password_hash VARCHAR(255) NOT NULL COMMENT 'bcrypt 密码摘要', + permissions_json JSON NOT NULL COMMENT '允许进入外管白名单路由的权限快照', + status VARCHAR(24) NOT NULL DEFAULT 'active' COMMENT 'active/disabled', + password_change_required TINYINT(1) NOT NULL DEFAULT 1 COMMENT '管理员创建或重置后要求首次改密', + failed_login_count INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '连续登录失败次数', + locked_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT '失败锁定截止时间,UTC epoch ms', + last_login_at_ms BIGINT NULL COMMENT '最近成功登录时间,UTC epoch ms', + created_by_admin_id BIGINT UNSIGNED 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 (id), + UNIQUE KEY uk_external_admin_accounts_app_username (app_code, username), + UNIQUE KEY uk_external_admin_accounts_app_linked_user (app_code, linked_app_user_id), + KEY idx_external_admin_accounts_app_status_updated (app_code, status, updated_at_ms), + KEY idx_external_admin_accounts_creator (created_by_admin_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='独立外管账号'; + +CREATE TABLE IF NOT EXISTS external_admin_sessions ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '会话 ID', + account_id BIGINT UNSIGNED NOT NULL COMMENT '外管账号 ID', + app_code VARCHAR(32) NOT NULL COMMENT '创建时固化的 App 租户', + token_hash CHAR(64) CHARACTER SET ascii COLLATE ascii_bin NOT NULL COMMENT 'opaque session token SHA-256', + csrf_token_hash CHAR(64) CHARACTER SET ascii COLLATE ascii_bin NOT NULL COMMENT 'CSRF token SHA-256', + ip VARCHAR(64) NOT NULL DEFAULT '' COMMENT '登录 IP', + user_agent VARCHAR(512) NOT NULL DEFAULT '' COMMENT '登录客户端', + expires_at_ms BIGINT NOT NULL COMMENT '过期时间,UTC epoch ms', + last_seen_at_ms BIGINT NOT NULL COMMENT '最近访问时间,UTC epoch ms', + revoked_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '撤销时间,0 表示有效', + revoke_reason VARCHAR(64) NOT NULL DEFAULT '' COMMENT '撤销原因', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + PRIMARY KEY (id), + UNIQUE KEY uk_external_admin_sessions_token_hash (token_hash), + KEY idx_external_admin_sessions_account_active (account_id, revoked_at_ms, expires_at_ms), + KEY idx_external_admin_sessions_app_expiry (app_code, expires_at_ms), + CONSTRAINT fk_external_admin_sessions_account FOREIGN KEY (account_id) REFERENCES external_admin_accounts(id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='外管服务端 opaque 会话'; + +CREATE TABLE IF NOT EXISTS external_admin_login_logs ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '登录日志 ID', + account_id BIGINT UNSIGNED NULL COMMENT '命中账号时记录;未知账号保持 NULL 防止伪造关联', + app_code VARCHAR(32) NOT NULL COMMENT '请求 App', + username VARCHAR(64) NOT NULL COMMENT '请求账号', + ip VARCHAR(64) NOT NULL DEFAULT '' COMMENT '请求 IP', + user_agent VARCHAR(512) NOT NULL DEFAULT '' COMMENT '请求客户端', + status VARCHAR(24) NOT NULL COMMENT 'success/failed', + message VARCHAR(128) NOT NULL DEFAULT '' COMMENT '内部审计原因,不回传客户端', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + PRIMARY KEY (id), + KEY idx_external_admin_login_logs_app_username_time (app_code, username, created_at_ms), + KEY idx_external_admin_login_logs_account_time (account_id, created_at_ms), + KEY idx_external_admin_login_logs_status_time (status, created_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='外管登录日志'; + +CREATE TABLE IF NOT EXISTS external_admin_operation_logs ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '操作日志 ID', + account_id BIGINT UNSIGNED NOT NULL COMMENT '外管账号 ID', + app_code VARCHAR(32) NOT NULL COMMENT '会话固定 App', + username VARCHAR(64) NOT NULL COMMENT '外管账号', + request_id VARCHAR(64) NOT NULL DEFAULT '' COMMENT '请求链路 ID', + action VARCHAR(160) NOT NULL COMMENT 'HTTP 方法与路由模板', + resource VARCHAR(120) NOT NULL DEFAULT '' COMMENT '资源类型', + resource_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '目标资源 ID', + method VARCHAR(12) NOT NULL COMMENT 'HTTP 方法', + path VARCHAR(255) NOT NULL COMMENT '实际请求路径', + ip VARCHAR(64) NOT NULL DEFAULT '' COMMENT '请求 IP', + user_agent VARCHAR(512) NOT NULL DEFAULT '' COMMENT '请求客户端', + status VARCHAR(24) NOT NULL COMMENT 'success/failed', + http_status INT NOT NULL COMMENT 'HTTP 状态码', + latency_ms BIGINT NOT NULL DEFAULT 0 COMMENT '处理耗时', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + PRIMARY KEY (id), + KEY idx_external_admin_operation_logs_account_time (account_id, created_at_ms), + KEY idx_external_admin_operation_logs_app_time (app_code, created_at_ms), + KEY idx_external_admin_operation_logs_request (request_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='外管业务操作审计'; + +INSERT INTO admin_permissions (name, code, kind, description, created_at_ms, updated_at_ms) VALUES + ('外管用户查看', 'external-admin-user:view', 'menu', '查看当前 App 的外管用户', @now_ms, @now_ms), + ('外管用户创建', 'external-admin-user:create', 'button', '按当前 App 用户短 ID 创建外管账号', @now_ms, @now_ms), + ('外管用户状态', 'external-admin-user:status', 'button', '启用或停用当前 App 的外管账号', @now_ms, @now_ms), + ('外管用户重置密码', 'external-admin-user:reset-password', 'button', '重置当前 App 的外管账号密码并撤销全部会话', @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) +SELECT parent.id, '外管用户', 'operation-external-admin-users', '/operations/external-admin-users', 'shield', 'external-admin-user:view', 72, 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; + +-- 创建或重置密码等同于签发/接管固定的全能力外管账号,只允许平台管理员执行, +-- 避免运营角色通过委派获得自身权限矩阵中不存在的 VIP 发放等高风险能力。 +INSERT IGNORE INTO admin_role_permissions (role_id, permission_id) +SELECT role.id, permission.id +FROM admin_roles role +JOIN admin_permissions permission +WHERE role.code = 'platform-admin' + AND permission.code IN ( + 'external-admin-user:view', + 'external-admin-user:create', + 'external-admin-user:status', + 'external-admin-user:reset-password' + ); + +-- 运营负责人和运营专员负责日常查看、启用和停用,不持有账号凭据签发能力。 +INSERT IGNORE INTO admin_role_permissions (role_id, permission_id) +SELECT role.id, permission.id +FROM admin_roles role +JOIN admin_permissions permission +WHERE role.code IN ('ops-admin', 'operations-specialist') + AND permission.code IN ( + 'external-admin-user:view', + 'external-admin-user:status' + ); diff --git a/server/admin/migrations/099_external_admin_credential_delegation.sql b/server/admin/migrations/099_external_admin_credential_delegation.sql new file mode 100644 index 00000000..28d802d9 --- /dev/null +++ b/server/admin/migrations/099_external_admin_credential_delegation.sql @@ -0,0 +1,13 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- 098 尚未发布时本迁移为空操作;若某个环境曾执行过早期 098(曾把四项权限都给运营岗位), +-- 这里通过角色 code、权限 code 的唯一索引和关联表主键定点撤销,不扫描任何业务数据表。 +DELETE role_permission +FROM admin_role_permissions role_permission +JOIN admin_roles role ON role.id = role_permission.role_id +JOIN admin_permissions permission ON permission.id = role_permission.permission_id +WHERE role.code IN ('ops-admin', 'operations-specialist') + AND permission.code IN ( + 'external-admin-user:create', + 'external-admin-user:reset-password' + ); diff --git a/server/admin/migrations/100_external_admin_global_username.sql b/server/admin/migrations/100_external_admin_global_username.sql new file mode 100644 index 00000000..272a28b3 --- /dev/null +++ b/server/admin/migrations/100_external_admin_global_username.sql @@ -0,0 +1,13 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- 外管登录不再接受客户端选择 App,因此 username 必须在整张账号表中唯一, +-- 服务端才能仅凭账号确定唯一租户。该 DDL 不改写任何账号,也不会自动重命名冲突凭据: +-- 若历史数据存在同名账号,唯一索引构建会失败并保留原复合索引,要求人工确认归属后再重跑。 +-- external_admin_accounts 是小型凭据表;INPLACE + LOCK=NONE 只扫描该表建立二级索引, +-- 不扫描 users、房间、钱包等业务表,并允许迁移期间继续读写。并发写入若制造同名账号, +-- MySQL 会让索引构建失败而不是提交不唯一结构,保持 fail-closed。 +ALTER TABLE external_admin_accounts + ADD UNIQUE KEY uk_external_admin_accounts_username (username), + DROP INDEX uk_external_admin_accounts_app_username, + ALGORITHM=INPLACE, + LOCK=NONE; diff --git a/server/admin/migrations/101_external_admin_permission_assignment.sql b/server/admin/migrations/101_external_admin_permission_assignment.sql new file mode 100644 index 00000000..0ac0875b --- /dev/null +++ b/server/admin/migrations/101_external_admin_permission_assignment.sql @@ -0,0 +1,33 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- 098-100 may already be recorded in production, so permission delegation is added +-- incrementally instead of rewriting an executed migration. external_admin_accounts is a +-- small credential table; adding a fixed-width column with INPLACE + LOCK=NONE may scan/rebuild +-- only that table on older supported MySQL versions while allowing concurrent reads/writes. +-- Run this outside credential-creation peaks even though no users/rooms/wallet table is touched. +ALTER TABLE external_admin_accounts + ADD COLUMN permission_revision BIGINT UNSIGNED NOT NULL DEFAULT 1 AFTER permissions_json, + ALGORITHM=INPLACE, + LOCK=NONE; + +-- Both RBAC lookup predicates below use unique indexes (admin_permissions.code and +-- admin_roles.code); the final INSERT is guarded by admin_role_permissions(role_id, +-- permission_id), touches one row, and scans no business, external-account or session table. +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 + ('外管用户权限配置', 'external-admin-user:permissions', 'button', '配置当前 App 外管用户权限并撤销其现有会话', @now_ms, @now_ms) +ON DUPLICATE KEY UPDATE + name = VALUES(name), + kind = VALUES(kind), + description = VALUES(description), + updated_at_ms = @now_ms; + +-- 权限配置可以扩大外部操作者的业务能力,只授予平台管理员;运营岗位仍只拥有 +-- 098/099 中的查看与启停能力,不能通过本接口进行权限委派。 +INSERT IGNORE INTO admin_role_permissions (role_id, permission_id) +SELECT role.id, permission.id +FROM admin_roles role +JOIN admin_permissions permission +WHERE role.code = 'platform-admin' + AND permission.code = 'external-admin-user:permissions'; diff --git a/server/admin/migrations/102_user_withdrawal_operations_review.sql b/server/admin/migrations/102_user_withdrawal_operations_review.sql new file mode 100644 index 00000000..b38ecef7 --- /dev/null +++ b/server/admin/migrations/102_user_withdrawal_operations_review.sql @@ -0,0 +1,88 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- 这不是可直接混跑旧 admin 的普通滚动迁移:旧 admin 不读 operations_status,会把总体 status=pending 的新单直接财务终审。 +-- 生产必须先摘流所有旧 admin,再执行 102 并部署新 admin,恢复 admin 流量后才能滚动 gateway。 + +-- checkpoint 在首次执行时固定迁移前的最大申请 ID。迁移中断后重放仍使用原边界, +-- 不会把部署窗口内由旧 gateway 新建的单误标为 skipped。该表只保存小型迁移元数据,不承载业务状态。 +CREATE TABLE IF NOT EXISTS schema_migration_checkpoints ( + version VARCHAR(128) NOT NULL, + checkpoint_value BIGINT UNSIGNED NOT NULL DEFAULT 0, + created_at_ms BIGINT NOT NULL DEFAULT 0, + PRIMARY KEY (version) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='可重放迁移的持久边界'; + +INSERT IGNORE INTO schema_migration_checkpoints (version, checkpoint_value, created_at_ms) +SELECT '102_user_withdrawal_operations_review.sql', COALESCE(MAX(id), 0), CAST(UNIX_TIMESTAMP(UTC_TIMESTAMP(3)) * 1000 AS UNSIGNED) +FROM admin_user_withdrawal_applications; + +-- 新列的数据库默认必须是 pending:旧 gateway 不传新列,在滚动窗口内也会自动进入运营审核。 +-- 单个 ALTER 的列变更具有原子性;信息查询和持久 checkpoint 使整个文件在中断后可安全重放。 +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'admin_user_withdrawal_applications' AND COLUMN_NAME = 'operations_status') = 0, + 'ALTER TABLE admin_user_withdrawal_applications ADD COLUMN operations_status VARCHAR(32) NOT NULL DEFAULT ''pending'' COMMENT ''运营审核状态:skipped/pending/rejecting/approved/rejected'' AFTER status, ADD COLUMN operations_reviewer_user_id BIGINT UNSIGNED NULL AFTER operations_status, ADD COLUMN operations_reviewer_name VARCHAR(64) NOT NULL DEFAULT '''' AFTER operations_reviewer_user_id, ADD COLUMN operations_audit_remark TEXT NULL AFTER operations_reviewer_name, ADD COLUMN operations_audit_command_id VARCHAR(128) NOT NULL DEFAULT '''' AFTER operations_audit_remark, ADD COLUMN operations_audit_transaction_id VARCHAR(128) NOT NULL DEFAULT '''' AFTER operations_audit_command_id, ADD COLUMN operations_reviewed_at_ms BIGINT NULL AFTER operations_audit_transaction_id, ALGORITHM=INPLACE, LOCK=NONE', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- 兼容早期局部执行过 default=skipped 的开发库;修正默认值是元数据操作,不回写全表。 +SET @ddl := IF( + (SELECT COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'admin_user_withdrawal_applications' AND COLUMN_NAME = 'operations_status') <> 'pending', + 'ALTER TABLE admin_user_withdrawal_applications ALTER COLUMN operations_status SET DEFAULT ''pending'', ALGORITHM=INPLACE, LOCK=NONE', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- 只把迁移前已经终审的历史行标为 skipped,保留 status=pending 的真实待审申请进入运营初审; +-- 按主键范围回填低频 admin 申请,不扫描 wallet/user 流水。大量存量时在低峰执行,并监控行锁和复制延迟。 +UPDATE admin_user_withdrawal_applications application +JOIN schema_migration_checkpoints checkpoint + ON checkpoint.version = '102_user_withdrawal_operations_review.sql' +SET application.operations_status = 'skipped' +WHERE application.id <= checkpoint.checkpoint_value + AND application.status IN ('approved', 'rejected') + AND application.operations_status = 'pending'; + +-- 索引在回填后构建,避免回填期间逐行维护新索引。建索引会扫描该 admin 表并产生额外 IO/磁盘占用, +-- 必须在低峰确认磁盘余量,并监控 metadata lock 和复制延迟。 +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'admin_user_withdrawal_applications' AND INDEX_NAME = 'idx_admin_withdrawal_app_operations_status_time') = 0, + 'ALTER TABLE admin_user_withdrawal_applications ADD KEY idx_admin_withdrawal_app_operations_status_time (app_code, operations_status, created_at_ms, id), ALGORITHM=INPLACE, LOCK=NONE', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SET @now_ms = CAST(UNIX_TIMESTAMP(UTC_TIMESTAMP(3)) * 1000 AS UNSIGNED); + +-- 财务权限保留原 code,避免存量自建角色和 JWT 契约失效;仅收敛后台展示名称并新增独立运营权限。 +INSERT INTO admin_permissions (name, code, kind, description, created_at_ms, updated_at_ms) VALUES + ('用户提现财务审核', 'finance-withdrawal:view', 'menu', '查看已通过运营审核或历史兼容的用户提现申请', @now_ms, @now_ms), + ('用户提现财务审核操作', 'finance-withdrawal:audit', 'button', '财务终审用户提现并扣减或释放冻结余额', @now_ms, @now_ms), + ('用户提现运营审核', 'operations-withdrawal:view', 'menu', '查看需要运营初审的用户提现申请', @now_ms, @now_ms), + ('用户提现运营审核操作', 'operations-withdrawal:audit', 'button', '运营初审用户提现;通过后转交财务,拒绝时释放冻结余额', @now_ms, @now_ms) +ON DUPLICATE KEY UPDATE + name = VALUES(name), + kind = VALUES(kind), + description = VALUES(description), + updated_at_ms = @now_ms; + +-- 固定运营岗位不能继续持有财务终审权限,否则可绕过运营初审直接结算 frozen;只清理两个精确 role code 和两个精确 permission code。 +DELETE role_permission +FROM admin_role_permissions role_permission +JOIN admin_roles role ON role.id = role_permission.role_id +JOIN admin_permissions permission ON permission.id = role_permission.permission_id +WHERE role.code IN ('ops-admin', 'operations-specialist') + AND permission.code IN ('finance-withdrawal:view', 'finance-withdrawal:audit'); + +INSERT IGNORE INTO admin_role_permissions (role_id, permission_id) +SELECT role.id, permission.id +FROM admin_roles role +JOIN admin_permissions permission +WHERE role.code IN ('platform-admin', 'ops-admin', 'operations-specialist') + AND permission.code IN ('operations-withdrawal:view', 'operations-withdrawal:audit'); diff --git a/services/activity-service/internal/app/services.go b/services/activity-service/internal/app/services.go index 176578cd..5fac5b38 100644 --- a/services/activity-service/internal/app/services.go +++ b/services/activity-service/internal/app/services.go @@ -65,7 +65,12 @@ func buildServiceBundle(cfg config.Config, repository *mysqlstorage.Repository, taskSvc := taskservice.New(repository, walletClient) registrationRewardSvc := registrationrewardservice.New(repository, walletClient) sevenDayCheckInSvc := sevendaycheckinservice.New(repository, walletClient) - growthSvc := growthservice.New(repository, walletClient, growthservice.WithNoticeService(messageSvc)) + growthOptions := []growthservice.Option{growthservice.WithNoticeService(messageSvc)} + if userLeaderboardStore != nil { + // 复用游戏等级已接收的 game_spend_coin 事实写榜,避免再建一条会漂移口径的游戏消费链路。 + growthOptions = append(growthOptions, growthservice.WithGameLeaderboard(userLeaderboardStore)) + } + growthSvc := growthservice.New(repository, walletClient, growthOptions...) achievementSvc := achievementservice.New(repository, walletClient) agencyOpeningSvc := agencyopeningservice.New(repository, walletClient, activityclient.NewGRPCAgencyOpeningSource(clients.userConn), roomClient) weeklyStarSvc := weeklystarservice.New(repository, walletClient) diff --git a/services/activity-service/internal/config/config.go b/services/activity-service/internal/config/config.go index 12d8f8ce..975cfc70 100644 --- a/services/activity-service/internal/config/config.go +++ b/services/activity-service/internal/config/config.go @@ -112,9 +112,10 @@ type TaskEventWorkerConfig struct { Enabled bool `yaml:"enabled"` } -// UserLeaderboardWorkerConfig 保存用户送礼榜单 Redis 投影策略。 +// UserLeaderboardWorkerConfig 保存用户榜单 Redis 投影策略。 type UserLeaderboardWorkerConfig struct { - // Enabled 控制是否启动 wallet_outbox 用户榜单消费者;关闭时 gateway 只能读到已有 Redis 聚合。 + // Enabled 控制是否打开榜单 Redis 并启动 wallet_outbox 消费;游戏等级事件也复用该连接写 game 榜。 + // 关闭时 gateway 只能读到已有 Redis 聚合,但等级和任务主链路仍继续处理。 Enabled bool `yaml:"enabled"` // RedisAddr 是 activity 写入用户榜单聚合的 Redis 地址,必须与 gateway 读取地址一致。 RedisAddr string `yaml:"redis_addr"` diff --git a/services/activity-service/internal/service/growth/service.go b/services/activity-service/internal/service/growth/service.go index d122acb7..506cd6e0 100644 --- a/services/activity-service/internal/service/growth/service.go +++ b/services/activity-service/internal/service/growth/service.go @@ -15,6 +15,7 @@ import ( roomeventsv1 "hyapp.local/api/proto/events/room/v1" walletv1 "hyapp.local/api/proto/wallet/v1" "hyapp/pkg/appcode" + "hyapp/pkg/userleaderboard" "hyapp/pkg/xerr" domain "hyapp/services/activity-service/internal/domain/growth" messageservice "hyapp/services/activity-service/internal/service/message" @@ -64,6 +65,12 @@ type WalletClient interface { RevokeResourceGrant(ctx context.Context, req *walletv1.RevokeResourceGrantRequest, opts ...grpc.CallOption) (*walletv1.ResourceGrantResponse, error) } +// GameLeaderboard projects the same committed game-spend fact into the short-period user ranking read model. +// It stays optional so activity deployments that intentionally disable the Redis leaderboard keep level processing intact. +type GameLeaderboard interface { + ApplyGameEvent(ctx context.Context, event userleaderboard.GameEvent) (bool, error) +} + // NoticeService 只调用 message service 的公开 helper;growth 不直接写 inbox 表。 type NoticeService interface { CreateSystemNotice(ctx context.Context, cmd messageservice.NoticeCommand) (messageservice.NoticeResult, error) @@ -75,12 +82,17 @@ func WithNoticeService(notices NoticeService) Option { return func(service *Service) { service.notices = notices } } +func WithGameLeaderboard(leaderboard GameLeaderboard) Option { + return func(service *Service) { service.gameLeaderboard = leaderboard } +} + // Service 承载 App 查询、事件消费、后台配置和等级奖励补偿。 type Service struct { - repository Repository - wallet WalletClient - notices NoticeService - now func() time.Time + repository Repository + wallet WalletClient + notices NoticeService + gameLeaderboard GameLeaderboard + now func() time.Time } func New(repository Repository, wallet WalletClient, options ...Option) *Service { @@ -310,7 +322,25 @@ func (s *Service) ConsumeLevelEvent(ctx context.Context, event domain.ValueEvent if event.OccurredAtMS <= 0 { event.OccurredAtMS = s.now().UnixMilli() } - return s.repository.ConsumeLevelEvent(ctx, event, s.now().UnixMilli()) + result, err := s.repository.ConsumeLevelEvent(ctx, event, s.now().UnixMilli()) + if err != nil { + return domain.EventResult{}, err + } + if s.gameLeaderboard == nil || event.Track != domain.TrackGame || event.MetricType != domain.MetricGameSpendCoin { + return result, nil + } + // MySQL is committed before Redis. Returning a retryable error here makes game-service replay the durable outbox; + // on replay MySQL returns duplicate while Redis event_id dedupe either repairs the missing projection or no-ops safely. + if _, err := s.gameLeaderboard.ApplyGameEvent(ctx, userleaderboard.GameEvent{ + AppCode: appcode.FromContext(ctx), + EventID: event.EventID, + UserID: event.UserID, + CoinSpent: event.ValueDelta, + OccurredAtMS: event.OccurredAtMS, + }); err != nil { + return domain.EventResult{}, fmt.Errorf("project game leaderboard: %w", err) + } + return result, nil } // SetUserLevel 是经理中心的直接等级调整入口。 diff --git a/services/activity-service/internal/service/growth/service_test.go b/services/activity-service/internal/service/growth/service_test.go index 740a5f2e..985c8b91 100644 --- a/services/activity-service/internal/service/growth/service_test.go +++ b/services/activity-service/internal/service/growth/service_test.go @@ -2,6 +2,7 @@ package growth_test import ( "context" + "errors" "fmt" "testing" "time" @@ -11,6 +12,7 @@ import ( activityevents "hyapp.local/api/proto/events/room/v1" walletv1 "hyapp.local/api/proto/wallet/v1" "hyapp/pkg/appcode" + "hyapp/pkg/userleaderboard" domain "hyapp/services/activity-service/internal/domain/growth" growthservice "hyapp/services/activity-service/internal/service/growth" messageservice "hyapp/services/activity-service/internal/service/message" @@ -89,6 +91,42 @@ func TestGrowthLevelEventRewardFlow(t *testing.T) { } } +func TestGameSpendLeaderboardProjectionRetriesAfterRedisFailure(t *testing.T) { + repository := mysqltest.NewRepository(t) + projector := &fakeGameLeaderboard{failuresRemaining: 1} + svc := growthservice.New(repository, &fakeGrowthWallet{}, growthservice.WithGameLeaderboard(projector)) + svc.SetClock(fixedGrowthNow) + ctx := appcode.WithContext(context.Background(), "huwaa") + seedGrowthRules(t, ctx, svc, domain.TrackGame) + event := domain.ValueEvent{ + EventID: "game_level:order_projection_1", + SourceEventID: "order_projection_1", + SourceService: "game-service", + SourceEventType: "GameCoinDebited", + UserID: 20002, + Track: domain.TrackGame, + MetricType: domain.MetricGameSpendCoin, + ValueDelta: 120, + OccurredAtMS: fixedGrowthNow().UnixMilli(), + DimensionsJSON: `{"game_id":"dice"}`, + } + + if _, err := svc.ConsumeLevelEvent(ctx, event); err == nil { + t.Fatal("Redis projection failure must keep the durable game outbox retryable") + } + retry, err := svc.ConsumeLevelEvent(ctx, event) + if err != nil || retry.Status != domain.EventStatusDuplicate { + t.Fatalf("retry should repair Redis after MySQL duplicate: result=%+v err=%v", retry, err) + } + if len(projector.events) != 2 { + t.Fatalf("projection call count = %d, want 2", len(projector.events)) + } + projected := projector.events[1] + if projected.AppCode != "huwaa" || projected.EventID != event.EventID || projected.UserID != event.UserID || projected.CoinSpent != event.ValueDelta || projected.OccurredAtMS != event.OccurredAtMS { + t.Fatalf("projected game event mismatch: %+v", projected) + } +} + func TestTemporaryGrowthLevelOverlayExpiresAndRevokesAllWalletGrants(t *testing.T) { repository := mysqltest.NewRepository(t) wallet := &fakeGrowthWallet{} @@ -987,6 +1025,20 @@ func newGrowthService(t *testing.T) (*growthservice.Service, *fakeGrowthWallet) return svc, wallet } +type fakeGameLeaderboard struct { + events []userleaderboard.GameEvent + failuresRemaining int +} + +func (f *fakeGameLeaderboard) ApplyGameEvent(_ context.Context, event userleaderboard.GameEvent) (bool, error) { + f.events = append(f.events, event) + if f.failuresRemaining > 0 { + f.failuresRemaining-- + return false, errors.New("redis unavailable") + } + return true, nil +} + func seedGrowthRules(t *testing.T, ctx context.Context, svc *growthservice.Service, track string) { t.Helper() if _, created, err := svc.UpsertLevelRule(ctx, domain.RuleCommand{ diff --git a/services/game-service/internal/service/roomrps/service.go b/services/game-service/internal/service/roomrps/service.go index d72ea84a..87adeabd 100644 --- a/services/game-service/internal/service/roomrps/service.go +++ b/services/game-service/internal/service/roomrps/service.go @@ -342,9 +342,10 @@ func (s *Service) CreateChallenge(ctx context.Context, req *gamev1.CreateRoomRPS StakeCoin: stakeCoin, Initiator: &gamev1.RoomRPSPlayer{UserId: req.GetUserId(), Gesture: gesture, BalanceAfter: initiatorBalance, JoinedAtMs: nowMS}, SettlementStatus: SettlementPending, - TimeoutAtMs: now.Add(s.config.ChallengeTimeout).UnixMilli(), - CreatedAtMs: nowMS, - UpdatedAtMs: nowMS, + // timeout_at_ms 是订单创建时冻结的运营配置事实;后台后续改配置只影响新挑战,不改写已有订单截止时间。 + TimeoutAtMs: now.Add(time.Duration(config.GetChallengeTimeoutMs()) * time.Millisecond).UnixMilli(), + CreatedAtMs: nowMS, + UpdatedAtMs: nowMS, } s.challenges[challenge.GetChallengeId()] = challenge cloned := cloneChallenge(challenge) @@ -377,11 +378,19 @@ func (s *Service) AcceptChallenge(ctx context.Context, req *gamev1.AcceptRoomRPS now := s.now() nowMS := now.UnixMilli() if challenge.GetStatus() != StatusPending { - // pending 是唯一可应战状态;matched/revealing/finished/timeout 都已经有明确归属,重复点击只能返回冲突。 + // timeout 和“被其他人接单”都需要稳定业务码;其它终态才保留通用冲突,避免客户端按 message 猜状态。 + expired := challenge.GetStatus() == StatusTimeout + takenByAnother := roomRPSChallengeTakenByAnother(challenge, req.GetUserId()) s.mu.Unlock() + if expired { + return nil, 0, xerr.New(xerr.RoomRPSChallengeExpired, "room rps challenge is timeout") + } + if takenByAnother { + return nil, 0, xerr.New(xerr.RoomRPSChallengeTaken, "room rps challenge was accepted by another user") + } return nil, 0, xerr.New(xerr.Conflict, "room rps challenge is not pending") } - if challenge.GetTimeoutAtMs() > 0 && nowMS > challenge.GetTimeoutAtMs() { + if challenge.GetTimeoutAtMs() > 0 && nowMS >= challenge.GetTimeoutAtMs() { // 读到已超时但还未收敛的 pending 时,先在锁内改成 timeout,避免下一个用户还能应战同一单。 challenge.Status = StatusTimeout challenge.SettlementStatus = SettlementRefunded @@ -396,7 +405,7 @@ func (s *Service) AcceptChallenge(ctx context.Context, req *gamev1.AcceptRoomRPS s.replaceChallengeSnapshot(app, challengeID, refunded) cloned = refunded _ = s.publishChallengeEvent(ctx, eventExpired, cloned) - return nil, 0, xerr.New(xerr.Conflict, "room rps challenge is timeout") + return nil, 0, xerr.New(xerr.RoomRPSChallengeExpired, "room rps challenge is timeout") } if challenge.GetInitiator().GetUserId() == req.GetUserId() { // 发起人不能应战自己的单;这个判断必须在 service 锁内做,不能依赖前端按钮状态。 @@ -423,11 +432,19 @@ func (s *Service) AcceptChallenge(ctx context.Context, req *gamev1.AcceptRoomRPS nowMS = now.UnixMilli() if challenge.GetStatus() != StatusPending { // 钱包扣款期间可能已有其他用户抢先应战;状态机必须以锁内二次校验为准,失败时立即退回刚扣的挑战方本金。 + expired := challenge.GetStatus() == StatusTimeout + takenByAnother := roomRPSChallengeTakenByAnother(challenge, req.GetUserId()) s.mu.Unlock() _, _ = s.applyCoinChange(ctx, req.GetMeta().GetRequestId(), app, challengeID, roomID, req.GetUserId(), stakeCoin, roomRPSOpRefund) + if expired { + return nil, 0, xerr.New(xerr.RoomRPSChallengeExpired, "room rps challenge is timeout") + } + if takenByAnother { + return nil, 0, xerr.New(xerr.RoomRPSChallengeTaken, "room rps challenge was accepted by another user") + } return nil, 0, xerr.New(xerr.Conflict, "room rps challenge is not pending") } - if challenge.GetTimeoutAtMs() > 0 && nowMS > challenge.GetTimeoutAtMs() { + if challenge.GetTimeoutAtMs() > 0 && nowMS >= challenge.GetTimeoutAtMs() { // 二次校验也要收敛超时单,避免扣款耗时跨过 timeout 后仍然匹配成功。 challenge.Status = StatusTimeout challenge.SettlementStatus = SettlementRefunded @@ -443,7 +460,7 @@ func (s *Service) AcceptChallenge(ctx context.Context, req *gamev1.AcceptRoomRPS s.replaceChallengeSnapshot(app, challengeID, refunded) cloned = refunded _ = s.publishChallengeEvent(ctx, eventExpired, cloned) - return nil, 0, xerr.New(xerr.Conflict, "room rps challenge is timeout") + return nil, 0, xerr.New(xerr.RoomRPSChallengeExpired, "room rps challenge is timeout") } if challenge.GetInitiator().GetUserId() == req.GetUserId() { // 二次校验保留同一条权限边界,防止测试或未来接口在第一次检查后篡改挑战归属。 @@ -500,6 +517,12 @@ func (s *Service) AcceptChallenge(ctx context.Context, req *gamev1.AcceptRoomRPS return cloned, nowMS, nil } +// roomRPSChallengeTakenByAnother 只识别“已有其他挑战者”这一个可操作冲突,避免把超时、结算失败或当事人重试误报为被他人接单。 +func roomRPSChallengeTakenByAnother(challenge *gamev1.RoomRPSChallenge, userID int64) bool { + challengerID := challenge.GetChallenger().GetUserId() + return challengerID > 0 && challengerID != userID +} + func (s *Service) GetChallenge(ctx context.Context, app string, challengeID string) (*gamev1.RoomRPSChallenge, int64, error) { if s == nil { return nil, 0, xerr.New(xerr.Unavailable, "room rps service is not configured") diff --git a/services/game-service/internal/service/roomrps/service_test.go b/services/game-service/internal/service/roomrps/service_test.go index 614c8475..3890f975 100644 --- a/services/game-service/internal/service/roomrps/service_test.go +++ b/services/game-service/internal/service/roomrps/service_test.go @@ -358,6 +358,136 @@ func TestAcceptChallengeRecordsChallengerCoinBalance(t *testing.T) { } } +func TestAcceptChallengeReturnsTakenWhenAnotherUserAlreadyAccepted(t *testing.T) { + wallet := newFakeRoomRPSWallet(map[int64]int64{41: 1000, 42: 500, 43: 500}) + svc := New(Config{}, nil, nil, wallet) + svc.now = func() time.Time { return time.UnixMilli(1770000000000) } + + created, _, err := svc.CreateChallenge(context.Background(), &gamev1.CreateRoomRPSChallengeRequest{ + Meta: &gamev1.RequestMeta{AppCode: "lalu", RequestId: "req-create"}, + UserId: 41, + RoomId: "room-1", + GiftId: 10001, + Gesture: "rock", + }) + if err != nil { + t.Fatalf("CreateChallenge() error = %v", err) + } + _, _, err = svc.AcceptChallenge(context.Background(), &gamev1.AcceptRoomRPSChallengeRequest{ + Meta: &gamev1.RequestMeta{AppCode: "lalu", RequestId: "req-first-accept"}, + UserId: 42, + ChallengeId: created.GetChallengeId(), + Gesture: "paper", + }) + if err != nil { + t.Fatalf("first AcceptChallenge() error = %v", err) + } + + _, _, err = svc.AcceptChallenge(context.Background(), &gamev1.AcceptRoomRPSChallengeRequest{ + Meta: &gamev1.RequestMeta{AppCode: "lalu", RequestId: "req-late-accept"}, + UserId: 43, + ChallengeId: created.GetChallengeId(), + Gesture: "scissors", + }) + if !xerr.IsCode(err, xerr.RoomRPSChallengeTaken) { + t.Fatalf("late AcceptChallenge() error = %v, want RoomRPSChallengeTaken", err) + } + if wallet.balances[43] != 500 { + t.Fatalf("late challenger must not be debited: balance=%d", wallet.balances[43]) + } +} + +func TestCreateChallengeFreezesConfiguredTimeoutForEachNewOrder(t *testing.T) { + wallet := newFakeRoomRPSWallet(map[int64]int64{41: 1000, 42: 1000}) + store := newFakeRoomRPSConfigStore() + svc := New(Config{}, nil, nil, wallet, store) + now := time.UnixMilli(1770000000000) + svc.now = func() time.Time { return now } + + updateTimeout := func(timeoutMS int64) { + t.Helper() + _, _, err := svc.UpdateConfig(context.Background(), "lalu", &gamev1.RoomRPSConfig{ + Status: "active", + ChallengeTimeoutMs: timeoutMS, + RevealCountdownMs: 3000, + StakeGifts: defaultGifts(), + }) + if err != nil { + t.Fatalf("UpdateConfig(%d) error = %v", timeoutMS, err) + } + } + create := func(userID int64, requestID string) *gamev1.RoomRPSChallenge { + t.Helper() + challenge, _, err := svc.CreateChallenge(context.Background(), &gamev1.CreateRoomRPSChallengeRequest{ + Meta: &gamev1.RequestMeta{AppCode: "lalu", RequestId: requestID}, + UserId: userID, + RoomId: "room-1", + GiftId: 10001, + Gesture: "rock", + }) + if err != nil { + t.Fatalf("CreateChallenge() error = %v", err) + } + return challenge + } + + updateTimeout(60000) + first := create(41, "req-create-60s") + if got, want := first.GetTimeoutAtMs(), now.UnixMilli()+60000; got != want { + t.Fatalf("first timeout_at_ms = %d, want configured boundary %d", got, want) + } + + updateTimeout(120000) + second := create(42, "req-create-120s") + if got, want := second.GetTimeoutAtMs(), now.UnixMilli()+120000; got != want { + t.Fatalf("second timeout_at_ms = %d, want configured boundary %d", got, want) + } + if got, want := first.GetTimeoutAtMs(), now.UnixMilli()+60000; got != want { + t.Fatalf("existing challenge timeout changed after config update: got %d want %d", got, want) + } +} + +func TestAcceptChallengeReturnsExpiredAtConfiguredBoundary(t *testing.T) { + wallet := newFakeRoomRPSWallet(map[int64]int64{41: 1000, 42: 1000}) + svc := New(Config{ChallengeTimeout: 60 * time.Second}, nil, nil, wallet) + now := time.UnixMilli(1770000000000) + svc.now = func() time.Time { return now } + + created, _, err := svc.CreateChallenge(context.Background(), &gamev1.CreateRoomRPSChallengeRequest{ + Meta: &gamev1.RequestMeta{AppCode: "lalu", RequestId: "req-create-expiring"}, + UserId: 41, + RoomId: "room-1", + GiftId: 10001, + Gesture: "rock", + }) + if err != nil { + t.Fatalf("CreateChallenge() error = %v", err) + } + + // 截止毫秒是排他边界:到达 timeout_at_ms 即失效,不能再多放行一个毫秒。 + now = time.UnixMilli(created.GetTimeoutAtMs()) + accept := func(requestID string) error { + t.Helper() + _, _, acceptErr := svc.AcceptChallenge(context.Background(), &gamev1.AcceptRoomRPSChallengeRequest{ + Meta: &gamev1.RequestMeta{AppCode: "lalu", RequestId: requestID}, + UserId: 42, + ChallengeId: created.GetChallengeId(), + Gesture: "paper", + }) + return acceptErr + } + if err := accept("req-accept-expired"); !xerr.IsCode(err, xerr.RoomRPSChallengeExpired) { + t.Fatalf("AcceptChallenge() error = %v, want RoomRPSChallengeExpired", err) + } + if wallet.balances[41] != 1000 || wallet.balances[42] != 1000 { + t.Fatalf("expired challenge must refund initiator without debiting challenger: balances=%+v", wallet.balances) + } + // 已收敛为 timeout 的旧挑战再次点击时仍返回同一业务码,不能退化回通用 CONFLICT。 + if err := accept("req-accept-expired-again"); !xerr.IsCode(err, xerr.RoomRPSChallengeExpired) { + t.Fatalf("repeated AcceptChallenge() error = %v, want RoomRPSChallengeExpired", err) + } +} + func TestAcceptChallengeDrawRefundsBothPlayers(t *testing.T) { wallet := newFakeRoomRPSWallet(map[int64]int64{41: 1000, 42: 500}) svc := New(Config{}, nil, nil, wallet) diff --git a/services/gateway-service/internal/app/app.go b/services/gateway-service/internal/app/app.go index f008cc47..bda878ea 100644 --- a/services/gateway-service/internal/app/app.go +++ b/services/gateway-service/internal/app/app.go @@ -478,22 +478,16 @@ func configureUserLeaderboard(handler *httptransport.Handler, cfg config.Leaderb } func configureLoginRisk(handler *httptransport.Handler, cfg config.LoginRiskConfig, riskConfig httptransport.LoginRiskConfig) (func() error, error) { - if !riskConfig.Enabled { - handler.SetLoginRisk(riskConfig) - return nil, nil - } redisAddr := strings.TrimSpace(cfg.RedisAddr) if redisAddr == "" { - handler.SetLoginRisk(riskConfig) - return nil, nil + return nil, errors.New("session denylist redis_addr is required") } ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() redisClient, err := httptransport.NewLoginRiskRedisClient(ctx, redisAddr, cfg.RedisPassword, cfg.RedisDB) if err != nil { - // IP 风控缓存按文档 fail-open:Redis 不可用不能阻断 gateway 启动或登录。 - handler.SetLoginRisk(riskConfig) - return nil, nil + // FastGuard 可 fail-open,但 sid denylist 是 access JWT 撤销的唯一入口事实;连接失败必须阻断启动。 + return nil, fmt.Errorf("connect session denylist redis: %w", err) } handler.SetLoginRiskCache(riskConfig, httptransport.NewRedisLoginRiskCache(redisClient, riskConfig)) return redisClient.Close, nil diff --git a/services/gateway-service/internal/app/app_test.go b/services/gateway-service/internal/app/app_test.go index b36e121b..01091e32 100644 --- a/services/gateway-service/internal/app/app_test.go +++ b/services/gateway-service/internal/app/app_test.go @@ -49,3 +49,22 @@ func TestConfigureGiftCapacityLimitDisabledDoesNotRequireRedis(t *testing.T) { t.Fatal("disabled gift capacity limit must not allocate redis client") } } + +func TestConfigureLoginRiskRequiresSessionDenylistRedisEvenWhenRiskDisabled(t *testing.T) { + handler := httptransport.NewHandler(nil) + _, err := configureLoginRisk(handler, config.LoginRiskConfig{Enabled: false}, httptransport.LoginRiskConfig{Enabled: false}) + if err == nil || !strings.Contains(err.Error(), "session denylist redis_addr is required") { + t.Fatalf("mandatory session denylist must reject empty Redis config, err=%v", err) + } +} + +func TestConfigureLoginRiskFailsStartupWhenSessionDenylistRedisUnavailable(t *testing.T) { + handler := httptransport.NewHandler(nil) + _, err := configureLoginRisk(handler, config.LoginRiskConfig{ + Enabled: false, + RedisAddr: "127.0.0.1:1", + }, httptransport.LoginRiskConfig{Enabled: false}) + if err == nil || !strings.Contains(err.Error(), "connect session denylist redis") { + t.Fatalf("unreachable session denylist Redis must fail startup, err=%v", err) + } +} diff --git a/services/gateway-service/internal/auth/jwt.go b/services/gateway-service/internal/auth/jwt.go index a6f08356..bad57977 100644 --- a/services/gateway-service/internal/auth/jwt.go +++ b/services/gateway-service/internal/auth/jwt.go @@ -2,6 +2,7 @@ package auth import ( "context" + "errors" "fmt" "strconv" "strings" @@ -10,6 +11,9 @@ import ( "hyapp/pkg/appcode" ) +// ErrAccessTokenExpired 让 transport 精确区分“可通过 refresh 恢复”的 JWT 过期与签名非法/缺失凭证。 +var ErrAccessTokenExpired = errors.New("access token expired") + type contextKey string const ( @@ -65,6 +69,11 @@ func (v *Verifier) Verify(header string) (Claims, error) { return v.secret, nil }) + if errors.Is(err, jwt.ErrTokenExpired) && !errors.Is(err, jwt.ErrTokenNotValidYet) && !errors.Is(err, jwt.ErrInvalidType) { + // jwt 先验签再校验 claims,因此到这里签名已可信;但 exp 过期若同时伴随未来 nbf/畸形时间字段, + // 仍是非法凭证而非单纯可 refresh 的过期 token,不能向客户端发刷新信号。 + return Claims{}, ErrAccessTokenExpired + } if err != nil || !token.Valid { return Claims{}, fmt.Errorf("invalid token") } diff --git a/services/gateway-service/internal/auth/jwt_test.go b/services/gateway-service/internal/auth/jwt_test.go index 1875c56c..d665374a 100644 --- a/services/gateway-service/internal/auth/jwt_test.go +++ b/services/gateway-service/internal/auth/jwt_test.go @@ -2,8 +2,10 @@ package auth import ( "context" + "errors" "strconv" "testing" + "time" jwt "github.com/golang-jwt/jwt/v5" ) @@ -56,3 +58,35 @@ func TestVerifierKeepsLegacyTokenWithoutDeviceIDCompatible(t *testing.T) { t.Fatalf("legacy token device_id=%q, want empty instead of sid fallback", got) } } + +func TestVerifierDistinguishesExpiredAccessTokenFromInvalidCredentials(t *testing.T) { + t.Parallel() + expired := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "user_id": "42", + "sid": "sess-expired", + "exp": time.Now().Add(-time.Minute).Unix(), + }) + signed, err := expired.SignedString([]byte("secret")) + if err != nil { + t.Fatalf("sign expired token failed: %v", err) + } + if _, err := NewVerifier("secret").Verify("Bearer " + signed); !errors.Is(err, ErrAccessTokenExpired) { + t.Fatalf("expired token must return ErrAccessTokenExpired, got %v", err) + } + if _, err := NewVerifier("different-secret").Verify("Bearer " + signed); errors.Is(err, ErrAccessTokenExpired) || err == nil { + t.Fatalf("invalid signature must remain generic unauthorized, got %v", err) + } + contradictory := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "user_id": "42", + "sid": "sess-invalid-window", + "exp": time.Now().Add(-time.Minute).Unix(), + "nbf": time.Now().Add(time.Hour).Unix(), + }) + contradictorySigned, err := contradictory.SignedString([]byte("secret")) + if err != nil { + t.Fatalf("sign contradictory token failed: %v", err) + } + if _, err := NewVerifier("secret").Verify("Bearer " + contradictorySigned); errors.Is(err, ErrAccessTokenExpired) || err == nil { + t.Fatalf("expired token with another invalid time claim must remain generic unauthorized, got %v", err) + } +} diff --git a/services/gateway-service/internal/client/statistics_client.go b/services/gateway-service/internal/client/statistics_client.go index ae037763..fb925844 100644 --- a/services/gateway-service/internal/client/statistics_client.go +++ b/services/gateway-service/internal/client/statistics_client.go @@ -12,27 +12,29 @@ import ( ) type AppTrackingEvent struct { - AppCode string `json:"app_code"` - EventID string `json:"event_id"` - EventName string `json:"event_name"` - EventType string `json:"event_type"` - Screen string `json:"screen"` - TargetType string `json:"target_type"` - TargetID string `json:"target_id"` - UserID int64 `json:"user_id"` - DeviceID string `json:"device_id"` - SessionID string `json:"session_id"` - Platform string `json:"platform"` - AppVersion string `json:"app_version"` - Language string `json:"language"` - Timezone string `json:"timezone"` - CountryID int64 `json:"country_id"` - RegionID int64 `json:"region_id"` - DurationMS int64 `json:"duration_ms"` - Success bool `json:"success"` - ErrorCode string `json:"error_code"` - Properties json.RawMessage `json:"properties,omitempty"` - OccurredAtMS int64 `json:"occurred_at_ms"` + AppCode string `json:"app_code"` + EventID string `json:"event_id"` + EventName string `json:"event_name"` + EventType string `json:"event_type"` + Screen string `json:"screen"` + TargetType string `json:"target_type"` + TargetID string `json:"target_id"` + UserID int64 `json:"user_id"` + DeviceID string `json:"device_id"` + SessionID string `json:"session_id"` + ClientSessionID string `json:"client_session_id"` + AuthSessionID string `json:"auth_session_id"` + Platform string `json:"platform"` + AppVersion string `json:"app_version"` + Language string `json:"language"` + Timezone string `json:"timezone"` + CountryID int64 `json:"country_id"` + RegionID int64 `json:"region_id"` + DurationMS int64 `json:"duration_ms"` + Success bool `json:"success"` + ErrorCode string `json:"error_code"` + Properties json.RawMessage `json:"properties,omitempty"` + OccurredAtMS int64 `json:"occurred_at_ms"` } type AppTrackingReportResult struct { diff --git a/services/gateway-service/internal/client/user_client.go b/services/gateway-service/internal/client/user_client.go index 8b470c9c..bc8229c6 100644 --- a/services/gateway-service/internal/client/user_client.go +++ b/services/gateway-service/internal/client/user_client.go @@ -86,6 +86,12 @@ type UserCPClient interface { CancelBreakCPRelationship(ctx context.Context, req *userv1.CancelBreakCPRelationshipRequest) (*userv1.CancelBreakCPRelationshipResponse, error) } +// UserCPFormationGiftFeedClient 是成立礼物 feed 的独立只读能力。 +// 它不并入历史 UserCPClient,避免只覆盖关系命令的调用方被迫依赖新的展示接口。 +type UserCPFormationGiftFeedClient interface { + ListCPFormationGiftFeed(ctx context.Context, req *userv1.ListCPFormationGiftFeedRequest) (*userv1.ListCPFormationGiftFeedResponse, error) +} + // UserDeviceClient 抽象 gateway 对 user-service 设备 push token 的依赖。 type UserDeviceClient interface { BindPushToken(ctx context.Context, req *userv1.BindPushTokenRequest) (*userv1.BindPushTokenResponse, error) @@ -171,6 +177,8 @@ type grpcUserCPClient struct { client userv1.UserCPServiceClient } +var _ UserCPFormationGiftFeedClient = (*grpcUserCPClient)(nil) + type grpcUserDeviceClient struct { client userv1.UserDeviceServiceClient } @@ -483,6 +491,10 @@ func (c *grpcUserCPClient) ListCPIntimacyLeaderboard(ctx context.Context, req *u return c.client.ListCPIntimacyLeaderboard(ctx, req) } +func (c *grpcUserCPClient) ListCPFormationGiftFeed(ctx context.Context, req *userv1.ListCPFormationGiftFeedRequest) (*userv1.ListCPFormationGiftFeedResponse, error) { + return c.client.ListCPFormationGiftFeed(ctx, req) +} + func (c *grpcUserCPClient) PrepareBreakCPRelationship(ctx context.Context, req *userv1.PrepareBreakCPRelationshipRequest) (*userv1.PrepareBreakCPRelationshipResponse, error) { return c.client.PrepareBreakCPRelationship(ctx, req) } diff --git a/services/gateway-service/internal/config/config.go b/services/gateway-service/internal/config/config.go index a83b5c33..89c950be 100644 --- a/services/gateway-service/internal/config/config.go +++ b/services/gateway-service/internal/config/config.go @@ -578,7 +578,8 @@ func (cfg *Config) Normalize() error { } cfg.LoginRisk.RedisAddr = strings.TrimSpace(cfg.LoginRisk.RedisAddr) cfg.LoginRisk.KeyPrefix = strings.TrimSpace(cfg.LoginRisk.KeyPrefix) - if cfg.LoginRisk.Enabled && cfg.LoginRisk.RedisAddr == "" { + // 地区风控可关闭,但同一 Redis 还承载 mandatory session denylist;始终继承 auth rate-limit 连接。 + if cfg.LoginRisk.RedisAddr == "" { cfg.LoginRisk.RedisAddr = strings.TrimSpace(cfg.AuthRateLimit.RedisAddr) cfg.LoginRisk.RedisPassword = cfg.AuthRateLimit.RedisPassword cfg.LoginRisk.RedisDB = cfg.AuthRateLimit.RedisDB diff --git a/services/gateway-service/internal/config/config_test.go b/services/gateway-service/internal/config/config_test.go index ec193820..0bf40001 100644 --- a/services/gateway-service/internal/config/config_test.go +++ b/services/gateway-service/internal/config/config_test.go @@ -152,6 +152,23 @@ func TestLoadLegacyYAMLWithoutGiftSectionReusesAuthRedis(t *testing.T) { } } +func TestNormalizeLoginRiskDisabledStillInheritsMandatorySessionDenylistRedis(t *testing.T) { + cfg := Default() + cfg.AuthRateLimit.RedisAddr = "shared-redis.internal:6379" + cfg.AuthRateLimit.RedisPassword = "shared-secret" + cfg.AuthRateLimit.RedisDB = 4 + cfg.LoginRisk.Enabled = false + cfg.LoginRisk.RedisAddr = "" + cfg.LoginRisk.RedisPassword = "" + cfg.LoginRisk.RedisDB = 0 + if err := cfg.Normalize(); err != nil { + t.Fatalf("normalize login-risk disabled config failed: %v", err) + } + if cfg.LoginRisk.RedisAddr != "shared-redis.internal:6379" || cfg.LoginRisk.RedisPassword != "shared-secret" || cfg.LoginRisk.RedisDB != 4 { + t.Fatalf("disabled FastGuard must still inherit mandatory session denylist Redis: %+v", cfg.LoginRisk) + } +} + func TestNormalizeRejectsGiftLeaseWithoutRequestSafetyMargin(t *testing.T) { cfg := Default() cfg.GiftCapacityLimit.RequestTimeout = 8 * time.Second diff --git a/services/gateway-service/internal/financewithdrawal/dingtalk_notifier.go b/services/gateway-service/internal/financewithdrawal/dingtalk_notifier.go index 1e282aec..bfbcac9b 100644 --- a/services/gateway-service/internal/financewithdrawal/dingtalk_notifier.go +++ b/services/gateway-service/internal/financewithdrawal/dingtalk_notifier.go @@ -26,14 +26,14 @@ func (n *dingTalkNotifier) NotifyApplicationCreated(ctx context.Context, applica return nil } return n.client.SendMarkdown(ctx, dingtalkrobot.MarkdownMessage{ - Title: "用户提现申请待审核", + Title: "用户提现运营审核待处理", Text: withdrawalApplicationCreatedMarkdown(application), }) } func withdrawalApplicationCreatedMarkdown(application Application) string { return strings.Join([]string{ - "### 用户提现申请待审核", + "### 用户提现运营审核待处理", "", fmt.Sprintf("- 申请ID:%d", application.ID), fmt.Sprintf("- APP:%s", markdownValue(application.AppCode)), @@ -44,7 +44,7 @@ func withdrawalApplicationCreatedMarkdown(application Application) string { fmt.Sprintf("- 提现地址:%s", markdownValue(application.WithdrawAddress)), fmt.Sprintf("- 冻结交易:%s", markdownValue(application.FreezeTransactionID)), fmt.Sprintf("- 申请时间:%s", markdownValue(formatNotifyMillis(application.CreatedAtMS))), - "- 后台地址:https://admin-acc.global-interaction.com/finance/", + "- 后台地址:https://admin-acc.global-interaction.com/finance/?view=withdrawalOperations", }, "\n") } diff --git a/services/gateway-service/internal/financewithdrawal/dingtalk_notifier_test.go b/services/gateway-service/internal/financewithdrawal/dingtalk_notifier_test.go index 6b90eea0..728c537f 100644 --- a/services/gateway-service/internal/financewithdrawal/dingtalk_notifier_test.go +++ b/services/gateway-service/internal/financewithdrawal/dingtalk_notifier_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func TestWithdrawalApplicationCreatedMarkdownKeepsFinanceReviewDetails(t *testing.T) { +func TestWithdrawalApplicationCreatedMarkdownRoutesToOperationsReview(t *testing.T) { message := withdrawalApplicationCreatedMarkdown(Application{ ID: 77, AppCode: "lalu", @@ -19,14 +19,14 @@ func TestWithdrawalApplicationCreatedMarkdownKeepsFinanceReviewDetails(t *testin }) for _, expected := range []string{ - "用户提现申请待审核", + "用户提现运营审核待处理", "申请ID:77", "APP:lalu", "用户ID:42", "提现金额:$ 50.00", "提现方式:usdt_trc20", "冻结交易:freeze-tx-1", - "https://admin-acc.global-interaction.com/finance/", + "https://admin-acc.global-interaction.com/finance/?view=withdrawalOperations", } { if !strings.Contains(message, expected) { t.Fatalf("withdrawal DingTalk message missing %q: %s", expected, message) diff --git a/services/gateway-service/internal/financewithdrawal/writer.go b/services/gateway-service/internal/financewithdrawal/writer.go index be439750..117bb5b8 100644 --- a/services/gateway-service/internal/financewithdrawal/writer.go +++ b/services/gateway-service/internal/financewithdrawal/writer.go @@ -11,13 +11,15 @@ import ( ) const ( - // StatusPending 与后台 finance 用户提现申请列表的待审核状态保持一致;H5 只创建申请,不在入口层审批。 + // StatusPending 表示申请尚未形成最终财务结论;运营通过后总体状态仍保持 pending。 StatusPending = "pending" + // OperationsStatusPending 保证所有新申请先进入运营初审;102 迁移只把执行前已经终审的历史行标记为 skipped。 + OperationsStatusPending = "pending" // MethodUSDTTRC20 是当前 H5 提现页唯一收款方式,后台列表按该字段展示提现方式。 MethodUSDTTRC20 = "usdt_trc20" ) -// CreateApplicationCommand 是 H5 提交到后台 finance 的提现申请事实。 +// CreateApplicationCommand 是 H5 提交到后台审核链的提现申请事实。 // gateway 在调用前已经完成身份、余额和收款地址校验,这里只保护表字段的持久化边界。 type CreateApplicationCommand struct { AppCode string @@ -37,7 +39,7 @@ type CreateApplicationCommand struct { CreatedAtMS int64 } -// Application 是写入后台申请表后的最小返回值;H5 只需要知道申请已进入财务审核队列。 +// Application 是写入后台申请表后的最小返回值;H5 可以根据总体状态与运营状态区分终态和当前审核阶段。 type Application struct { ID int64 AppCode string @@ -54,17 +56,18 @@ type Application struct { WithdrawAddress string FreezeCommandID string FreezeTransactionID string + OperationsStatus string Status string CreatedAtMS int64 UpdatedAtMS int64 } -// Writer 把 gateway 与后台 finance 存储解耦,测试可以用内存 fake 验证 H5 编排,不 import admin internal 包。 +// Writer 把 gateway 与后台提现审核存储解耦,测试可以用内存 fake 验证 H5 编排,不 import admin internal 包。 type Writer interface { CreateApplication(ctx context.Context, command CreateApplicationCommand) (Application, error) } -// Notifier 负责把用户提现申请通知到财务协作工具;通知失败不能回滚已冻结和已落库的申请。 +// Notifier 负责把新申请通知到运营审核协作工具;通知失败不能回滚已冻结和已落库的申请。 type Notifier interface { NotifyApplicationCreated(ctx context.Context, application Application) error } @@ -96,7 +99,7 @@ func (w *MySQLWriter) Close() error { return w.db.Close() } -// CreateApplication 将用户提现请求落成后台 finance 的待审核申请。 +// CreateApplication 将用户提现请求落成运营待审申请,总体状态在财务终审前一直保持 pending。 // withdraw_amount 使用 decimal 字符串写入,避免 gateway 在 float 和 decimal 之间来回转换造成金额精度漂移。 func (w *MySQLWriter) CreateApplication(ctx context.Context, command CreateApplicationCommand) (Application, error) { if w == nil || w.db == nil { @@ -118,9 +121,9 @@ func (w *MySQLWriter) CreateApplication(ctx context.Context, command CreateAppli INSERT INTO admin_user_withdrawal_applications (app_code, user_id, salary_asset_type, withdraw_amount, withdraw_amount_minor, point_fee_amount, point_net_amount, points_per_usd, point_fee_bps, point_policy_instance_code, - withdraw_method, withdraw_address, freeze_command_id, freeze_transaction_id, status, created_at_ms, updated_at_ms) + withdraw_method, withdraw_address, freeze_command_id, freeze_transaction_id, status, operations_status, created_at_ms, updated_at_ms) VALUES - (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, command.AppCode, formatUserID(command.UserID), command.SalaryAssetType, @@ -136,6 +139,7 @@ VALUES command.FreezeCommandID, command.FreezeTransactionID, StatusPending, + OperationsStatusPending, command.CreatedAtMS, command.CreatedAtMS, ) @@ -170,6 +174,7 @@ VALUES WithdrawAddress: command.WithdrawAddress, FreezeCommandID: command.FreezeCommandID, FreezeTransactionID: command.FreezeTransactionID, + OperationsStatus: OperationsStatusPending, Status: StatusPending, CreatedAtMS: command.CreatedAtMS, UpdatedAtMS: command.CreatedAtMS, @@ -180,8 +185,8 @@ func (w *MySQLWriter) getApplicationByFreezeCommand(ctx context.Context, appCode row := w.db.QueryRowContext(ctx, ` SELECT id, app_code, user_id, salary_asset_type, withdraw_amount, withdraw_amount_minor, point_fee_amount, point_net_amount, points_per_usd, point_fee_bps, point_policy_instance_code, - withdraw_method, withdraw_address, freeze_command_id, freeze_transaction_id, - status, created_at_ms, updated_at_ms + withdraw_method, withdraw_address, freeze_command_id, freeze_transaction_id, + status, operations_status, created_at_ms, updated_at_ms FROM admin_user_withdrawal_applications WHERE app_code = ? AND freeze_command_id = ? LIMIT 1`, appCode, freezeCommandID) @@ -204,6 +209,7 @@ LIMIT 1`, appCode, freezeCommandID) &item.FreezeCommandID, &item.FreezeTransactionID, &item.Status, + &item.OperationsStatus, &item.CreatedAtMS, &item.UpdatedAtMS, ); err != nil { diff --git a/services/gateway-service/internal/financewithdrawal/writer_test.go b/services/gateway-service/internal/financewithdrawal/writer_test.go index eaf05ce7..a5af0839 100644 --- a/services/gateway-service/internal/financewithdrawal/writer_test.go +++ b/services/gateway-service/internal/financewithdrawal/writer_test.go @@ -49,6 +49,7 @@ func TestCreateApplicationReturnsExistingByAppAndFreezeCommand(t *testing.T) { "cmd-point-freeze", "tx-freeze", StatusPending, + "skipped", int64(1700000000000), int64(1700000000000), )) @@ -73,7 +74,7 @@ func TestCreateApplicationReturnsExistingByAppAndFreezeCommand(t *testing.T) { if err != nil { t.Fatalf("CreateApplication existing lookup failed: %v", err) } - if got.ID != 77 || got.AppCode != "huwaa" || got.UserID != 42001 || got.FreezeTransactionID != "tx-freeze" { + if got.ID != 77 || got.AppCode != "huwaa" || got.UserID != 42001 || got.FreezeTransactionID != "tx-freeze" || got.OperationsStatus != "skipped" { t.Fatalf("existing withdrawal application mismatch: %+v", got) } if err := mock.ExpectationsWereMet(); err != nil { @@ -106,6 +107,7 @@ func TestCreateApplicationInsertsAfterAppScopedMiss(t *testing.T) { "cmd-point-freeze", "tx-freeze", StatusPending, + OperationsStatusPending, int64(1700000000000), int64(1700000000000), ). @@ -130,7 +132,7 @@ func TestCreateApplicationInsertsAfterAppScopedMiss(t *testing.T) { if err != nil { t.Fatalf("CreateApplication insert failed: %v", err) } - if got.ID != 88 || got.AppCode != "huwaa" || got.SalaryAssetType != "POINT" || got.WithdrawMethod != MethodUSDTTRC20 { + if got.ID != 88 || got.AppCode != "huwaa" || got.SalaryAssetType != "POINT" || got.WithdrawMethod != MethodUSDTTRC20 || got.Status != StatusPending || got.OperationsStatus != OperationsStatusPending { t.Fatalf("inserted withdrawal application mismatch: %+v", got) } if err := mock.ExpectationsWereMet(); err != nil { @@ -156,6 +158,7 @@ func withdrawalApplicationRows() *sqlmock.Rows { "freeze_command_id", "freeze_transaction_id", "status", + "operations_status", "created_at_ms", "updated_at_ms", }) 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 3c81d6b4..d41cb360 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 @@ -20,6 +20,7 @@ import ( const ( leaderboardTypeSent = userleaderboard.BoardSent leaderboardTypeReceived = userleaderboard.BoardReceived + leaderboardTypeGame = userleaderboard.BoardGame leaderboardTypeRoom = "room" leaderboardPeriodToday = userleaderboard.PeriodToday 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 51f9eac2..39fffff5 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 @@ -45,6 +45,9 @@ func TestNormalizeUserLeaderboardTypeAndPeriod(t *testing.T) { if normalizeUserLeaderboardType("rooms") != leaderboardTypeRoom { t.Fatal("rooms should normalize to room") } + if normalizeUserLeaderboardType("gaming") != leaderboardTypeGame { + t.Fatal("gaming should normalize to game") + } if normalizeUserLeaderboardPeriod("monthly") != leaderboardPeriodMonth { t.Fatal("monthly should normalize to month") } @@ -171,6 +174,58 @@ func TestListUserLeaderboardsReadsRedisStore(t *testing.T) { } } +func TestListUserLeaderboardsAcceptsGameBoard(t *testing.T) { + store := &fakeUserLeaderboardStore{ + page: userleaderboard.Page{ + Items: []userleaderboard.Entry{{ + Rank: 1, + UserID: "20002", + GiftValue: 1200, + TransactionCount: 4, + LastGiftAtMS: 1784095200000, + }}, + Total: 1, + BoardType: leaderboardTypeGame, + Period: leaderboardPeriodToday, + StartAtMS: 1784073600000, + EndAtMS: 1784095200000, + ServerTimeMS: 1784095200000, + }, + rank: userleaderboard.Entry{ + Rank: 8, + UserID: "10001", + GiftValue: 180, + TransactionCount: 2, + LastGiftAtMS: 1784095000000, + }, + rankFound: true, + } + handler := &Handler{userLeaderboard: store} + request := httptest.NewRequest(http.MethodGet, "/api/v1/activities/user-leaderboards?board_type=gaming&period=today&page=1&page_size=20", nil) + ctx := appcode.WithContext(request.Context(), "huwaa") + ctx = auth.WithUserID(ctx, 10001) + recorder := httptest.NewRecorder() + + handler.listUserLeaderboards(recorder, request.WithContext(ctx)) + + if recorder.Code != http.StatusOK { + t.Fatalf("status = %d body=%s", recorder.Code, recorder.Body.String()) + } + if store.listCalls != 1 || store.rankCalls != 1 || store.listQuery.AppCode != "huwaa" || store.listQuery.BoardType != leaderboardTypeGame || store.rankQuery.BoardType != leaderboardTypeGame { + t.Fatalf("game query should use its own Redis bucket: list=%+v rank=%+v", store.listQuery, store.rankQuery) + } + var envelope struct { + Code string `json:"code"` + Data userLeaderboardResponse `json:"data"` + } + if err := json.Unmarshal(recorder.Body.Bytes(), &envelope); err != nil { + t.Fatalf("decode response failed: %v", err) + } + if envelope.Code != "OK" || envelope.Data.BoardType != leaderboardTypeGame || len(envelope.Data.Items) != 1 || envelope.Data.Items[0].GiftValue != 1200 || envelope.Data.MyRank == nil || envelope.Data.MyRank.Rank != 8 { + t.Fatalf("game leaderboard response mismatch: %+v", envelope.Data) + } +} + type fakeUserLeaderboardStore struct { listCalls int rankCalls int diff --git a/services/gateway-service/internal/transport/http/appapi/app_event_handler.go b/services/gateway-service/internal/transport/http/appapi/app_event_handler.go index b4e9b65a..41b4ccc1 100644 --- a/services/gateway-service/internal/transport/http/appapi/app_event_handler.go +++ b/services/gateway-service/internal/transport/http/appapi/app_event_handler.go @@ -19,23 +19,24 @@ type appEventsRequest struct { } type appEventRequest struct { - EventID string `json:"event_id"` - EventName string `json:"event_name"` - EventType string `json:"event_type"` - Screen string `json:"screen"` - TargetType string `json:"target_type"` - TargetID string `json:"target_id"` - DeviceID string `json:"device_id"` - SessionID string `json:"session_id"` - Platform string `json:"platform"` - AppVersion string `json:"app_version"` - Language string `json:"language"` - Timezone string `json:"timezone"` - DurationMS int64 `json:"duration_ms"` - Success bool `json:"success"` - ErrorCode string `json:"error_code"` - Properties json.RawMessage `json:"properties"` - OccurredAtMS int64 `json:"occurred_at_ms"` + EventID string `json:"event_id"` + EventName string `json:"event_name"` + EventType string `json:"event_type"` + Screen string `json:"screen"` + TargetType string `json:"target_type"` + TargetID string `json:"target_id"` + DeviceID string `json:"device_id"` + SessionID string `json:"session_id"` + ClientSessionID string `json:"client_session_id"` + Platform string `json:"platform"` + AppVersion string `json:"app_version"` + Language string `json:"language"` + Timezone string `json:"timezone"` + DurationMS int64 `json:"duration_ms"` + Success bool `json:"success"` + ErrorCode string `json:"error_code"` + Properties json.RawMessage `json:"properties"` + OccurredAtMS int64 `json:"occurred_at_ms"` } func (h *Handler) reportAppEvents(writer http.ResponseWriter, request *http.Request) { @@ -147,25 +148,27 @@ func appTrackingEventFromRequest(item appEventRequest, defaults appTrackingEvent occurredAtMS = defaults.receivedAtMS } event := client.AppTrackingEvent{ - AppCode: defaults.appCode, - EventID: item.EventID, - EventName: item.EventName, - EventType: item.EventType, - Screen: item.Screen, - TargetType: item.TargetType, - TargetID: item.TargetID, - UserID: defaults.userID, - DeviceID: deviceID, - SessionID: firstTrimmed(defaults.sessionID, item.SessionID), - Platform: strings.ToLower(firstTrimmed(item.Platform, defaults.platform)), - AppVersion: firstTrimmed(item.AppVersion, defaults.appVersion), - Language: firstTrimmed(item.Language, defaults.language), - Timezone: firstTrimmed(item.Timezone, defaults.timezone), - DurationMS: item.DurationMS, - Success: item.Success, - ErrorCode: item.ErrorCode, - Properties: properties, - OccurredAtMS: occurredAtMS, + AppCode: defaults.appCode, + EventID: item.EventID, + EventName: item.EventName, + EventType: item.EventType, + Screen: item.Screen, + TargetType: item.TargetType, + TargetID: item.TargetID, + UserID: defaults.userID, + DeviceID: deviceID, + SessionID: firstTrimmed(defaults.sessionID, item.SessionID), + ClientSessionID: item.ClientSessionID, + AuthSessionID: defaults.sessionID, + Platform: strings.ToLower(firstTrimmed(item.Platform, defaults.platform)), + AppVersion: firstTrimmed(item.AppVersion, defaults.appVersion), + Language: firstTrimmed(item.Language, defaults.language), + Timezone: firstTrimmed(item.Timezone, defaults.timezone), + DurationMS: item.DurationMS, + Success: item.Success, + ErrorCode: item.ErrorCode, + Properties: properties, + OccurredAtMS: occurredAtMS, } if !normalizeAppTrackingEventText(&event) || event.EventID == "" || event.EventName == "" { return client.AppTrackingEvent{}, false @@ -201,6 +204,8 @@ func normalizeAppTrackingEventText(event *client.AppTrackingEvent) bool { {value: &event.TargetID, maxBytes: apptracking.MaxTargetIDBytes}, {value: &event.DeviceID, maxBytes: apptracking.MaxDeviceIDBytes}, {value: &event.SessionID, maxBytes: apptracking.MaxSessionIDBytes}, + {value: &event.ClientSessionID, maxBytes: apptracking.MaxSessionIDBytes}, + {value: &event.AuthSessionID, maxBytes: apptracking.MaxSessionIDBytes}, {value: &event.Platform, maxBytes: apptracking.MaxPlatformBytes}, {value: &event.AppVersion, maxBytes: apptracking.MaxAppVersionBytes}, {value: &event.Language, maxBytes: apptracking.MaxLanguageBytes}, diff --git a/services/gateway-service/internal/transport/http/auth_handler.go b/services/gateway-service/internal/transport/http/auth_handler.go index c059c656..3d3d14f1 100644 --- a/services/gateway-service/internal/transport/http/auth_handler.go +++ b/services/gateway-service/internal/transport/http/auth_handler.go @@ -438,10 +438,11 @@ func (h *Handler) setPassword(writer http.ResponseWriter, request *http.Request) // refreshToken 处理 refresh token 轮换。 func (h *Handler) refreshToken(writer http.ResponseWriter, request *http.Request) { var body struct { - RefreshToken string `json:"refresh_token"` - DeviceID string `json:"device_id"` - AppVersion string `json:"app_version"` - BuildNumber string `json:"build_number"` + RefreshToken string `json:"refresh_token"` + RefreshRequestID string `json:"refresh_request_id"` + DeviceID string `json:"device_id"` + AppVersion string `json:"app_version"` + BuildNumber string `json:"build_number"` } if !decode(writer, request, &body) { return @@ -459,8 +460,9 @@ func (h *Handler) refreshToken(writer http.ResponseWriter, request *http.Request resp, err := h.userClient.RefreshToken(request.Context(), &userv1.RefreshTokenRequest{ // refresh 是登录态自动恢复的一部分,必须携带当前安装包版本;否则升级后画像会一直停留在旧显式登录版本。 - Meta: authRequestMetaWithLoginContext(request, body.DeviceID, "", "", "", body.AppVersion, body.BuildNumber), - RefreshToken: body.RefreshToken, + Meta: authRequestMetaWithLoginContext(request, body.DeviceID, "", "", "", body.AppVersion, body.BuildNumber), + RefreshToken: body.RefreshToken, + RefreshRequestId: body.RefreshRequestID, }) if err != nil { httpkit.WriteRPCError(writer, request, err) diff --git a/services/gateway-service/internal/transport/http/handler.go b/services/gateway-service/internal/transport/http/handler.go index 4e512083..4ac7874d 100644 --- a/services/gateway-service/internal/transport/http/handler.go +++ b/services/gateway-service/internal/transport/http/handler.go @@ -367,7 +367,7 @@ func (h *Handler) SetStatisticsClient(statisticsClient client.StatisticsClient) h.statisticsClient = statisticsClient } -// SetUserLeaderboardStore 注入 App 用户送礼榜 Redis 读模型;gateway 只读聚合结果。 +// SetUserLeaderboardStore 注入 App 用户榜 Redis 读模型;gateway 只读 activity-service 的聚合结果。 func (h *Handler) SetUserLeaderboardStore(store *userleaderboard.Store) { h.userLeaderboard = store } diff --git a/services/gateway-service/internal/transport/http/httpkit/response.go b/services/gateway-service/internal/transport/http/httpkit/response.go index 9e6bb37f..1ccc18d0 100644 --- a/services/gateway-service/internal/transport/http/httpkit/response.go +++ b/services/gateway-service/internal/transport/http/httpkit/response.go @@ -26,17 +26,18 @@ import ( type requestIDContextKey struct{} const ( - CodeOK = "OK" - CodeInvalidJSON = "INVALID_JSON" - CodeInvalidArgument = "INVALID_ARGUMENT" - CodeUnauthorized = "UNAUTHORIZED" - CodePermissionDenied = "PERMISSION_DENIED" - CodeProfileRequired = "PROFILE_REQUIRED" - CodeAuthLoginBlocked = "AUTH_LOGIN_BLOCKED" - CodeNotFound = "NOT_FOUND" - CodeRateLimited = "RATE_LIMITED" - CodeUpstreamError = "UPSTREAM_ERROR" - CodeInternalError = "INTERNAL_ERROR" + CodeOK = "OK" + CodeInvalidJSON = "INVALID_JSON" + CodeInvalidArgument = "INVALID_ARGUMENT" + CodeUnauthorized = "UNAUTHORIZED" + CodeAccessTokenExpired = "ACCESS_TOKEN_EXPIRED" + CodePermissionDenied = "PERMISSION_DENIED" + CodeProfileRequired = "PROFILE_REQUIRED" + CodeAuthLoginBlocked = "AUTH_LOGIN_BLOCKED" + CodeNotFound = "NOT_FOUND" + CodeRateLimited = "RATE_LIMITED" + CodeUpstreamError = "UPSTREAM_ERROR" + CodeInternalError = "INTERNAL_ERROR" ) // ResponseEnvelope 是 gateway 暴露给客户端的稳定 JSON 外壳。 diff --git a/services/gateway-service/internal/transport/http/httproutes/router.go b/services/gateway-service/internal/transport/http/httproutes/router.go index 12913cf4..c77c0f71 100644 --- a/services/gateway-service/internal/transport/http/httproutes/router.go +++ b/services/gateway-service/internal/transport/http/httproutes/router.go @@ -129,6 +129,7 @@ type UserHandlers struct { RejectCPApplication http.HandlerFunc ListCPRelationships http.HandlerFunc ListCPIntimacyLeaderboard http.HandlerFunc + ListCPFormationGiftFeed http.HandlerFunc BreakCPRelationship http.HandlerFunc GetMyProfile http.HandlerFunc GetUserProfile http.HandlerFunc @@ -522,6 +523,7 @@ func (r routes) registerUserRoutes() { r.profile("/cp/applications/{application_id}/reject", http.MethodPost, h.RejectCPApplication) r.profile("/cp/relationships", http.MethodGet, h.ListCPRelationships) r.profile("/cp/intimacy-leaderboard", http.MethodGet, h.ListCPIntimacyLeaderboard) + r.profile("/cp/formation-gift-feed", http.MethodGet, h.ListCPFormationGiftFeed) r.profile("/cp/relationships/{relationship_id}/break", http.MethodPost, h.BreakCPRelationship) r.profile("/appearance", http.MethodGet, h.GetMyAppearance) r.profile("/users/me/appearance", http.MethodGet, h.GetMyAppearance) diff --git a/services/gateway-service/internal/transport/http/middleware.go b/services/gateway-service/internal/transport/http/middleware.go index 52e5f669..0af19521 100644 --- a/services/gateway-service/internal/transport/http/middleware.go +++ b/services/gateway-service/internal/transport/http/middleware.go @@ -2,7 +2,7 @@ package http import ( "context" - "hyapp/services/gateway-service/internal/transport/http/httpkit" + "errors" "log/slog" "net/http" "strings" @@ -13,6 +13,7 @@ import ( "hyapp/pkg/logx" "hyapp/pkg/xerr" "hyapp/services/gateway-service/internal/auth" + "hyapp/services/gateway-service/internal/transport/http/httpkit" ) // apiHandler 包装需要 app 解析和 access token 的业务 API。 @@ -42,6 +43,11 @@ func (h *Handler) withAuth(jwtVerifier *auth.Verifier, next http.HandlerFunc) ht return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { claims, err := jwtVerifier.Verify(request.Header.Get("Authorization")) if err != nil { + if errors.Is(err, auth.ErrAccessTokenExpired) { + // 只有明确 JWT exp 过期才给客户端刷新信号;签名非法、缺 token 仍保持普通 UNAUTHORIZED。 + httpkit.WriteError(writer, request, http.StatusUnauthorized, httpkit.CodeAccessTokenExpired, "access token expired") + return + } httpkit.WriteError(writer, request, http.StatusUnauthorized, httpkit.CodeUnauthorized, "unauthorized") return } @@ -95,6 +101,8 @@ func (h *Handler) withOptionalAuth(jwtVerifier *auth.Verifier, next http.Handler func (h *Handler) revokedSession(ctx context.Context, appCode string, sessionID string) (bool, error) { if h.loginRiskCache == nil { + // Handler 允许被纯 transport 单测和轻量工具独立构造;生产 app 的 configureLoginRisk 已把 + // Redis 缺失/连接失败设为启动失败,因此线上进入此分支只可能是非生产装配。 return false, nil } return h.loginRiskCache.RevokedSessionExists(ctx, appCode, sessionID) diff --git a/services/gateway-service/internal/transport/http/response_test.go b/services/gateway-service/internal/transport/http/response_test.go index 526ea117..81748df7 100644 --- a/services/gateway-service/internal/transport/http/response_test.go +++ b/services/gateway-service/internal/transport/http/response_test.go @@ -771,6 +771,9 @@ func (f *fakeWithdrawalApplicationWriter) CreateApplication(_ context.Context, c if resp.Status == "" { resp.Status = financewithdrawal.StatusPending } + if resp.OperationsStatus == "" { + resp.OperationsStatus = financewithdrawal.OperationsStatusPending + } if resp.CreatedAtMS == 0 { resp.CreatedAtMS = command.CreatedAtMS } @@ -6053,7 +6056,7 @@ func TestSalaryWalletWithdrawAddressGetAndSave(t *testing.T) { } } -func TestSalaryWalletWithdrawCreatesFinanceApplicationWithSavedAddress(t *testing.T) { +func TestSalaryWalletWithdrawCreatesOperationsPendingApplicationWithSavedAddress(t *testing.T) { walletClient := &fakeWalletClient{resp: &walletv1.GetBalancesResponse{Balances: []*walletv1.AssetBalance{ {AssetType: "HOST_SALARY_USD", AvailableAmount: 6000}, }}} @@ -6119,6 +6122,7 @@ func TestSalaryWalletWithdrawCreatesFinanceApplicationWithSavedAddress(t *testin balanceAfter, _ := data["salary_balance_after"].(map[string]any) if data["application_id"] != "77" || data["status"] != "pending" || + data["operations_status"] != "pending" || data["withdraw_amount"] != "50.00" || data["withdraw_address"] != "TCSTWxGagPpCS8RaZeBXMW9d69gUsK9QGb" || data["freeze_transaction_id"] != "freeze-tx-1" || @@ -7815,7 +7819,7 @@ func TestRefreshRateLimitByDeviceID(t *testing.T) { func TestRefreshPropagatesCurrentClientVersionWithHeaderPriority(t *testing.T) { userClient := &fakeUserAuthClient{} router := NewHandler(&fakeRoomClient{}, userClient).Routes(auth.NewVerifier("secret")) - body := []byte(`{"refresh_token":"refresh-1","device_id":"dev-1","app_version":"1.2.3","build_number":"123"}`) + body := []byte(`{"refresh_token":"refresh-1","refresh_request_id":"refresh-attempt-1","device_id":"dev-1","app_version":"1.2.3","build_number":"123"}`) request := httptest.NewRequest(http.MethodPost, "/api/v1/auth/token/refresh", bytes.NewReader(body)) request.Header.Set("X-Request-ID", "req-refresh-version") request.Header.Set("X-App-Version", "2.0.0") @@ -7831,6 +7835,9 @@ func TestRefreshPropagatesCurrentClientVersionWithHeaderPriority(t *testing.T) { if meta.GetAppVersion() != "2.0.0" || meta.GetBuildNumber() != "200" { t.Fatalf("refresh client version mismatch: %+v", meta) } + if userClient.lastRefresh.GetRefreshRequestId() != "refresh-attempt-1" { + t.Fatalf("refresh_request_id must reach user-service, got %q", userClient.lastRefresh.GetRefreshRequestId()) + } } func TestLogoutRateLimitBySessionIDAndIP(t *testing.T) { @@ -11243,6 +11250,28 @@ func TestRoutesWriteUnauthorizedEnvelope(t *testing.T) { assertEnvelope(t, recorder, http.StatusUnauthorized, httpkit.CodeUnauthorized, "req-auth") } +func TestRoutesWriteAccessTokenExpiredOnlyForValidExpiredJWT(t *testing.T) { + token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "user_id": "42", + "sid": "sess-expired", + "app_code": "lalu", + "exp": time.Now().Add(-time.Minute).Unix(), + }) + signed, err := token.SignedString([]byte("secret")) + if err != nil { + t.Fatalf("sign expired gateway token failed: %v", err) + } + router := NewHandler(&fakeRoomClient{}).Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodPost, "/api/v1/rooms/create", bytes.NewReader([]byte(`{}`))) + request.Header.Set("Authorization", "Bearer "+signed) + request.Header.Set("X-Request-ID", "req-expired-access-token") + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + assertEnvelope(t, recorder, http.StatusUnauthorized, httpkit.CodeAccessTokenExpired, "req-expired-access-token") +} + func TestRoutesWriteInvalidJSONEnvelope(t *testing.T) { router := NewHandler(&fakeRoomClient{}).Routes(auth.NewVerifier("secret")) request := httptest.NewRequest(http.MethodPost, "/api/v1/rooms/create", bytes.NewReader([]byte(`{`))) diff --git a/services/gateway-service/internal/transport/http/userapi/cp_handler.go b/services/gateway-service/internal/transport/http/userapi/cp_handler.go index 94792e47..37983727 100644 --- a/services/gateway-service/internal/transport/http/userapi/cp_handler.go +++ b/services/gateway-service/internal/transport/http/userapi/cp_handler.go @@ -8,6 +8,7 @@ import ( userv1 "hyapp.local/api/proto/user/v1" walletv1 "hyapp.local/api/proto/wallet/v1" "hyapp/services/gateway-service/internal/auth" + "hyapp/services/gateway-service/internal/client" "hyapp/services/gateway-service/internal/transport/http/httpkit" ) @@ -48,6 +49,14 @@ type cpIntimacyLeaderboardItemData struct { UpdatedAtMS int64 `json:"updated_at_ms"` } +type cpFormationGiftFeedItemData struct { + FormationID string `json:"formation_id"` + GiftCoinValue int64 `json:"gift_coin_value"` + Requester *cpUserProfileData `json:"requester,omitempty"` + Target *cpUserProfileData `json:"target,omitempty"` + FormedAtMS int64 `json:"formed_at_ms"` +} + type cpGiftSnapshotData struct { GiftID string `json:"gift_id"` GiftName string `json:"gift_name"` @@ -55,6 +64,7 @@ type cpGiftSnapshotData struct { GiftAnimationURL string `json:"gift_animation_url"` GiftCount int32 `json:"gift_count"` GiftValue int64 `json:"gift_value"` + CoinSpent int64 `json:"coin_spent"` BillingReceiptID string `json:"billing_receipt_id"` } @@ -272,6 +282,59 @@ func (h *Handler) listCPIntimacyLeaderboard(writer http.ResponseWriter, request }) } +// listCPFormationGiftFeed 返回已接受的 CP 成立礼物事件流,金额口径固定为 wallet 结算出的礼物金币价值。 +func (h *Handler) listCPFormationGiftFeed(writer http.ResponseWriter, request *http.Request) { + feedClient, ok := h.userCPClient.(client.UserCPFormationGiftFeedClient) + if h.userCPClient == nil || !ok { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + limit, ok := cpFormationGiftFeedLimit(request) + if !ok { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + // HTTP 只允许客户端缩小/放大返回条数到 100;严格 >5000、accepted 和 CP 类型都不能由 query 覆盖。 + resp, err := feedClient.ListCPFormationGiftFeed(request.Context(), &userv1.ListCPFormationGiftFeedRequest{ + Meta: httpkit.UserMeta(request, ""), + Limit: limit, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + items := make([]cpFormationGiftFeedItemData, 0, len(resp.GetItems())) + for _, item := range resp.GetItems() { + if item == nil { + continue + } + items = append(items, cpFormationGiftFeedItemData{ + FormationID: item.GetFormationId(), + GiftCoinValue: item.GetGiftCoinValue(), + Requester: cpUserProfileFromProto(item.GetRequester()), + Target: cpUserProfileFromProto(item.GetTarget()), + FormedAtMS: item.GetFormedAtMs(), + }) + } + httpkit.WriteOK(writer, request, map[string]any{"items": items}) +} + +func cpFormationGiftFeedLimit(request *http.Request) (int32, bool) { + raw := strings.TrimSpace(request.URL.Query().Get("limit")) + if raw == "" { + // 0 由 user-service 归一成默认 20,保证 HTTP 和内部 RPC 共用一套上限语义。 + return 0, true + } + parsed, err := strconv.ParseInt(raw, 10, 32) + if err != nil || parsed <= 0 { + return 0, false + } + if parsed > 100 { + parsed = 100 + } + return int32(parsed), true +} + // breakCPRelationship 先在 user-service 创建解除占位,再扣钱包,最后确认关系 ended,避免并发请求重复扣费。 func (h *Handler) breakCPRelationship(writer http.ResponseWriter, request *http.Request) { if h.userCPClient == nil || h.walletClient == nil { @@ -477,6 +540,7 @@ func cpGiftSnapshotFromProto(item *userv1.CPGiftSnapshot) *cpGiftSnapshotData { GiftAnimationURL: item.GetGiftAnimationUrl(), GiftCount: item.GetGiftCount(), GiftValue: item.GetGiftValue(), + CoinSpent: item.GetCoinSpent(), BillingReceiptID: item.GetBillingReceiptId(), } } diff --git a/services/gateway-service/internal/transport/http/userapi/handler.go b/services/gateway-service/internal/transport/http/userapi/handler.go index a12f296e..38b4d258 100644 --- a/services/gateway-service/internal/transport/http/userapi/handler.go +++ b/services/gateway-service/internal/transport/http/userapi/handler.go @@ -112,6 +112,7 @@ func (h *Handler) UserHandlers() httproutes.UserHandlers { RejectCPApplication: h.rejectCPApplication, ListCPRelationships: h.listCPRelationships, ListCPIntimacyLeaderboard: h.listCPIntimacyLeaderboard, + ListCPFormationGiftFeed: h.listCPFormationGiftFeed, BreakCPRelationship: h.breakCPRelationship, GetMyProfile: h.getMyProfile, GetUserProfile: h.getUserProfile, diff --git a/services/gateway-service/internal/transport/http/vip_handler_test.go b/services/gateway-service/internal/transport/http/vip_handler_test.go index 06ed461b..a4b20dcd 100644 --- a/services/gateway-service/internal/transport/http/vip_handler_test.go +++ b/services/gateway-service/internal/transport/http/vip_handler_test.go @@ -184,6 +184,9 @@ func TestTriggerVIPOnlineNoticeDenialDoesNotReadProfileOrBroadcast(t *testing.T) if recorder.Code != http.StatusForbidden || profileClient.lastGet != nil || broadcastClient.lastGlobal != nil { t.Fatalf("denied request leaked into downstream calls: status=%d profile=%+v broadcast=%+v body=%s", recorder.Code, profileClient.lastGet, broadcastClient.lastGlobal, recorder.Body.String()) } + if !strings.Contains(recorder.Body.String(), `"code":"VIP_BENEFIT_REQUIRED"`) { + t.Fatalf("denied notice must expose stable VIP code: %s", recorder.Body.String()) + } } func TestTriggerVIPOnlineNoticeUserSettingDenialDoesNotReadProfileOrBroadcast(t *testing.T) { @@ -214,12 +217,16 @@ func TestVIPSettingsHTTPContractPreservesExplicitFalseAndAuthScope(t *testing.T) UserSettings: &walletv1.VipUserSettings{ AppCode: "fami", UserId: 42, RoomEntryNoticeEnabled: true, OnlineGlobalNoticeEnabled: false, UpdatedAtMs: 1_799_999_999_000, + HideProfileDataEnabled: true, AnonymousProfileVisitEnabled: false, + LeaderboardInvisibleEnabled: true, }, }}, updateVIPSettingsResp: &walletv1.UpdateMyVipSettingsResponse{ Settings: &walletv1.VipUserSettings{ AppCode: "fami", UserId: 42, RoomEntryNoticeEnabled: false, OnlineGlobalNoticeEnabled: false, UpdatedAtMs: 1_800_000_000_100, + HideProfileDataEnabled: false, AnonymousProfileVisitEnabled: false, + LeaderboardInvisibleEnabled: true, }, ServerTimeMs: 1_800_000_000_200, }, @@ -240,10 +247,13 @@ func TestVIPSettingsHTTPContractPreservesExplicitFalseAndAuthScope(t *testing.T) var getEnvelope struct { Data struct { Settings struct { - AppCode string `json:"app_code"` - UserID int64 `json:"user_id"` - RoomEntryNoticeEnabled bool `json:"room_entry_notice_enabled"` - OnlineGlobalNoticeEnabled bool `json:"online_global_notice_enabled"` + AppCode string `json:"app_code"` + UserID int64 `json:"user_id"` + RoomEntryNoticeEnabled bool `json:"room_entry_notice_enabled"` + OnlineGlobalNoticeEnabled bool `json:"online_global_notice_enabled"` + HideProfileDataEnabled bool `json:"hide_profile_data_enabled"` + AnonymousProfileVisitEnabled bool `json:"anonymous_profile_visit_enabled"` + LeaderboardInvisibleEnabled bool `json:"leaderboard_invisible_enabled"` } `json:"settings"` EvaluatedAtMS int64 `json:"evaluated_at_ms"` } `json:"data"` @@ -251,11 +261,11 @@ func TestVIPSettingsHTTPContractPreservesExplicitFalseAndAuthScope(t *testing.T) if err := json.NewDecoder(getRecorder.Body).Decode(&getEnvelope); err != nil { t.Fatalf("decode GET settings response failed: %v", err) } - if getEnvelope.Data.Settings.AppCode != "fami" || getEnvelope.Data.Settings.UserID != 42 || !getEnvelope.Data.Settings.RoomEntryNoticeEnabled || getEnvelope.Data.Settings.OnlineGlobalNoticeEnabled || getEnvelope.Data.EvaluatedAtMS != 1_800_000_000_000 { + if getEnvelope.Data.Settings.AppCode != "fami" || getEnvelope.Data.Settings.UserID != 42 || !getEnvelope.Data.Settings.RoomEntryNoticeEnabled || getEnvelope.Data.Settings.OnlineGlobalNoticeEnabled || !getEnvelope.Data.Settings.HideProfileDataEnabled || getEnvelope.Data.Settings.AnonymousProfileVisitEnabled || !getEnvelope.Data.Settings.LeaderboardInvisibleEnabled || getEnvelope.Data.EvaluatedAtMS != 1_800_000_000_000 { t.Fatalf("GET settings response mismatch: %+v", getEnvelope.Data) } - patchRequest := httptest.NewRequest(http.MethodPatch, "/api/v1/vip/settings", bytes.NewReader([]byte(`{"room_entry_notice_enabled":false}`))) + patchRequest := httptest.NewRequest(http.MethodPatch, "/api/v1/vip/settings", bytes.NewReader([]byte(`{"room_entry_notice_enabled":false,"hide_profile_data_enabled":false}`))) patchRequest.Header.Set("Authorization", token) patchRecorder := httptest.NewRecorder() router.ServeHTTP(patchRecorder, patchRequest) @@ -263,7 +273,7 @@ func TestVIPSettingsHTTPContractPreservesExplicitFalseAndAuthScope(t *testing.T) t.Fatalf("PATCH settings status mismatch: got=%d body=%s", patchRecorder.Code, patchRecorder.Body.String()) } patch := walletClient.lastUpdateVIPSettings - if patch == nil || patch.GetAppCode() != "fami" || patch.GetUserId() != 42 || patch.RoomEntryNoticeEnabled == nil || patch.GetRoomEntryNoticeEnabled() || patch.OnlineGlobalNoticeEnabled != nil || patch.GetRequestId() != patchRecorder.Header().Get("X-Request-ID") { + if patch == nil || patch.GetAppCode() != "fami" || patch.GetUserId() != 42 || patch.RoomEntryNoticeEnabled == nil || patch.GetRoomEntryNoticeEnabled() || patch.HideProfileDataEnabled == nil || patch.GetHideProfileDataEnabled() || patch.OnlineGlobalNoticeEnabled != nil || patch.AnonymousProfileVisitEnabled != nil || patch.LeaderboardInvisibleEnabled != nil || patch.GetRequestId() != patchRecorder.Header().Get("X-Request-ID") { t.Fatalf("PATCH settings lost explicit false or auth scope: %+v", patch) } @@ -505,7 +515,13 @@ func TestListVIPPackagesAddsProgramStateAndLevelBenefits(t *testing.T) { CurrentVip: &walletv1.UserVip{UserId: 42, Level: 2, Active: true}, Packages: []*walletv1.VipLevel{{ Level: 3, Name: "VIP3", PriceCoin: 300, DurationMs: 2_592_000_000, CanPurchase: true, ConfigVersion: 7, - Benefits: []*walletv1.VipBenefit{{BenefitCode: "voice_wave", Name: "语音波纹", ExecutionScope: "room", TrialEnabled: true}}, + Benefits: []*walletv1.VipBenefit{{ + BenefitCode: "voice_wave", Name: "语音波纹", ExecutionScope: "room", TrialEnabled: true, + Presentation: &walletv1.VipBenefitPresentation{ + Description: "动态声波纹预览", + PreviewItems: []*walletv1.VipBenefitPreviewItem{{PreviewId: "wave-main", MediaType: "animation", AnimationUrl: "https://cdn.example/wave.svga", CompositionType: "user_avatar_waveform"}}, + }, + }}, }}, State: &walletv1.VipState{EffectiveVip: &walletv1.UserVip{UserId: 42, Level: 2, Active: true}, EffectiveSource: "paid", ProgramConfig: config}, ProgramConfig: config, @@ -537,7 +553,13 @@ func TestListVIPPackagesAddsProgramStateAndLevelBenefits(t *testing.T) { Packages []struct { ConfigVersion int64 `json:"config_version"` Benefits []struct { - BenefitCode string `json:"benefit_code"` + BenefitCode string `json:"benefit_code"` + Presentation struct { + Description string `json:"description"` + PreviewItems []struct { + CompositionType string `json:"composition_type"` + } `json:"preview_items"` + } `json:"presentation"` } `json:"benefits"` } `json:"packages"` } `json:"data"` @@ -551,13 +573,17 @@ func TestListVIPPackagesAddsProgramStateAndLevelBenefits(t *testing.T) { if envelope.Data.Packages[0].ConfigVersion != 7 || len(envelope.Data.Packages[0].Benefits) != 1 || envelope.Data.Packages[0].Benefits[0].BenefitCode != "voice_wave" { t.Fatalf("package benefits mismatch: %+v", envelope.Data.Packages) } + if envelope.Data.Packages[0].Benefits[0].Presentation.Description != "动态声波纹预览" || len(envelope.Data.Packages[0].Benefits[0].Presentation.PreviewItems) != 1 || envelope.Data.Packages[0].Benefits[0].Presentation.PreviewItems[0].CompositionType != "user_avatar_waveform" { + t.Fatalf("structured presentation mismatch: %+v", envelope.Data.Packages[0].Benefits[0].Presentation) + } } func TestPurchaseVIPKeepsLegacyResultAndAddsState(t *testing.T) { config := &walletv1.VipProgramConfig{AppCode: "fami", ProgramType: "tiered_privilege_v1", UpgradeExpiryPolicy: "replace_from_now", ConfigVersion: 8} walletClient := &fakeWalletClient{purchaseVipResp: &walletv1.PurchaseVipResponse{ OrderId: "vip-order-1", TransactionId: "vip-tx-1", Vip: &walletv1.UserVip{UserId: 42, Level: 4, Active: true, ExpiresAtMs: 4_000}, CoinSpent: 400, CoinBalanceAfter: 600, - State: &walletv1.VipState{PaidVip: &walletv1.UserVip{UserId: 42, Level: 4, Active: true}, EffectiveVip: &walletv1.UserVip{UserId: 42, Level: 4, Active: true}, EffectiveSource: "paid", ProgramConfig: config}, + CoinBalance: &walletv1.AssetBalance{AssetType: "COIN", AvailableAmount: 600, FrozenAmount: 0, Version: 18}, + State: &walletv1.VipState{PaidVip: &walletv1.UserVip{UserId: 42, Level: 4, Active: true}, EffectiveVip: &walletv1.UserVip{UserId: 42, Level: 4, Active: true}, EffectiveSource: "paid", ProgramConfig: config, UserSettings: &walletv1.VipUserSettings{AppCode: "fami", UserId: 42, RoomEntryNoticeEnabled: true, OnlineGlobalNoticeEnabled: true, HideProfileDataEnabled: true, AnonymousProfileVisitEnabled: true, LeaderboardInvisibleEnabled: true}}, }} router := newVIPTestRouter(walletClient) request := httptest.NewRequest(http.MethodPost, "/api/v1/vip/purchase", bytes.NewReader([]byte(`{"command_id":"vip-buy-4","level":4}`))) @@ -569,6 +595,7 @@ func TestPurchaseVIPKeepsLegacyResultAndAddsState(t *testing.T) { if recorder.Code != http.StatusOK { t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) } + assertCompleteVIPStateJSON(t, recorder.Body.Bytes()) if req := walletClient.lastPurchaseVip; req == nil || req.GetCommandId() != "vip-buy-4" || req.GetAppCode() != "fami" || req.GetUserId() != 42 || req.GetLevel() != 4 { t.Fatalf("PurchaseVip request mismatch: %+v", req) } @@ -585,12 +612,16 @@ func TestPurchaseVIPKeepsLegacyResultAndAddsState(t *testing.T) { State struct { EffectiveSource string `json:"effective_source"` } `json:"state"` + CoinBalance struct { + AvailableAmount int64 `json:"available_amount"` + Version int64 `json:"version"` + } `json:"coin_balance"` } `json:"data"` } if err := json.NewDecoder(recorder.Body).Decode(&envelope); err != nil { t.Fatalf("decode response failed: %v", err) } - if envelope.Data.OrderID != "vip-order-1" || envelope.Data.TransactionID != "vip-tx-1" || envelope.Data.VIP.Level != 4 || envelope.Data.ProgramConfig.UpgradeExpiryPolicy != "replace_from_now" || envelope.Data.State.EffectiveSource != "paid" { + if envelope.Data.OrderID != "vip-order-1" || envelope.Data.TransactionID != "vip-tx-1" || envelope.Data.VIP.Level != 4 || envelope.Data.ProgramConfig.UpgradeExpiryPolicy != "replace_from_now" || envelope.Data.State.EffectiveSource != "paid" || envelope.Data.CoinBalance.AvailableAmount != 600 || envelope.Data.CoinBalance.Version != 18 { t.Fatalf("purchase response mismatch: %+v", envelope.Data) } } @@ -612,6 +643,7 @@ func TestEquipVIPTrialCardUsesAuthenticatedEntitlement(t *testing.T) { if recorder.Code != http.StatusOK { t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) } + assertCompleteVIPStateJSON(t, recorder.Body.Bytes()) if req := walletClient.lastTrialEquip; req == nil || req.GetRequestId() != recorder.Header().Get("X-Request-ID") || req.GetAppCode() != "fami" || req.GetUserId() != 42 || req.GetEntitlementId() != "ent-card-9" { t.Fatalf("EquipVipTrialCard request mismatch: %+v", req) } @@ -651,6 +683,7 @@ func TestUnequipVIPTrialCardRestoresPaidState(t *testing.T) { if recorder.Code != http.StatusOK { t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) } + assertCompleteVIPStateJSON(t, recorder.Body.Bytes()) if req := walletClient.lastTrialUnequip; req == nil || req.GetRequestId() != recorder.Header().Get("X-Request-ID") || req.GetAppCode() != "fami" || req.GetUserId() != 42 { t.Fatalf("UnequipVipTrialCard request mismatch: %+v", req) } @@ -672,3 +705,22 @@ func TestUnequipVIPTrialCardRestoresPaidState(t *testing.T) { t.Fatalf("unequip response mismatch: %+v", envelope.Data) } } + +// assertCompleteVIPStateJSON 锁定所有 VIP 写接口的 state 与 /vip/me.state 同构;即使值为空, +// 字段也必须存在,Flutter 才能用响应原子替换本地状态而不是做不安全的局部合并。 +func assertCompleteVIPStateJSON(t *testing.T, body []byte) { + t.Helper() + var envelope struct { + Data struct { + State map[string]json.RawMessage `json:"state"` + } `json:"data"` + } + if err := json.Unmarshal(body, &envelope); err != nil { + t.Fatalf("decode complete state envelope: %v", err) + } + for _, field := range []string{"paid_vip", "equipped_trial_card", "effective_vip", "effective_source", "effective_benefits", "evaluated_at_ms", "program_config", "user_settings"} { + if _, exists := envelope.Data.State[field]; !exists { + t.Fatalf("VIP state missing %s: %s", field, body) + } + } +} 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 12a595e1..dfa330be 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 @@ -215,20 +215,45 @@ type vipProgramConfigData struct { // vipBenefitData 是最终生效权益的资格描述。客户端不得根据 unlock_level 自行继承; // 对可关闭通知还需结合 state.user_settings,真正执行前以 CheckVipBenefit 为准。 type vipBenefitData struct { - BenefitCode string `json:"benefit_code"` - Name string `json:"name"` - BenefitType string `json:"benefit_type"` - UnlockLevel int32 `json:"unlock_level"` - Status string `json:"status"` - TrialEnabled bool `json:"trial_enabled"` - ResourceID int64 `json:"resource_id"` - ResourceType string `json:"resource_type"` - ExecutionScope string `json:"execution_scope"` - AutoEquip bool `json:"auto_equip"` - SortOrder int32 `json:"sort_order"` - MetadataJSON string `json:"metadata_json"` - CreatedAtMS int64 `json:"created_at_ms"` - UpdatedAtMS int64 `json:"updated_at_ms"` + BenefitCode string `json:"benefit_code"` + Name string `json:"name"` + BenefitType string `json:"benefit_type"` + UnlockLevel int32 `json:"unlock_level"` + Status string `json:"status"` + TrialEnabled bool `json:"trial_enabled"` + ResourceID int64 `json:"resource_id"` + ResourceType string `json:"resource_type"` + ExecutionScope string `json:"execution_scope"` + AutoEquip bool `json:"auto_equip"` + SortOrder int32 `json:"sort_order"` + MetadataJSON string `json:"metadata_json"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` + Presentation *vipBenefitPresentationData `json:"presentation"` +} + +type vipBenefitPresentationData struct { + Description string `json:"description"` + PreviewItems []vipBenefitPreviewItemData `json:"preview_items"` + NumericReward *vipBenefitNumericRewardData `json:"numeric_reward"` +} + +type vipBenefitPreviewItemData struct { + PreviewID string `json:"preview_id"` + Title string `json:"title"` + MediaType string `json:"media_type"` + AssetURL string `json:"asset_url"` + PreviewURL string `json:"preview_url"` + AnimationURL string `json:"animation_url"` + CompositionType string `json:"composition_type"` + SortOrder int32 `json:"sort_order"` +} + +type vipBenefitNumericRewardData struct { + Label string `json:"label"` + Value int64 `json:"value"` + Unit string `json:"unit"` + Period string `json:"period"` } type vipTrialCardData struct { @@ -262,11 +287,14 @@ type vipStateData struct { } type vipUserSettingsData struct { - AppCode string `json:"app_code"` - UserID int64 `json:"user_id"` - RoomEntryNoticeEnabled bool `json:"room_entry_notice_enabled"` - OnlineGlobalNoticeEnabled bool `json:"online_global_notice_enabled"` - UpdatedAtMS int64 `json:"updated_at_ms"` + AppCode string `json:"app_code"` + UserID int64 `json:"user_id"` + RoomEntryNoticeEnabled bool `json:"room_entry_notice_enabled"` + OnlineGlobalNoticeEnabled bool `json:"online_global_notice_enabled"` + HideProfileDataEnabled bool `json:"hide_profile_data_enabled"` + AnonymousProfileVisitEnabled bool `json:"anonymous_profile_visit_enabled"` + LeaderboardInvisibleEnabled bool `json:"leaderboard_invisible_enabled"` + UpdatedAtMS int64 `json:"updated_at_ms"` } type vipRewardItemData struct { diff --git a/services/gateway-service/internal/transport/http/walletapi/point_wallet_handler.go b/services/gateway-service/internal/transport/http/walletapi/point_wallet_handler.go index 73e6f51b..02b3eeec 100644 --- a/services/gateway-service/internal/transport/http/walletapi/point_wallet_handler.go +++ b/services/gateway-service/internal/transport/http/walletapi/point_wallet_handler.go @@ -337,6 +337,7 @@ func (h *Handler) withdrawPointWallet(writer http.ResponseWriter, request *http. httpkit.WriteOK(writer, request, map[string]any{ "application_id": strconv.FormatInt(application.ID, 10), "status": application.Status, + "operations_status": application.OperationsStatus, "asset_type": pointWalletAssetType, "gross_point_amount": grossPoints, "fee_point_amount": feePoints, diff --git a/services/gateway-service/internal/transport/http/walletapi/point_wallet_handler_test.go b/services/gateway-service/internal/transport/http/walletapi/point_wallet_handler_test.go index 0f20e58d..2cfa4bd2 100644 --- a/services/gateway-service/internal/transport/http/walletapi/point_wallet_handler_test.go +++ b/services/gateway-service/internal/transport/http/walletapi/point_wallet_handler_test.go @@ -110,6 +110,8 @@ func TestWithdrawPointWalletFreezesWithClientCommandIDAndCreatesApplication(t *t } if response.Code != httpkit.CodeOK || response.Data["application_id"] != "77" || + response.Data["status"] != financewithdrawal.StatusPending || + response.Data["operations_status"] != financewithdrawal.OperationsStatusPending || response.Data["gross_point_amount"] != float64(1_000_000) || response.Data["fee_point_amount"] != float64(50_000) || response.Data["net_usd"] != "9.50" { @@ -247,6 +249,7 @@ func (f *fakePointWithdrawalWriter) CreateApplication(_ context.Context, command WithdrawAddress: command.WithdrawAddress, FreezeCommandID: command.FreezeCommandID, FreezeTransactionID: command.FreezeTransactionID, + OperationsStatus: financewithdrawal.OperationsStatusPending, Status: financewithdrawal.StatusPending, CreatedAtMS: command.CreatedAtMS, UpdatedAtMS: command.CreatedAtMS, 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 index 871253be..2aa1fd73 100644 --- a/services/gateway-service/internal/transport/http/walletapi/salary_wallet_handler.go +++ b/services/gateway-service/internal/transport/http/walletapi/salary_wallet_handler.go @@ -406,6 +406,7 @@ func (h *Handler) withdrawSalaryWallet(writer http.ResponseWriter, request *http httpkit.WriteOK(writer, request, map[string]any{ "application_id": strconv.FormatInt(application.ID, 10), "status": application.Status, + "operations_status": application.OperationsStatus, "identity": identity.Identity, "salary_asset_type": identity.SalaryAssetType, "salary_usd_minor": amountUSDMinor, diff --git a/services/gateway-service/internal/transport/http/walletapi/vip_handler.go b/services/gateway-service/internal/transport/http/walletapi/vip_handler.go index 587aecef..b376d4f3 100644 --- a/services/gateway-service/internal/transport/http/walletapi/vip_handler.go +++ b/services/gateway-service/internal/transport/http/walletapi/vip_handler.go @@ -11,6 +11,7 @@ import ( userv1 "hyapp.local/api/proto/user/v1" walletv1 "hyapp.local/api/proto/wallet/v1" "hyapp/pkg/appcode" + "hyapp/pkg/xerr" "hyapp/services/gateway-service/internal/auth" "hyapp/services/gateway-service/internal/transport/http/httpkit" ) @@ -131,6 +132,7 @@ func (h *Handler) purchaseVIP(writer http.ResponseWriter, request *http.Request) "vip": vipFromProto(resp.GetVip()), "coin_spent": resp.GetCoinSpent(), "coin_balance_after": resp.GetCoinBalanceAfter(), + "coin_balance": balanceFromProto(resp.GetCoinBalance()), "reward_items": vipRewardItemsFromProto(resp.GetRewardItems()), "program_config": vipProgramConfigFromProto(resp.GetState().GetProgramConfig()), "state": vipStateFromProto(resp.GetState()), @@ -230,7 +232,8 @@ func (h *Handler) triggerVIPOnlineNotice(writer http.ResponseWriter, request *ht if !benefitResp.GetAllowed() { // 客户端展示态可能滞后,执行前必须重新查 effective benefit;体验卡排除、过期和后台停用 // 都以 wallet-service 此刻的判定为准,不能仅比较 VIP9 等级。 - httpkit.WriteError(writer, request, http.StatusForbidden, httpkit.CodePermissionDenied, "permission denied") + statusCode, code, message := httpkit.MapReasonToHTTP(xerr.VIPBenefitRequired) + httpkit.WriteError(writer, request, statusCode, code, message) return } equippedResp, err := h.walletClient.BatchGetUserEquippedResources(ctx, &walletv1.BatchGetUserEquippedResourcesRequest{ @@ -434,11 +437,38 @@ func vipBenefitsFromProto(items []*walletv1.VipBenefit) []vipBenefitData { MetadataJSON: item.GetMetadataJson(), CreatedAtMS: item.GetCreatedAtMs(), UpdatedAtMS: item.GetUpdatedAtMs(), + Presentation: vipBenefitPresentationFromProto(item.GetPresentation()), }) } return result } +func vipBenefitPresentationFromProto(item *walletv1.VipBenefitPresentation) *vipBenefitPresentationData { + if item == nil { + return nil + } + result := &vipBenefitPresentationData{ + Description: item.GetDescription(), + PreviewItems: make([]vipBenefitPreviewItemData, 0, len(item.GetPreviewItems())), + } + for _, preview := range item.GetPreviewItems() { + if preview == nil { + continue + } + result.PreviewItems = append(result.PreviewItems, vipBenefitPreviewItemData{ + PreviewID: preview.GetPreviewId(), Title: preview.GetTitle(), MediaType: preview.GetMediaType(), + AssetURL: preview.GetAssetUrl(), PreviewURL: preview.GetPreviewUrl(), AnimationURL: preview.GetAnimationUrl(), + CompositionType: preview.GetCompositionType(), SortOrder: preview.GetSortOrder(), + }) + } + if reward := item.GetNumericReward(); reward != nil { + result.NumericReward = &vipBenefitNumericRewardData{ + Label: reward.GetLabel(), Value: reward.GetValue(), Unit: reward.GetUnit(), Period: reward.GetPeriod(), + } + } + return result +} + func vipTrialCardFromProto(card *walletv1.VipTrialCard) *vipTrialCardData { if card == nil { return nil @@ -469,6 +499,8 @@ func vipStateFromProto(state *walletv1.VipState) vipStateData { EffectiveBenefits: []vipBenefitData{}, UserSettings: vipUserSettingsData{ RoomEntryNoticeEnabled: true, OnlineGlobalNoticeEnabled: true, + HideProfileDataEnabled: true, AnonymousProfileVisitEnabled: true, + LeaderboardInvisibleEnabled: true, }, } } @@ -487,13 +519,20 @@ func vipStateFromProto(state *walletv1.VipState) vipStateData { func vipUserSettingsFromProto(settings *walletv1.VipUserSettings) vipUserSettingsData { if settings == nil { // wallet 滚动升级期间旧实例没有 tag 8;与 wallet owner 的缺行语义一致,按默认开启兼容。 - return vipUserSettingsData{RoomEntryNoticeEnabled: true, OnlineGlobalNoticeEnabled: true} + return vipUserSettingsData{ + RoomEntryNoticeEnabled: true, OnlineGlobalNoticeEnabled: true, + HideProfileDataEnabled: true, AnonymousProfileVisitEnabled: true, + LeaderboardInvisibleEnabled: true, + } } return vipUserSettingsData{ AppCode: settings.GetAppCode(), UserID: settings.GetUserId(), - RoomEntryNoticeEnabled: settings.GetRoomEntryNoticeEnabled(), - OnlineGlobalNoticeEnabled: settings.GetOnlineGlobalNoticeEnabled(), - UpdatedAtMS: settings.GetUpdatedAtMs(), + RoomEntryNoticeEnabled: settings.GetRoomEntryNoticeEnabled(), + OnlineGlobalNoticeEnabled: settings.GetOnlineGlobalNoticeEnabled(), + HideProfileDataEnabled: settings.GetHideProfileDataEnabled(), + AnonymousProfileVisitEnabled: settings.GetAnonymousProfileVisitEnabled(), + LeaderboardInvisibleEnabled: settings.GetLeaderboardInvisibleEnabled(), + UpdatedAtMS: settings.GetUpdatedAtMs(), } } diff --git a/services/gateway-service/internal/transport/http/walletapi/vip_settings_handler.go b/services/gateway-service/internal/transport/http/walletapi/vip_settings_handler.go index dddbc381..f689b5cf 100644 --- a/services/gateway-service/internal/transport/http/walletapi/vip_settings_handler.go +++ b/services/gateway-service/internal/transport/http/walletapi/vip_settings_handler.go @@ -11,8 +11,11 @@ import ( type vipSettingsPatchBody struct { // 指针保留 PATCH 的三态:未提交、显式 true、显式 false。 - RoomEntryNoticeEnabled *bool `json:"room_entry_notice_enabled"` - OnlineGlobalNoticeEnabled *bool `json:"online_global_notice_enabled"` + RoomEntryNoticeEnabled *bool `json:"room_entry_notice_enabled"` + OnlineGlobalNoticeEnabled *bool `json:"online_global_notice_enabled"` + HideProfileDataEnabled *bool `json:"hide_profile_data_enabled"` + AnonymousProfileVisitEnabled *bool `json:"anonymous_profile_visit_enabled"` + LeaderboardInvisibleEnabled *bool `json:"leaderboard_invisible_enabled"` } // handleVIPSettings 在同一路径分发 GET/PATCH,避免向当前 ServeMux 重复注册相同 pattern。 @@ -70,7 +73,9 @@ func (h *Handler) patchVIPSettings(writer http.ResponseWriter, request *http.Req if !httpkit.Decode(writer, request, &body) { return } - if body.RoomEntryNoticeEnabled == nil && body.OnlineGlobalNoticeEnabled == nil { + if body.RoomEntryNoticeEnabled == nil && body.OnlineGlobalNoticeEnabled == nil && + body.HideProfileDataEnabled == nil && body.AnonymousProfileVisitEnabled == nil && + body.LeaderboardInvisibleEnabled == nil { httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") return } @@ -78,7 +83,10 @@ func (h *Handler) patchVIPSettings(writer http.ResponseWriter, request *http.Req resp, err := h.walletClient.UpdateMyVipSettings(ctx, &walletv1.UpdateMyVipSettingsRequest{ RequestId: httpkit.RequestIDFromContext(ctx), AppCode: appcode.FromContext(ctx), UserId: auth.UserIDFromContext(ctx), RoomEntryNoticeEnabled: body.RoomEntryNoticeEnabled, - OnlineGlobalNoticeEnabled: body.OnlineGlobalNoticeEnabled, + OnlineGlobalNoticeEnabled: body.OnlineGlobalNoticeEnabled, + HideProfileDataEnabled: body.HideProfileDataEnabled, + AnonymousProfileVisitEnabled: body.AnonymousProfileVisitEnabled, + LeaderboardInvisibleEnabled: body.LeaderboardInvisibleEnabled, }) if err != nil { httpkit.WriteRPCError(writer, request, err) diff --git a/services/room-service/internal/room/outbox/outbox.go b/services/room-service/internal/room/outbox/outbox.go index e36feb1e..c5d351f5 100644 --- a/services/room-service/internal/room/outbox/outbox.go +++ b/services/room-service/internal/room/outbox/outbox.go @@ -6,7 +6,6 @@ import ( "google.golang.org/protobuf/proto" roomeventsv1 "hyapp.local/api/proto/events/room/v1" - "hyapp/pkg/appcode" "hyapp/pkg/idgen" ) @@ -62,14 +61,14 @@ func Build(roomID string, eventType string, roomVersion int64, occurredAt time.T // EventID 在 room-service 生成,后续同步广播和异步补偿都用同一个 ID 去重。 eventID := idgen.New("evt") + // Build 没有请求上下文,不能在多 App 环境猜租户。SaveMutation/SaveOutbox 会在持久化前用 + // 当前请求的 app_code 同时补齐 Record 和 Envelope;直发 IM/机器人展示也在发布边界做同样处理。 return Record{ - AppCode: appcode.Default, EventID: eventID, EventType: eventType, RoomID: roomID, Status: StatusPending, Envelope: &roomeventsv1.EventEnvelope{ - AppCode: appcode.Default, EventId: eventID, RoomId: roomID, EventType: eventType, diff --git a/services/room-service/internal/room/service/admin_robot_room.go b/services/room-service/internal/room/service/admin_robot_room.go index 5158f688..981651b4 100644 --- a/services/room-service/internal/room/service/admin_robot_room.go +++ b/services/room-service/internal/room/service/admin_robot_room.go @@ -235,6 +235,8 @@ func (s *Service) bootstrapRobotRoom(ctx context.Context, config RobotRoomConfig if _, err := s.JoinRoom(ctx, &roomv1.JoinRoomRequest{ Meta: robotRoomCommandMeta(config, userID, fmt.Sprintf("join:%d", userID)), Role: "audience", + // 首批机器人与运行期替换机器人必须使用同一事实标记;否则 RoomUserJoined 会被统计成缺国家的真人 DAU。 + ActorIsRobot: true, }); err != nil { return err } diff --git a/services/room-service/internal/room/service/admin_robot_room_test.go b/services/room-service/internal/room/service/admin_robot_room_test.go index d380d078..6eed9d48 100644 --- a/services/room-service/internal/room/service/admin_robot_room_test.go +++ b/services/room-service/internal/room/service/admin_robot_room_test.go @@ -139,16 +139,21 @@ func TestAdminCreateRobotRoomMarksRobotJoinOutbox(t *testing.T) { _, err := svc.AdminCreateRobotRoom(ctx, &roomv1.AdminCreateRobotRoomRequest{ Meta: roomservice.NewRequestMeta("", 9001), OwnerRobotUserId: 2001, - CandidateRobotUserIds: []int64{2001}, - MinRobotCount: 1, - MaxRobotCount: 1, + CandidateRobotUserIds: []int64{2001, 2002}, + MinRobotCount: 2, + MaxRobotCount: 2, RoomName: "Robot Join Outbox", RoomAvatar: testRoomCoverURL, VisibleRegionId: 686, OwnerCountryCode: "ae", GiftRule: &roomv1.AdminRobotRoomGiftRule{ GiftIds: []string{"84"}, + LuckyGiftIds: []string{"28"}, NormalGiftIntervalMs: 10000, + LuckyComboMin: 100, + LuckyComboMax: 10000, + LuckyPauseMinMs: 5000, + LuckyPauseMaxMs: 20000, }, AdminId: 9001, }) @@ -161,6 +166,7 @@ func TestAdminCreateRobotRoomMarksRobotJoinOutbox(t *testing.T) { t.Fatalf("list pending outbox failed: %v", err) } joinEvents := 0 + bootstrapRobotJoined := false for _, record := range records { if record.EventType != "RoomUserJoined" { continue @@ -170,13 +176,17 @@ func TestAdminCreateRobotRoomMarksRobotJoinOutbox(t *testing.T) { if err := proto.Unmarshal(record.Envelope.GetBody(), &joined); err != nil { t.Fatalf("decode room join event failed: %v", err) } - if joined.GetUserId() == 2001 && !joined.GetIsRobot() { + if !joined.GetIsRobot() { t.Fatalf("robot join outbox must mark is_robot=true: %+v", &joined) } + bootstrapRobotJoined = bootstrapRobotJoined || joined.GetUserId() == 2002 } if joinEvents == 0 { t.Fatalf("robot room creation should write RoomUserJoined outbox") } + if !bootstrapRobotJoined { + t.Fatalf("bootstrap robot should write RoomUserJoined outbox") + } } func occupiedSeatUserCount(snapshot *roomv1.RoomSnapshot) int { diff --git a/services/room-service/internal/room/service/outbox_worker_internal_test.go b/services/room-service/internal/room/service/outbox_worker_internal_test.go index 98cb701d..0942f77b 100644 --- a/services/room-service/internal/room/service/outbox_worker_internal_test.go +++ b/services/room-service/internal/room/service/outbox_worker_internal_test.go @@ -14,6 +14,24 @@ type countingOutboxPublisher struct { events []*roomeventsv1.EventEnvelope } +type scopedOutboxPublication struct { + contextApp string + envelopeApp string +} + +type scopedOutboxPublisher struct { + published chan scopedOutboxPublication +} + +func newScopedOutboxPublisher() *scopedOutboxPublisher { + return &scopedOutboxPublisher{published: make(chan scopedOutboxPublication, 2)} +} + +func (p *scopedOutboxPublisher) PublishOutboxEvent(ctx context.Context, envelope *roomeventsv1.EventEnvelope) error { + p.published <- scopedOutboxPublication{contextApp: appcode.FromContext(ctx), envelopeApp: envelope.GetAppCode()} + return nil +} + type crossAppOutboxRepository struct { Repository claims []string @@ -46,6 +64,51 @@ func TestOutboxSingleRecordLeaseCoversPublishAndStateWrite(t *testing.T) { } } +func TestDirectAndRobotPublishersScopeBuiltRecordsFromContext(t *testing.T) { + ctx := appcode.WithContext(context.Background(), "fami") + directPublisher := newScopedOutboxPublisher() + robotPublisher := newScopedOutboxPublisher() + svc := &Service{roomDisplayPublisher: directPublisher, robotDisplayPublisher: robotPublisher} + build := func(eventType string) outbox.Record { + record, err := outbox.Build("fami-room-publish", eventType, 3, time.UnixMilli(3000), &roomeventsv1.RoomUserJoined{UserId: 1001}) + if err != nil { + t.Fatalf("build %s outbox: %v", eventType, err) + } + return record + } + + svc.publishDirectIMRecordsBestEffort(ctx, []outbox.Record{build("RoomUserJoined")}) + svc.publishRobotDisplayRecordsBestEffort(ctx, []outbox.Record{build("RoomRobotUserJoined")}) + for name, publisher := range map[string]*scopedOutboxPublisher{"direct": directPublisher, "robot": robotPublisher} { + select { + case publication := <-publisher.published: + if publication.contextApp != "fami" || publication.envelopeApp != "fami" { + t.Fatalf("%s publisher lost scoped app: context=%q envelope=%q", name, publication.contextApp, publication.envelopeApp) + } + case <-time.After(time.Second): + t.Fatalf("%s publisher did not receive built record", name) + } + } +} + +func TestRobotDisplaySamplerUsesCommandAppForContextFreeRecords(t *testing.T) { + svc := &Service{robotDisplaySampler: newRobotDisplaySampler()} + build := func() outbox.Record { + record, err := outbox.Build("shared-room-id", "RoomRobotLuckyGiftDrawn", 3, time.UnixMilli(3000), &roomeventsv1.RoomRobotLuckyGiftDrawn{}) + if err != nil { + t.Fatalf("build robot display outbox: %v", err) + } + return record + } + // 同房间标识、事件类型和窗口在不同 App 下必须各保留一条;Build 尚未补 App,采样器只能从命令上下文取租户。 + if got := svc.sampleRobotDisplayRecords(appcode.WithContext(context.Background(), "fami"), []outbox.Record{build()}); len(got) != 1 { + t.Fatalf("fami robot display unexpectedly sampled: %+v", got) + } + if got := svc.sampleRobotDisplayRecords(appcode.WithContext(context.Background(), "huwaa"), []outbox.Record{build()}); len(got) != 1 { + t.Fatalf("huwaa robot display shared fami sample window: %+v", got) + } +} + func TestClaimPendingOutboxFindsNonDefaultApp(t *testing.T) { repository := &crossAppOutboxRepository{} svc := &Service{nodeID: "room-cross-app", repository: repository} diff --git a/services/room-service/internal/room/service/pipeline.go b/services/room-service/internal/room/service/pipeline.go index 92a50496..668c52d2 100644 --- a/services/room-service/internal/room/service/pipeline.go +++ b/services/room-service/internal/room/service/pipeline.go @@ -107,7 +107,7 @@ func (s *Service) mutateRoom(ctx context.Context, cmd command.Command, replayabl return nil, err } // 机器人展示只是 App 视觉补偿,提交前按短窗口降采样;命令日志、房间状态和主 outbox 不受影响。 - robotDisplayRecords := s.sampleRobotDisplayRecords(result.robotDisplayRecords) + robotDisplayRecords := s.sampleRobotDisplayRecords(ctx, result.robotDisplayRecords) durableOutboxRecords, directIMRecords := splitRoomDirectIMRecords(outboxRecords, result.suppressDirectIMEventTypes) // mutate 可额外返回只服务客户端展示的直发 IM,典型场景是重复 JoinRoom 的入房飘窗; // 这类事件不能进入 durable outbox,否则会污染活跃统计和补偿消费。 diff --git a/services/room-service/internal/room/service/robot_display_sampler.go b/services/room-service/internal/room/service/robot_display_sampler.go index 3bf30608..eb3d378a 100644 --- a/services/room-service/internal/room/service/robot_display_sampler.go +++ b/services/room-service/internal/room/service/robot_display_sampler.go @@ -1,6 +1,7 @@ package service import ( + "context" "sync" "time" @@ -28,14 +29,14 @@ func newRobotDisplaySampler() *robotDisplaySampler { return &robotDisplaySampler{lastWindow: make(map[robotDisplaySampleKey]int64)} } -func (s *Service) sampleRobotDisplayRecords(records []outbox.Record) []outbox.Record { +func (s *Service) sampleRobotDisplayRecords(ctx context.Context, records []outbox.Record) []outbox.Record { if len(records) == 0 || s == nil || s.robotDisplaySampler == nil { return records } - return s.robotDisplaySampler.filter(records, robotDisplaySampleWindow) + return s.robotDisplaySampler.filter(records, robotDisplaySampleWindow, appcode.FromContext(ctx)) } -func (s *robotDisplaySampler) filter(records []outbox.Record, window time.Duration) []outbox.Record { +func (s *robotDisplaySampler) filter(records []outbox.Record, window time.Duration, scopedApp string) []outbox.Record { if s == nil || window <= 0 || len(records) == 0 { return records } @@ -48,7 +49,9 @@ func (s *robotDisplaySampler) filter(records []outbox.Record, window time.Durati var newestWindow int64 for _, record := range records { key := robotDisplaySampleKey{ - appCode: appcode.Normalize(record.AppCode), + // Build 阶段故意不猜 App;降采样发生在发布边界补值之前,因此必须使用当前命令上下文兜底, + // 否则不同 App 的同房间标识会共用默认 Lalu 窗口并误丢展示事件。 + appCode: appcode.Normalize(firstNonEmpty(record.AppCode, scopedApp)), roomID: record.RoomID, eventType: record.EventType, } diff --git a/services/room-service/internal/room/service/vip.go b/services/room-service/internal/room/service/vip.go index 1c37eff5..6cf20563 100644 --- a/services/room-service/internal/room/service/vip.go +++ b/services/room-service/internal/room/service/vip.go @@ -118,7 +118,7 @@ func (s *Service) requireCustomRoomBackgroundBenefit(ctx context.Context, reques return nil } if !access.hasBenefit(vipBenefitCustomRoomBackground) { - return xerr.New(xerr.PermissionDenied, "custom room background vip benefit is required") + return xerr.New(xerr.VIPBenefitRequired, "custom room background vip benefit is required") } return nil } @@ -131,7 +131,14 @@ func (s *Service) requireTargetWithoutVIPBenefit(ctx context.Context, requestID return err } if access.hasBenefit(benefitCode) { - return xerr.New(xerr.PermissionDenied, "target vip benefit prevents this room moderation action") + switch normalizeVIPCode(benefitCode) { + case vipBenefitAntiKick: + return xerr.New(xerr.VIPAntiKick, "target vip benefit prevents kick") + case vipBenefitAntiMute: + return xerr.New(xerr.VIPAntiMute, "target vip benefit prevents mute") + default: + return xerr.New(xerr.VIPBenefitRequired, "target vip benefit prevents this room moderation action") + } } return nil } diff --git a/services/room-service/internal/room/service/vip_test.go b/services/room-service/internal/room/service/vip_test.go index b280e93b..39643004 100644 --- a/services/room-service/internal/room/service/vip_test.go +++ b/services/room-service/internal/room/service/vip_test.go @@ -48,6 +48,9 @@ func TestJoinRoomCarriesEffectiveVIPAndQueriesWalletOnce(t *testing.T) { if len(records) != 1 { t.Fatalf("joined direct IM record mismatch: %+v", records) } + if records[0].GetAppCode() != vipTestAppCode { + t.Fatalf("joined direct IM must inherit request app: got=%q want=%q", records[0].GetAppCode(), vipTestAppCode) + } var joined roomeventsv1.RoomUserJoined if err := proto.Unmarshal(records[0].GetBody(), &joined); err != nil { t.Fatalf("decode joined event failed: %v", err) @@ -118,7 +121,7 @@ func TestTieredVIPCustomRoomBackgroundRequiresEffectiveBenefit(t *testing.T) { Meta: vipRoomMeta(roomID, ownerID, "save-denied"), RoomId: roomID, ImageUrl: "https://cdn.example.com/fami-vip-denied.png", - }); !xerr.IsCode(err, xerr.PermissionDenied) { + }); !xerr.IsCode(err, xerr.VIPBenefitRequired) { t.Fatalf("tiered app without custom_room_background must be denied: %v", err) } @@ -136,7 +139,7 @@ func TestTieredVIPCustomRoomBackgroundRequiresEffectiveBenefit(t *testing.T) { if _, err := svc.SetRoomBackground(ctx, &roomv1.SetRoomBackgroundRequest{ Meta: vipRoomMeta(roomID, ownerID, "set-denied"), BackgroundId: second.GetBackgroundId(), - }); !xerr.IsCode(err, xerr.PermissionDenied) { + }); !xerr.IsCode(err, xerr.VIPBenefitRequired) { t.Fatalf("expired custom_room_background benefit must block later set: %v", err) } } @@ -161,13 +164,13 @@ func TestVIPModerationProtectionBlocksRoomManagersButNotSystemEvict(t *testing.T Meta: vipRoomMeta(roomID, ownerID, "mute"), TargetUserId: targetID, Muted: true, - }); !xerr.IsCode(err, xerr.PermissionDenied) { + }); !xerr.IsCode(err, xerr.VIPAntiMute) { t.Fatalf("anti_mute must block ordinary room owner: %v", err) } if _, err := svc.KickUser(ctx, &roomv1.KickUserRequest{ Meta: vipRoomMeta(roomID, ownerID, "kick"), TargetUserId: targetID, - }); !xerr.IsCode(err, xerr.PermissionDenied) { + }); !xerr.IsCode(err, xerr.VIPAntiKick) { t.Fatalf("anti_kick must block ordinary room owner: %v", err) } diff --git a/services/room-service/internal/storage/mysql/command_log_test.go b/services/room-service/internal/storage/mysql/command_log_test.go index 9c25935e..c6a43c82 100644 --- a/services/room-service/internal/storage/mysql/command_log_test.go +++ b/services/room-service/internal/storage/mysql/command_log_test.go @@ -6,12 +6,61 @@ import ( "errors" "sync" "testing" + "time" + "google.golang.org/protobuf/proto" + roomeventsv1 "hyapp.local/api/proto/events/room/v1" "hyapp/internal/testutil/mysqlschema" "hyapp/pkg/appcode" + "hyapp/services/room-service/internal/room/outbox" roomservice "hyapp/services/room-service/internal/room/service" ) +func TestSaveMutationScopesBuiltOutboxToContextApp(t *testing.T) { + ctx := appcode.WithContext(context.Background(), "fami") + repo := newCommandLogTestRepository(t, ctx) + record, err := outbox.Build("fami-room-outbox", "RoomCreated", 1, time.UnixMilli(1000), &roomeventsv1.RoomCreated{}) + if err != nil { + t.Fatalf("build room outbox: %v", err) + } + if record.AppCode != "" || record.Envelope.GetAppCode() != "" { + t.Fatalf("context-free Build must not guess an app: record=%q envelope=%q", record.AppCode, record.Envelope.GetAppCode()) + } + + if err := repo.SaveMutation(ctx, roomservice.MutationCommit{ + Command: roomservice.CommandRecord{ + RoomID: record.RoomID, + RoomVersion: 1, + CommandID: "cmd-fami-room-outbox", + CommandType: "create_room", + Payload: []byte(`{"command_id":"cmd-fami-room-outbox"}`), + Replayable: true, + OwnerNodeID: "node-fami", + LeaseToken: "lease-fami", + CreatedAtMS: record.CreatedAtMS, + }, + OutboxRecords: []outbox.Record{record}, + }); err != nil { + t.Fatalf("save fami mutation: %v", err) + } + + var storedApp string + var envelopeBytes []byte + if err := repo.db.QueryRowContext(ctx, + `SELECT app_code, envelope FROM room_outbox WHERE app_code = ? AND event_id = ?`, + "fami", record.EventID, + ).Scan(&storedApp, &envelopeBytes); err != nil { + t.Fatalf("read persisted fami outbox: %v", err) + } + var envelope roomeventsv1.EventEnvelope + if err := proto.Unmarshal(envelopeBytes, &envelope); err != nil { + t.Fatalf("decode persisted fami envelope: %v", err) + } + if storedApp != "fami" || envelope.GetAppCode() != "fami" { + t.Fatalf("persistence boundary lost scoped app: row=%q envelope=%q", storedApp, envelope.GetAppCode()) + } +} + func TestSaveMutationRejectsSameCommandInsteadOfContinuingSideEffects(t *testing.T) { ctx := appcode.WithContext(context.Background(), appcode.Default) repo := newCommandLogTestRepository(t, ctx) diff --git a/services/room-service/internal/storage/mysql/outbox_retention_test.go b/services/room-service/internal/storage/mysql/outbox_retention_test.go index 124d2d51..e1673b60 100644 --- a/services/room-service/internal/storage/mysql/outbox_retention_test.go +++ b/services/room-service/internal/storage/mysql/outbox_retention_test.go @@ -3,13 +3,53 @@ package mysql import ( "context" "testing" + "time" + "google.golang.org/protobuf/proto" roomeventsv1 "hyapp.local/api/proto/events/room/v1" "hyapp/internal/testutil/mysqlschema" "hyapp/pkg/appcode" "hyapp/services/room-service/internal/room/outbox" ) +func TestSaveOutboxScopesBuiltRecordToContextApp(t *testing.T) { + schema := mysqlschema.New(t, mysqlschema.Config{ + EnvVar: "ROOM_SERVICE_MYSQL_TEST_DSN", + InitDBPath: mysqlschema.InitDBPath(t, mysqlschema.CallerFile(t, 1), "..", "..", "..", "deploy", "mysql", "initdb", "001_room_service.sql"), + DatabasePrefix: "hyapp_room_outbox_scope_test", + }) + ctx := appcode.WithContext(context.Background(), "huwaa") + repo, err := Open(ctx, schema.DSN, 4, 4) + if err != nil { + t.Fatalf("open repository: %v", err) + } + defer repo.Close() + + record, err := outbox.Build("huwaa-room-outbox", "RoomUserJoined", 9, time.UnixMilli(2000), &roomeventsv1.RoomUserJoined{UserId: 99}) + if err != nil { + t.Fatalf("build room outbox: %v", err) + } + if err := repo.SaveOutbox(ctx, []outbox.Record{record}); err != nil { + t.Fatalf("save scoped outbox: %v", err) + } + + var storedApp string + var envelopeBytes []byte + if err := schema.DB.QueryRowContext(ctx, + `SELECT app_code, envelope FROM room_outbox WHERE app_code = ? AND event_id = ?`, + "huwaa", record.EventID, + ).Scan(&storedApp, &envelopeBytes); err != nil { + t.Fatalf("read scoped outbox: %v", err) + } + var envelope roomeventsv1.EventEnvelope + if err := proto.Unmarshal(envelopeBytes, &envelope); err != nil { + t.Fatalf("decode scoped outbox envelope: %v", err) + } + if storedApp != "huwaa" || envelope.GetAppCode() != "huwaa" { + t.Fatalf("SaveOutbox lost scoped app: row=%q envelope=%q", storedApp, envelope.GetAppCode()) + } +} + func retentionTestRecord(eventID string, createdAtMS int64) outbox.Record { return outbox.Record{ AppCode: appcode.Default, diff --git a/services/statistics-service/Dockerfile b/services/statistics-service/Dockerfile index 5ec4ea09..63a4f396 100644 --- a/services/statistics-service/Dockerfile +++ b/services/statistics-service/Dockerfile @@ -15,13 +15,17 @@ COPY . . RUN --mount=type=cache,id=hyapp-go-mod,target=/go/pkg/mod \ --mount=type=cache,id=hyapp-go-build,target=/root/.cache/go-build \ mkdir -p /out && \ - GOWORK=off CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /out/ ./services/statistics-service/cmd/server + GOWORK=off CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /out/server ./services/statistics-service/cmd/server && \ + GOWORK=off CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /out/backfill-social-identities ./services/statistics-service/cmd/backfill-social-identities FROM alpine:3.20 ENV TZ=UTC WORKDIR /app RUN apk add --no-cache ca-certificates wget && adduser -D -g '' appuser COPY --from=builder /out/server /app/server +# 历史身份回放只随 statistics 镜像交付,不开放 HTTP;生产由单节点 +# docker exec 显式 dry-run/apply,复用容器内只读配置与最小连接数保护。 +COPY --from=builder /out/backfill-social-identities /app/backfill-social-identities COPY services/statistics-service/configs/config.docker.yaml /app/config.yaml USER appuser EXPOSE 13110 diff --git a/services/statistics-service/cmd/backfill-social-identities/main.go b/services/statistics-service/cmd/backfill-social-identities/main.go new file mode 100644 index 00000000..2b9f83e5 --- /dev/null +++ b/services/statistics-service/cmd/backfill-social-identities/main.go @@ -0,0 +1,356 @@ +package main + +import ( + "context" + "database/sql" + "flag" + "fmt" + "log" + "os" + "sort" + "strings" + "time" + + "hyapp/pkg/appcode" + statisticsconfig "hyapp/services/statistics-service/internal/config" + + _ "github.com/go-sql-driver/mysql" +) + +const ( + legacyDayResolutionSource = "legacy_day_unique" + legacyWindowResolutionSource = "legacy_window_unique" + legacyAmbiguousResolutionSource = "legacy_ambiguous" +) + +type replayWindow struct { + start time.Time + end time.Time + loc *time.Location +} + +type deviceResolution struct { + userID int64 + ambiguous bool +} + +type dayResolution struct { + deviceID string + userID int64 + state string + source string +} + +type daySummary struct { + day string + anonymous int + resolved int + ambiguous int + unresolved int +} + +func main() { + var ( + appsValue = flag.String("apps", envDefault("APP_CODES", "lalu,huwaa,fami"), "comma-separated app_code list") + statTZ = flag.String("timezone", envDefault("STAT_TZ", "Asia/Shanghai"), "UTC or Asia/Shanghai") + startDay = flag.String("start-day", "", "inclusive day, yyyy-mm-dd") + endDay = flag.String("end-day", "", "inclusive day, yyyy-mm-dd") + apply = flag.Bool("apply", false, "write identity resolutions; default is dry-run") + configPath = flag.String("config", envDefault("STATISTICS_CONFIG", "/app/config.yaml"), "statistics-service YAML used when no DSN flag/env is set") + dsn = flag.String("statistics-dsn", firstNonEmptyEnv("STATISTICS_MYSQL_DSN", "MYSQL_DSN"), "statistics MySQL DSN") + pause = flag.Duration("pause", 250*time.Millisecond, "pause between bounded day queries") + slicePause = flag.Duration("slice-pause", 50*time.Millisecond, "pause after each one-hour raw scan") + queryLimit = flag.Duration("query-timeout", 30*time.Second, "timeout for each bounded query or day transaction") + maxOpenConn = flag.Int("max-open-conns", 1, "small connection cap for production-safe backfill") + receivedCutoff = flag.Int64("received-before-ms", time.Now().UTC().UnixMilli(), "only use raw events received at or before this fixed cutoff") + allowWindowFallback = flag.Bool("allow-window-fallback", false, "allow cross-day unique device inference; unsafe by default for legacy shared devices") + ) + flag.Parse() + + apps := normalizeApps(*appsValue) + dsnValue := strings.TrimSpace(*dsn) + if dsnValue == "" { + cfg, err := statisticsconfig.Load(strings.TrimSpace(*configPath)) + if err != nil { + log.Fatalf("load statistics config: %v", err) + } + dsnValue = strings.TrimSpace(cfg.MySQLDSN) + } + if len(apps) == 0 || dsnValue == "" { + log.Fatal("apps and statistics MySQL DSN are required") + } + window, err := resolveWindow(*startDay, *endDay, *statTZ) + if err != nil { + log.Fatal(err) + } + db, err := sql.Open("mysql", dsnValue) + if err != nil { + log.Fatal(err) + } + defer db.Close() + if *maxOpenConn < 1 { + *maxOpenConn = 1 + } + db.SetMaxOpenConns(*maxOpenConn) + db.SetMaxIdleConns(1) + db.SetConnMaxLifetime(5 * time.Minute) + ctx, cancel := context.WithTimeout(context.Background(), *queryLimit) + if err := db.PingContext(ctx); err != nil { + cancel() + log.Fatal(err) + } + cancel() + fmt.Printf("identity backfill cutoff received_before_ms=%d (%s)\n", *receivedCutoff, time.UnixMilli(*receivedCutoff).UTC().Format(time.RFC3339)) + + for _, app := range apps { + if err := backfillApp(db, app, *statTZ, window, *receivedCutoff, *allowWindowFallback, *apply, *pause, *slicePause, *queryLimit); err != nil { + log.Fatalf("app=%s: %v", app, err) + } + } +} + +func backfillApp(db *sql.DB, app, statTZ string, window replayWindow, receivedCutoff int64, allowWindowFallback, apply bool, pause, slicePause, queryLimit time.Duration) error { + windowDeviceUsers := map[string]deviceResolution{} + dayDeviceUsers := map[string]map[string]deviceResolution{} + for day := window.start; !day.After(window.end); day = day.AddDate(0, 0, 1) { + dayText := day.Format("2006-01-02") + dayDeviceUsers[dayText] = map[string]deviceResolution{} + // One-hour slices cap every index range even on the peak day. All + // authenticated event names participate: an account that only emitted + // page_open must still disqualify a shared device from "unique" mapping. + for hour := day; hour.Before(day.AddDate(0, 0, 1)); hour = hour.Add(time.Hour) { + if err := loadLoggedIdentitySlice(db, app, hour.UnixMilli(), hour.Add(time.Hour).UnixMilli(), receivedCutoff, + dayDeviceUsers[dayText], windowDeviceUsers, queryLimit); err != nil { + return fmt.Errorf("load logged identities day=%s hour=%s: %w", dayText, hour.Format("15:04"), err) + } + pauseFor(slicePause) + } + pauseFor(pause) + } + + for day := window.start; !day.After(window.end); day = day.AddDate(0, 0, 1) { + dayText := day.Format("2006-01-02") + resolutions, summary, err := planDay(db, app, statTZ, dayText, dayDeviceUsers[dayText], windowDeviceUsers, allowWindowFallback, queryLimit) + if err != nil { + return err + } + mode := "dry-run" + if apply { + mode = "applied" + if err := applyDay(db, app, statTZ, dayText, resolutions, queryLimit); err != nil { + return err + } + } + fmt.Printf("%s app=%s stat_tz=%s day=%s anonymous=%d resolved=%d ambiguous=%d unresolved=%d\n", + mode, app, statTZ, summary.day, summary.anonymous, summary.resolved, summary.ambiguous, summary.unresolved) + pauseFor(pause) + } + return nil +} + +func loadLoggedIdentitySlice(db *sql.DB, app string, startMS, endMS, receivedCutoff int64, dayUsers, windowUsers map[string]deviceResolution, queryLimit time.Duration) error { + ctx, cancel := context.WithTimeout(context.Background(), queryLimit) + defer cancel() + rows, err := db.QueryContext(ctx, ` + SELECT device_id, user_id + FROM app_tracking_events FORCE INDEX (idx_app_tracking_time_window) + WHERE app_code = ? AND occurred_at_ms >= ? AND occurred_at_ms < ? AND received_at_ms <= ? + AND device_id <> '' AND user_id > 0 + `, app, startMS, endMS, receivedCutoff) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + var deviceID string + var userID int64 + if err := rows.Scan(&deviceID, &userID); err != nil { + return err + } + deviceID = strings.TrimSpace(deviceID) + if deviceID == "" || userID <= 0 { + continue + } + addDeviceUser(dayUsers, deviceID, userID) + addDeviceUser(windowUsers, deviceID, userID) + } + return rows.Err() +} + +func addDeviceUser(target map[string]deviceResolution, deviceID string, userID int64) { + current, exists := target[deviceID] + if !exists { + target[deviceID] = deviceResolution{userID: userID} + return + } + if current.ambiguous || current.userID == userID { + return + } + current.ambiguous = true + current.userID = 0 + target[deviceID] = current +} + +func planDay(db *sql.DB, app, statTZ, day string, dayUsers, windowUsers map[string]deviceResolution, allowWindowFallback bool, queryLimit time.Duration) ([]dayResolution, daySummary, error) { + ctx, cancel := context.WithTimeout(context.Background(), queryLimit) + defer cancel() + rows, err := db.QueryContext(ctx, ` + SELECT device_id + FROM stat_social_user_day + WHERE app_code = ? AND stat_tz = ? AND stat_day = ? + AND user_id = 0 AND device_id <> '' + ORDER BY device_id + `, app, statTZ, day) + if err != nil { + return nil, daySummary{}, fmt.Errorf("load anonymous devices day=%s: %w", day, err) + } + defer rows.Close() + summary := daySummary{day: day} + resolutions := []dayResolution{} + for rows.Next() { + var deviceID string + if err := rows.Scan(&deviceID); err != nil { + return nil, daySummary{}, err + } + summary.anonymous++ + identity, ok := dayUsers[deviceID] + switch { + case ok && (identity.ambiguous || identity.userID <= 0): + summary.ambiguous++ + resolutions = append(resolutions, dayResolution{deviceID: deviceID, state: "ambiguous", source: legacyAmbiguousResolutionSource}) + case ok: + summary.resolved++ + resolutions = append(resolutions, dayResolution{deviceID: deviceID, userID: identity.userID, state: "resolved", source: legacyDayResolutionSource}) + default: + if !allowWindowFallback { + summary.unresolved++ + continue + } + identity, ok = windowUsers[deviceID] + if !ok { + summary.unresolved++ + continue + } + if identity.ambiguous || identity.userID <= 0 { + summary.ambiguous++ + resolutions = append(resolutions, dayResolution{deviceID: deviceID, state: "ambiguous", source: legacyAmbiguousResolutionSource}) + continue + } + // Cross-day unique fallback repairs the exact retention gap where day 1 + // was anonymous and the same device first authenticated on day 2. It is + // never used if the device showed more than one account in the window. + summary.resolved++ + resolutions = append(resolutions, dayResolution{deviceID: deviceID, userID: identity.userID, state: "resolved", source: legacyWindowResolutionSource}) + } + } + return resolutions, summary, rows.Err() +} + +func applyDay(db *sql.DB, app, statTZ, day string, resolutions []dayResolution, queryLimit time.Duration) error { + ctx, cancel := context.WithTimeout(context.Background(), queryLimit) + defer cancel() + tx, err := db.BeginTx(ctx, nil) + if err != nil { + return err + } + defer tx.Rollback() + // Only rows produced by this legacy job are replaced. Realtime client-session + // evidence has higher authority and must survive an idempotent historical rerun. + if _, err := tx.ExecContext(ctx, ` + DELETE FROM stat_social_identity_day + WHERE app_code = ? AND stat_tz = ? AND stat_day = ? + AND resolution_source IN (?, ?, ?) + `, app, statTZ, day, legacyDayResolutionSource, legacyWindowResolutionSource, legacyAmbiguousResolutionSource); err != nil { + return err + } + stmt, err := tx.PrepareContext(ctx, ` + INSERT INTO stat_social_identity_day ( + app_code, stat_tz, stat_day, device_id, resolved_user_id, + resolution_state, resolution_source, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + resolved_user_id = IF(resolution_source = 'client_session', resolved_user_id, VALUES(resolved_user_id)), + resolution_state = IF(resolution_source = 'client_session', resolution_state, VALUES(resolution_state)), + resolution_source = IF(resolution_source = 'client_session', resolution_source, VALUES(resolution_source)), + updated_at_ms = IF(resolution_source = 'client_session', updated_at_ms, VALUES(updated_at_ms)) + `) + if err != nil { + return err + } + defer stmt.Close() + nowMS := time.Now().UTC().UnixMilli() + for _, resolution := range resolutions { + if _, err := stmt.ExecContext(ctx, app, statTZ, day, resolution.deviceID, resolution.userID, + resolution.state, resolution.source, nowMS); err != nil { + return err + } + } + return tx.Commit() +} + +func resolveWindow(startDay, endDay, statTZ string) (replayWindow, error) { + var loc *time.Location + switch strings.TrimSpace(statTZ) { + case "UTC": + loc = time.UTC + case "Asia/Shanghai": + loc = time.FixedZone("Asia/Shanghai", 8*60*60) + default: + return replayWindow{}, fmt.Errorf("unsupported timezone %q", statTZ) + } + start, err := time.ParseInLocation("2006-01-02", strings.TrimSpace(startDay), loc) + if err != nil { + return replayWindow{}, fmt.Errorf("parse start-day: %w", err) + } + end, err := time.ParseInLocation("2006-01-02", strings.TrimSpace(endDay), loc) + if err != nil { + return replayWindow{}, fmt.Errorf("parse end-day: %w", err) + } + if end.Before(start) { + return replayWindow{}, fmt.Errorf("end-day is before start-day") + } + if days := int(end.Sub(start).Hours()/24) + 1; days > 31 { + return replayWindow{}, fmt.Errorf("window has %d days; maximum is 31", days) + } + return replayWindow{start: start, end: end, loc: loc}, nil +} + +func normalizeApps(value string) []string { + seen := map[string]struct{}{} + apps := []string{} + for _, item := range strings.Split(value, ",") { + app := appcode.Normalize(item) + if app == "" { + continue + } + if _, ok := seen[app]; ok { + continue + } + seen[app] = struct{}{} + apps = append(apps, app) + } + sort.Strings(apps) + return apps +} + +func pauseFor(pause time.Duration) { + if pause > 0 { + time.Sleep(pause) + } +} + +func envDefault(key, fallback string) string { + if value := strings.TrimSpace(os.Getenv(key)); value != "" { + return value + } + return fallback +} + +func firstNonEmptyEnv(keys ...string) string { + for _, key := range keys { + if value := strings.TrimSpace(os.Getenv(key)); value != "" { + return value + } + } + return "" +} 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 0b87eccc..b9093454 100644 --- a/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql +++ b/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql @@ -28,7 +28,9 @@ CREATE TABLE IF NOT EXISTS app_tracking_events ( user_id BIGINT NOT NULL DEFAULT 0 COMMENT '服务端识别的用户 ID,匿名为 0', device_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '设备 ID', identity_key VARCHAR(160) GENERATED ALWAYS AS (CASE WHEN user_id > 0 THEN CONCAT('u:', user_id) ELSE CONCAT('d:', device_id) END) VIRTUAL COMMENT '漏斗/留存去重身份,登录用户优先 user_id,匿名用户回退 device_id', - session_id VARCHAR(160) NOT NULL DEFAULT '' COMMENT '会话 ID', + session_id VARCHAR(160) NOT NULL DEFAULT '' COMMENT '兼容会话 ID', + client_session_id VARCHAR(160) NOT NULL DEFAULT '' COMMENT 'App 进程会话 ID,登录前后保持不变', + auth_session_id VARCHAR(160) NOT NULL DEFAULT '' COMMENT '服务端认证会话 ID', platform VARCHAR(32) NOT NULL DEFAULT '' COMMENT '平台', app_version VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'App 版本', language VARCHAR(32) NOT NULL DEFAULT '' COMMENT '语言', @@ -205,6 +207,49 @@ CREATE TABLE IF NOT EXISTS stat_social_user_day ( KEY idx_stat_social_user_day_filter (app_code, stat_tz, stat_day, user_role, recharge_user) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Social BI P0-P5 用户日级读模型'; +CREATE TABLE IF NOT EXISTS stat_social_identity_session_user ( + app_code VARCHAR(32) NOT NULL, + device_id VARCHAR(128) COLLATE utf8mb4_bin NOT NULL, + client_session_id VARCHAR(160) COLLATE utf8mb4_bin NOT NULL, + user_id BIGINT NOT NULL, + first_seen_at_ms BIGINT NOT NULL, + updated_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, device_id, client_session_id, user_id), + KEY idx_social_identity_session_user (app_code, user_id, first_seen_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Social 客户端会话登录账号观测表'; + +CREATE TABLE IF NOT EXISTS stat_social_identity_device_lock ( + app_code VARCHAR(32) NOT NULL, + device_id VARCHAR(128) COLLATE utf8mb4_bin NOT NULL, + created_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, device_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Social 身份解析设备级事务锁'; + +CREATE TABLE IF NOT EXISTS stat_social_identity_session_day ( + app_code VARCHAR(32) NOT NULL, + stat_tz VARCHAR(64) NOT NULL, + stat_day DATE NOT NULL, + device_id VARCHAR(128) COLLATE utf8mb4_bin NOT NULL, + client_session_id VARCHAR(160) COLLATE utf8mb4_bin NOT NULL, + first_seen_at_ms BIGINT NOT NULL, + updated_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, device_id, client_session_id, stat_tz, stat_day), + KEY idx_social_identity_session_day (app_code, stat_tz, stat_day, device_id, client_session_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Social 匿名会话活跃日观测表'; + +CREATE TABLE IF NOT EXISTS stat_social_identity_day ( + app_code VARCHAR(32) NOT NULL, + stat_tz VARCHAR(64) NOT NULL, + stat_day DATE NOT NULL, + device_id VARCHAR(128) COLLATE utf8mb4_bin NOT NULL, + resolved_user_id BIGINT NOT NULL DEFAULT 0, + resolution_state VARCHAR(16) NOT NULL DEFAULT 'unresolved', + resolution_source VARCHAR(32) NOT NULL DEFAULT 'client_session', + updated_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, stat_tz, stat_day, device_id), + KEY idx_social_identity_day_user (app_code, stat_tz, stat_day, resolved_user_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Social 设备日级 canonical 身份解析表'; + CREATE TABLE IF NOT EXISTS stat_recharge_day_payers ( app_code VARCHAR(32) NOT NULL, stat_tz VARCHAR(64) NOT NULL DEFAULT 'UTC' COMMENT '统计时区,UTC 或 Asia/Shanghai', diff --git a/services/statistics-service/internal/app/activity_template_flow_test.go b/services/statistics-service/internal/app/activity_template_flow_test.go index 42a3c49c..1bc95a56 100644 --- a/services/statistics-service/internal/app/activity_template_flow_test.go +++ b/services/statistics-service/internal/app/activity_template_flow_test.go @@ -47,6 +47,20 @@ func TestActivityTemplateDataHTTPRejectsPartialUTCDay(t *testing.T) { } } +func TestSocialRequirementsHTTPRejectsBaseRangeOver31Days(t *testing.T) { + start := time.Date(2026, time.July, 1, 0, 0, 0, 0, time.UTC) + request := httptest.NewRequest(http.MethodGet, fmt.Sprintf( + "/internal/v1/statistics/social/requirements?app_code=lalu§ion=retention&start_ms=%d&end_ms=%d", + start.UnixMilli(), start.AddDate(0, 0, 32).UnixMilli(), + ), nil) + response := httptest.NewRecorder() + // nil repo proves the range guard rejects the request before any database query. + (&queryHTTPServer{}).socialRequirements(response, request) + if response.Code != http.StatusBadRequest || !strings.Contains(response.Body.String(), "at most 31 days") { + t.Fatalf("unexpected over-range response: status=%d body=%s", response.Code, response.Body.String()) + } +} + func TestActivityTemplateMQProjectionAndQueryHTTPAreIdempotent(t *testing.T) { ctx := context.Background() _, file, _, _ := runtime.Caller(0) diff --git a/services/statistics-service/internal/app/query_http.go b/services/statistics-service/internal/app/query_http.go index b611d40f..46c00cb9 100644 --- a/services/statistics-service/internal/app/query_http.go +++ b/services/statistics-service/internal/app/query_http.go @@ -21,6 +21,8 @@ type queryHTTPServer struct { listener net.Listener } +const socialRequirementsMaxBaseRange = 31 * 24 * time.Hour + func newQueryHTTPServer(addr string, repo *mysqlstorage.Repository) (*queryHTTPServer, error) { addr = strings.TrimSpace(addr) if addr == "" { @@ -225,6 +227,12 @@ func (s *queryHTTPServer) socialRequirements(w http.ResponseWriter, r *http.Requ if endMS <= startMS { endMS = startMS + 24*time.Hour.Milliseconds() } + // 留存最多还会向后读取 30 天观察窗;限制基准区间可以把单次扫描稳定 + // 控制在最多 61 个用户日分区,避免自定义超长时间范围压垮线上 MySQL。 + if endMS-startMS > socialRequirementsMaxBaseRange.Milliseconds() { + writeJSON(w, http.StatusBadRequest, map[string]any{"error": "start_ms and end_ms must span at most 31 days"}) + return + } requirements, err := s.repo.QuerySocialRequirements(r.Context(), mysqlstorage.SocialRequirementsQuery{ AppCode: query.Get("app_code"), StatTZ: query.Get("stat_tz"), @@ -286,27 +294,29 @@ type socialCoinSellerRechargeOrderRequest struct { } type appTrackingEventRequest struct { - AppCode string `json:"app_code"` - EventID string `json:"event_id"` - EventName string `json:"event_name"` - EventType string `json:"event_type"` - Screen string `json:"screen"` - TargetType string `json:"target_type"` - TargetID string `json:"target_id"` - UserID int64 `json:"user_id"` - DeviceID string `json:"device_id"` - SessionID string `json:"session_id"` - Platform string `json:"platform"` - AppVersion string `json:"app_version"` - Language string `json:"language"` - Timezone string `json:"timezone"` - CountryID int64 `json:"country_id"` - RegionID int64 `json:"region_id"` - DurationMS int64 `json:"duration_ms"` - Success bool `json:"success"` - ErrorCode string `json:"error_code"` - Properties json.RawMessage `json:"properties"` - OccurredAtMS int64 `json:"occurred_at_ms"` + AppCode string `json:"app_code"` + EventID string `json:"event_id"` + EventName string `json:"event_name"` + EventType string `json:"event_type"` + Screen string `json:"screen"` + TargetType string `json:"target_type"` + TargetID string `json:"target_id"` + UserID int64 `json:"user_id"` + DeviceID string `json:"device_id"` + SessionID string `json:"session_id"` + ClientSessionID string `json:"client_session_id"` + AuthSessionID string `json:"auth_session_id"` + Platform string `json:"platform"` + AppVersion string `json:"app_version"` + Language string `json:"language"` + Timezone string `json:"timezone"` + CountryID int64 `json:"country_id"` + RegionID int64 `json:"region_id"` + DurationMS int64 `json:"duration_ms"` + Success bool `json:"success"` + ErrorCode string `json:"error_code"` + Properties json.RawMessage `json:"properties"` + OccurredAtMS int64 `json:"occurred_at_ms"` } func (s *queryHTTPServer) socialCoinSellerRechargeOrder(w http.ResponseWriter, r *http.Request) { @@ -375,27 +385,29 @@ func (s *queryHTTPServer) appEvents(w http.ResponseWriter, r *http.Request) { for _, item := range body.Events { // Internal ingest 只接受 gateway 已解析过的 App、用户和维度;statistics-service 只负责幂等落表,不回查 owner service。 events = append(events, mysqlstorage.AppTrackingEvent{ - AppCode: appcode.Normalize(item.AppCode), - EventID: item.EventID, - EventName: item.EventName, - EventType: item.EventType, - Screen: item.Screen, - TargetType: item.TargetType, - TargetID: item.TargetID, - UserID: item.UserID, - DeviceID: item.DeviceID, - SessionID: item.SessionID, - Platform: item.Platform, - AppVersion: item.AppVersion, - Language: item.Language, - Timezone: item.Timezone, - CountryID: item.CountryID, - RegionID: item.RegionID, - DurationMS: item.DurationMS, - Success: item.Success, - ErrorCode: item.ErrorCode, - Properties: item.Properties, - OccurredAtMS: item.OccurredAtMS, + AppCode: appcode.Normalize(item.AppCode), + EventID: item.EventID, + EventName: item.EventName, + EventType: item.EventType, + Screen: item.Screen, + TargetType: item.TargetType, + TargetID: item.TargetID, + UserID: item.UserID, + DeviceID: item.DeviceID, + SessionID: item.SessionID, + ClientSessionID: item.ClientSessionID, + AuthSessionID: item.AuthSessionID, + Platform: item.Platform, + AppVersion: item.AppVersion, + Language: item.Language, + Timezone: item.Timezone, + CountryID: item.CountryID, + RegionID: item.RegionID, + DurationMS: item.DurationMS, + Success: item.Success, + ErrorCode: item.ErrorCode, + Properties: item.Properties, + OccurredAtMS: item.OccurredAtMS, }) } result, err := s.repo.ConsumeAppTrackingEvents(r.Context(), events) diff --git a/services/statistics-service/internal/storage/mysql/query.go b/services/statistics-service/internal/storage/mysql/query.go index 44cedec5..a16305b6 100644 --- a/services/statistics-service/internal/storage/mysql/query.go +++ b/services/statistics-service/internal/storage/mysql/query.go @@ -573,6 +573,20 @@ func (r *Repository) QueryOverview(ctx context.Context, query OverviewQuery) (Ov if err != nil { return Overview{}, err } + // Revenue and business counts remain on stat_app_day_country, but every DAU + // value and DAU-derived denominator must come from the same canonical Social + // user-day source. Load current and previous windows before deriving ratios + // so deltas cannot compare canonical current data with legacy previous data. + activeCube, err := r.queryCanonicalOverviewActiveCube(ctx, app, statTZ, startDay, endDay, query.CountryID, query.RegionID) + if err != nil { + return Overview{}, err + } + previousActiveCube, err := r.queryCanonicalOverviewActiveCube(ctx, app, statTZ, previousStartDay, previousEndDay, query.CountryID, query.RegionID) + if err != nil { + return Overview{}, err + } + overview.ActiveUsers = activeCube.Total + previous.ActiveUsers = previousActiveCube.Total overview.AppCode, overview.StatTZ, overview.StartMS, overview.EndMS, overview.CountryID = app, statTZ, query.StartMS, query.EndMS, query.CountryID previous.AppCode, previous.StatTZ, previous.CountryID = app, statTZ, query.CountryID // 新增付费用户来自日充值用户去重表和注册表的交集;只读聚合小表,避免 Databi 页面回扫钱包或订单明细。 @@ -635,12 +649,12 @@ func (r *Repository) QueryOverview(ctx context.Context, query OverviewQuery) (Ov } overview.GameRanking = ranking if query.CountryID <= 0 { - breakdown, err := r.queryCountryBreakdown(ctx, app, statTZ, startDay, endDay, query.RegionID, retentionCube.ByCountry) + breakdown, err := r.queryCountryBreakdown(ctx, app, statTZ, startDay, endDay, query.RegionID, retentionCube.ByCountry, activeCube) if err != nil { return Overview{}, err } overview.CountryBreakdown = breakdown - dailyCountryBreakdown, err := r.queryDailyCountryBreakdown(ctx, app, statTZ, startDay, endDay, query.RegionID, retentionCube.ByDayCountry) + dailyCountryBreakdown, err := r.queryDailyCountryBreakdown(ctx, app, statTZ, startDay, endDay, query.RegionID, retentionCube.ByDayCountry, activeCube) if err != nil { return Overview{}, err } @@ -652,15 +666,20 @@ func (r *Repository) QueryOverview(ctx context.Context, query OverviewQuery) (Ov seriesEndDay = statDayIn(query.SeriesEndMS-1, statTZ) } seriesRetentionByDay := retentionCube.ByDay + seriesActiveCube := activeCube if seriesStartDay != startDay || seriesEndDay != endDay { seriesRetentionCube, err := r.queryRetentionCube(ctx, app, statTZ, seriesStartDay, seriesEndDay, query.CountryID, query.RegionID) if err != nil { return Overview{}, err } seriesRetentionByDay = seriesRetentionCube.ByDay + seriesActiveCube, err = r.queryCanonicalOverviewActiveCube(ctx, app, statTZ, seriesStartDay, seriesEndDay, query.CountryID, query.RegionID) + if err != nil { + return Overview{}, err + } } // daily_series 服务卡片内 sparkline 和弹窗折线图;一条 GROUP BY stat_day 查询返回全部指标,避免前端逐日请求。 - dailySeries, err := r.queryDailySeries(ctx, app, statTZ, seriesStartDay, seriesEndDay, query.CountryID, query.RegionID, seriesRetentionByDay) + dailySeries, err := r.queryDailySeries(ctx, app, statTZ, seriesStartDay, seriesEndDay, query.CountryID, query.RegionID, seriesRetentionByDay, seriesActiveCube) if err != nil { return Overview{}, err } @@ -852,7 +871,7 @@ func (r *Repository) queryAppDayOverviewTotals(ctx context.Context, app, statTZ, 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), + SELECT COALESCE(SUM(new_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(coin_seller_stock_coin),0), COALESCE(SUM(mifapay_recharge_usd_minor),0), COALESCE(SUM(google_recharge_usd_minor),0), COALESCE(SUM(coin_seller_transfer_coin),0), @@ -867,7 +886,7 @@ func (r *Repository) queryAppDayOverviewTotals(ctx context.Context, app, statTZ, FROM stat_app_day_country WHERE app_code = ? AND stat_tz = ? 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.CoinSellerStockCoin, &overview.MifaPayRechargeUSDMinor, &overview.GoogleRechargeUSDMinor, &overview.CoinSellerTransferCoin, &overview.CoinTotal, &overview.ConsumedCoin, &overview.OutputCoin, &overview.PlatformGrantCoin, &overview.ManualGrantCoin, &overview.SalaryUSDMinor, &overview.SalaryTransferCoin, &overview.MicOnlineMS, &overview.MicOnlineUsers, &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.PaidUsers, &overview.RechargeUSDMinor, &overview.NewUserRechargeUSDMinor, &overview.CoinSellerRechargeUSDMinor, &overview.CoinSellerStockCoin, &overview.MifaPayRechargeUSDMinor, &overview.GoogleRechargeUSDMinor, &overview.CoinSellerTransferCoin, &overview.CoinTotal, &overview.ConsumedCoin, &overview.OutputCoin, &overview.PlatformGrantCoin, &overview.ManualGrantCoin, &overview.SalaryUSDMinor, &overview.SalaryTransferCoin, &overview.MicOnlineMS, &overview.MicOnlineUsers, &overview.GiftCoinSpent, &overview.LuckyGiftTurnover, &overview.LuckyGiftPayout, &overview.LuckyGiftPayers, &overview.GameTurnover, &overview.GamePayout, &overview.GameRefund, &overview.GamePlayers); err != nil { return Overview{}, err } return overview, nil @@ -925,7 +944,7 @@ func (r *Repository) queryRealRoomRobotGiftOverview(ctx context.Context, app, st return overview, nil } -func (r *Repository) queryDailySeries(ctx context.Context, app, statTZ, startDay, endDay string, countryID int64, regionID int64, retentionByDay map[string]retentionCount) ([]DailySeriesItem, error) { +func (r *Repository) queryDailySeries(ctx context.Context, app, statTZ, startDay, endDay string, countryID int64, regionID int64, retentionByDay map[string]retentionCount, activeCube canonicalOverviewActiveCube) ([]DailySeriesItem, error) { args := []any{app, normalizeStatTZ(statTZ), startDay, endDay} filter := "" if countryID > 0 { @@ -938,7 +957,7 @@ func (r *Repository) queryDailySeries(ctx context.Context, app, statTZ, startDay } 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(new_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(coin_seller_stock_coin),0), COALESCE(SUM(mifapay_recharge_usd_minor),0), COALESCE(SUM(google_recharge_usd_minor),0), COALESCE(SUM(coin_seller_transfer_coin),0), @@ -960,7 +979,7 @@ func (r *Repository) queryDailySeries(ctx context.Context, app, statTZ, startDay 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.CoinSellerStockCoin, &item.MifaPayRechargeUSDMinor, &item.GoogleRechargeUSDMinor, &item.CoinSellerTransferCoin, &item.CoinTotal, &item.ConsumedCoin, &item.OutputCoin, &item.PlatformGrantCoin, &item.ManualGrantCoin, &item.SalaryUSDMinor, &item.SalaryTransferCoin, &item.MicOnlineMS, &item.MicOnlineUsers, &item.GiftCoinSpent, &item.LuckyGiftTurnover, &item.LuckyGiftPayout, &item.GameTurnover, &gamePayout, &gameRefund); err != nil { + if err := rows.Scan(&item.StatDay, &item.NewUsers, &item.PaidUsers, &item.RechargeUSDMinor, &item.NewUserRechargeUSDMinor, &item.CoinSellerRechargeUSDMinor, &item.CoinSellerStockCoin, &item.MifaPayRechargeUSDMinor, &item.GoogleRechargeUSDMinor, &item.CoinSellerTransferCoin, &item.CoinTotal, &item.ConsumedCoin, &item.OutputCoin, &item.PlatformGrantCoin, &item.ManualGrantCoin, &item.SalaryUSDMinor, &item.SalaryTransferCoin, &item.MicOnlineMS, &item.MicOnlineUsers, &item.GiftCoinSpent, &item.LuckyGiftTurnover, &item.LuckyGiftPayout, &item.GameTurnover, &gamePayout, &gameRefund); err != nil { return nil, err } item.Label = item.StatDay @@ -1021,7 +1040,7 @@ func (r *Repository) queryDailySeries(ctx context.Context, app, statTZ, startDay out = mergeActivityLuckyGiftDaily(out, activityDaily) } } - return out, nil + return overlayCanonicalDailyActive(out, activeCube), nil } func (r *Repository) queryDailyNewPaidUsers(ctx context.Context, app, statTZ, startDay, endDay string, countryID int64, regionID int64) (map[string]int64, error) { @@ -1255,6 +1274,28 @@ func applyDailySeriesDerivedMetrics(item *DailySeriesItem) { item.RechargeConversionRate = ratio(item.RechargeUsers, item.ActiveUsers) } +// overlayCanonicalDailyActive makes canonical Social the only DAU source. It +// also creates days that have client activity but no legacy business aggregate, +// then recalculates every metric whose denominator is DAU. +func overlayCanonicalDailyActive(items []DailySeriesItem, cube canonicalOverviewActiveCube) []DailySeriesItem { + indexByDay := make(map[string]int, len(items)) + for index := range items { + indexByDay[items[index].StatDay] = index + items[index].ActiveUsers = cube.ByDay[items[index].StatDay] + } + for day, activeUsers := range cube.ByDay { + if _, ok := indexByDay[day]; ok { + continue + } + items = append(items, DailySeriesItem{StatDay: day, Label: day, ActiveUsers: activeUsers}) + } + for index := range items { + applyDailySeriesDerivedMetrics(&items[index]) + } + sort.SliceStable(items, func(i, j int) bool { return items[i].StatDay < items[j].StatDay }) + return items +} + func applyOverviewDerivedMetrics(overview *Overview) { if overview == nil { return @@ -1345,7 +1386,7 @@ func (r *Repository) queryGameRanking(ctx context.Context, app, statTZ, startDay return out, rows.Err() } -func (r *Repository) queryCountryBreakdown(ctx context.Context, app, statTZ, startDay, endDay string, regionID int64, retentionByCountry map[int64]retentionCount) ([]CountryBreakdown, error) { +func (r *Repository) queryCountryBreakdown(ctx context.Context, app, statTZ, startDay, endDay string, regionID int64, retentionByCountry map[int64]retentionCount, activeCube canonicalOverviewActiveCube) ([]CountryBreakdown, error) { args := []any{endDay, endDay, app, normalizeStatTZ(statTZ), startDay, endDay} filter := "" if regionID > 0 { @@ -1354,7 +1395,7 @@ func (r *Repository) queryCountryBreakdown(ctx context.Context, app, statTZ, sta } 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(new_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(coin_seller_stock_coin),0), COALESCE(SUM(mifapay_recharge_usd_minor),0), COALESCE(SUM(google_recharge_usd_minor),0), COALESCE(SUM(coin_seller_transfer_coin),0), @@ -1369,8 +1410,7 @@ func (r *Repository) queryCountryBreakdown(ctx context.Context, app, statTZ, sta FROM stat_app_day_country WHERE app_code = ? AND stat_tz = ? 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...) + ORDER BY COALESCE(SUM(recharge_usd_minor),0) DESC, country_id ASC`, args...) if err != nil { return nil, err } @@ -1378,7 +1418,7 @@ func (r *Repository) queryCountryBreakdown(ctx context.Context, app, statTZ, sta 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.CoinSellerStockCoin, &item.MifaPayRechargeUSDMinor, &item.GoogleRechargeUSDMinor, &item.CoinSellerTransferCoin, &item.CoinTotal, &item.ConsumedCoin, &item.OutputCoin, &item.PlatformGrantCoin, &item.ManualGrantCoin, &item.SalaryUSDMinor, &item.SalaryTransferCoin, &item.MicOnlineMS, &item.MicOnlineUsers, &item.GiftCoinSpent, &item.LuckyGiftTurnover, &item.LuckyGiftPayout, &item.LuckyGiftPayers, &item.GameTurnover, &item.GamePayout, &item.GameRefund, &item.GamePlayers); err != nil { + if err := rows.Scan(&item.CountryID, &item.RegionID, &item.NewUsers, &item.PaidUsers, &item.RechargeUSDMinor, &item.NewUserRechargeUSDMinor, &item.CoinSellerRechargeUSDMinor, &item.CoinSellerStockCoin, &item.MifaPayRechargeUSDMinor, &item.GoogleRechargeUSDMinor, &item.CoinSellerTransferCoin, &item.CoinTotal, &item.ConsumedCoin, &item.OutputCoin, &item.PlatformGrantCoin, &item.ManualGrantCoin, &item.SalaryUSDMinor, &item.SalaryTransferCoin, &item.MicOnlineMS, &item.MicOnlineUsers, &item.GiftCoinSpent, &item.LuckyGiftTurnover, &item.LuckyGiftPayout, &item.LuckyGiftPayers, &item.GameTurnover, &item.GamePayout, &item.GameRefund, &item.GamePlayers); err != nil { return nil, err } applyCountryBreakdownDerivedMetrics(&item) @@ -1421,10 +1461,10 @@ func (r *Repository) queryCountryBreakdown(ctx context.Context, app, statTZ, sta applyCountryBreakdownDerivedMetrics(&out[index]) } } - return out, nil + return overlayCanonicalCountryActive(out, activeCube), nil } -func (r *Repository) queryDailyCountryBreakdown(ctx context.Context, app, statTZ, startDay, endDay string, regionID int64, retentionByDayCountry map[string]retentionCount) ([]DailyCountryStat, error) { +func (r *Repository) queryDailyCountryBreakdown(ctx context.Context, app, statTZ, startDay, endDay string, regionID int64, retentionByDayCountry map[string]retentionCount, activeCube canonicalOverviewActiveCube) ([]DailyCountryStat, error) { args := []any{app, normalizeStatTZ(statTZ), startDay, endDay} filter := "" if regionID > 0 { @@ -1433,7 +1473,7 @@ func (r *Repository) queryDailyCountryBreakdown(ctx context.Context, app, statTZ } rows, err := r.db.QueryContext(ctx, ` SELECT DATE_FORMAT(stat_day, '%Y-%m-%d'), country_id, COALESCE(MAX(region_id),0), - COALESCE(SUM(new_users),0), COALESCE(SUM(active_users),0), COALESCE(SUM(paid_users),0), + COALESCE(SUM(new_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(coin_seller_stock_coin),0), COALESCE(SUM(mifapay_recharge_usd_minor),0), COALESCE(SUM(google_recharge_usd_minor),0), COALESCE(SUM(coin_seller_transfer_coin),0), @@ -1447,8 +1487,7 @@ func (r *Repository) queryDailyCountryBreakdown(ctx context.Context, app, statTZ FROM stat_app_day_country WHERE app_code = ? AND stat_tz = ? AND stat_day BETWEEN ? AND ?`+filter+` GROUP BY stat_day, country_id - ORDER BY stat_day ASC, COALESCE(SUM(recharge_usd_minor),0) DESC, COALESCE(SUM(active_users),0) DESC, country_id ASC - LIMIT 5000`, args...) + ORDER BY stat_day ASC, COALESCE(SUM(recharge_usd_minor),0) DESC, country_id ASC`, args...) if err != nil { return nil, err } @@ -1456,7 +1495,7 @@ func (r *Repository) queryDailyCountryBreakdown(ctx context.Context, app, statTZ out := []DailyCountryStat{} for rows.Next() { var item DailyCountryStat - if err := rows.Scan(&item.StatDay, &item.CountryID, &item.RegionID, &item.NewUsers, &item.ActiveUsers, &item.PaidUsers, &item.RechargeUSDMinor, &item.NewUserRechargeUSDMinor, &item.CoinSellerRechargeUSDMinor, &item.CoinSellerStockCoin, &item.MifaPayRechargeUSDMinor, &item.GoogleRechargeUSDMinor, &item.CoinSellerTransferCoin, &item.CoinTotal, &item.ConsumedCoin, &item.OutputCoin, &item.PlatformGrantCoin, &item.ManualGrantCoin, &item.SalaryUSDMinor, &item.SalaryTransferCoin, &item.MicOnlineMS, &item.MicOnlineUsers, &item.GiftCoinSpent, &item.LuckyGiftTurnover, &item.LuckyGiftPayout, &item.LuckyGiftPayers, &item.GameTurnover, &item.GamePayout, &item.GameRefund, &item.GamePlayers); err != nil { + if err := rows.Scan(&item.StatDay, &item.CountryID, &item.RegionID, &item.NewUsers, &item.PaidUsers, &item.RechargeUSDMinor, &item.NewUserRechargeUSDMinor, &item.CoinSellerRechargeUSDMinor, &item.CoinSellerStockCoin, &item.MifaPayRechargeUSDMinor, &item.GoogleRechargeUSDMinor, &item.CoinSellerTransferCoin, &item.CoinTotal, &item.ConsumedCoin, &item.OutputCoin, &item.PlatformGrantCoin, &item.ManualGrantCoin, &item.SalaryUSDMinor, &item.SalaryTransferCoin, &item.MicOnlineMS, &item.MicOnlineUsers, &item.GiftCoinSpent, &item.LuckyGiftTurnover, &item.LuckyGiftPayout, &item.LuckyGiftPayers, &item.GameTurnover, &item.GamePayout, &item.GameRefund, &item.GamePlayers); err != nil { return nil, err } item.Label = item.StatDay @@ -1510,7 +1549,7 @@ func (r *Repository) queryDailyCountryBreakdown(ctx context.Context, app, statTZ applyCountryBreakdownDerivedMetrics(&out[index].CountryBreakdown) } } - return out, nil + return overlayCanonicalDailyCountryActive(out, activeCube), nil } func applyCountryBreakdownDerivedMetrics(item *CountryBreakdown) { @@ -1541,6 +1580,129 @@ func applyCountryBreakdownDerivedMetrics(item *CountryBreakdown) { item.SuperLuckyGiftProfitRate = ratio(item.SuperLuckyGiftProfit, item.SuperLuckyGiftTurnover) } +// overlayCanonicalCountryActive preserves monetary and business facts from the +// legacy aggregate while replacing its incomplete activity counter. A +// canonical-only valid countries are added to preserve resolved detail. Unknown-country +// DAU intentionally remains only in the top-level total, so country rows need not sum to it. +func overlayCanonicalCountryActive(items []CountryBreakdown, cube canonicalOverviewActiveCube) []CountryBreakdown { + // 旧聚合表可能仍保存 country_id=0 的金额或历史活跃事实;总览总计会继续包含这些真实事实, + // 但国家明细不能把“未知维度”渲染成一个国家。先过滤旧行,避免 canonical cube 不再产出 0 后仍残留空壳行。 + validItems := items[:0] + for _, item := range items { + if item.CountryID > 0 { + validItems = append(validItems, item) + } + } + items = validItems + + indexByCountry := make(map[int64]int, len(items)) + for index := range items { + indexByCountry[items[index].CountryID] = index + dimension, ok := cube.ByCountry[items[index].CountryID] + items[index].ActiveUsers = 0 + if ok { + items[index].ActiveUsers = dimension.ActiveUsers + items[index].RegionID = dimension.RegionID + } + } + for countryID, dimension := range cube.ByCountry { + if _, ok := indexByCountry[countryID]; ok { + continue + } + items = append(items, CountryBreakdown{ + CountryID: countryID, + RegionID: dimension.RegionID, + ActiveUsers: dimension.ActiveUsers, + }) + } + for index := range items { + applyCountryBreakdownDerivedMetrics(&items[index]) + } + sort.SliceStable(items, func(i, j int) bool { + if items[i].RechargeUSDMinor != items[j].RechargeUSDMinor { + return items[i].RechargeUSDMinor > items[j].RechargeUSDMinor + } + if items[i].ActiveUsers != items[j].ActiveUsers { + return items[i].ActiveUsers > items[j].ActiveUsers + } + return items[i].CountryID < items[j].CountryID + }) + // Keep the existing response bound, but apply it only after canonical-only + // countries have participated in the same ordering as legacy fact rows. + if len(items) > 500 { + items = items[:500] + } + return items +} + +// overlayCanonicalDailyCountryActive is the day×country counterpart of the +// country overlay. It prevents stale legacy DAU from surviving on rows with no +// canonical activity and fills client-only detail rows before final ordering. +func overlayCanonicalDailyCountryActive(items []DailyCountryStat, cube canonicalOverviewActiveCube) []DailyCountryStat { + // 与汇总国家行保持同一边界:未知国家事实只进入 App/日期总计,不作为 day×country 明细返回。 + validItems := items[:0] + for _, item := range items { + if item.CountryID > 0 { + validItems = append(validItems, item) + } + } + items = validItems + + indexByDayCountry := make(map[string]int, len(items)) + for index := range items { + key := dailyCountryKey(items[index].StatDay, items[index].CountryID) + indexByDayCountry[key] = index + dimension, ok := cube.ByDayCountry[key] + items[index].ActiveUsers = 0 + if ok { + items[index].ActiveUsers = dimension.ActiveUsers + items[index].RegionID = dimension.RegionID + } + } + for key, dimension := range cube.ByDayCountry { + if _, ok := indexByDayCountry[key]; ok { + continue + } + separator := strings.LastIndex(key, ":") + if separator <= 0 { + continue + } + countryID, err := strconv.ParseInt(key[separator+1:], 10, 64) + if err != nil { + continue + } + day := key[:separator] + items = append(items, DailyCountryStat{ + StatDay: day, + Label: day, + CountryBreakdown: CountryBreakdown{ + CountryID: countryID, + RegionID: dimension.RegionID, + ActiveUsers: dimension.ActiveUsers, + }, + }) + } + for index := range items { + applyCountryBreakdownDerivedMetrics(&items[index].CountryBreakdown) + } + sort.SliceStable(items, func(i, j int) bool { + if items[i].StatDay != items[j].StatDay { + return items[i].StatDay < items[j].StatDay + } + if items[i].RechargeUSDMinor != items[j].RechargeUSDMinor { + return items[i].RechargeUSDMinor > items[j].RechargeUSDMinor + } + if items[i].ActiveUsers != items[j].ActiveUsers { + return items[i].ActiveUsers > items[j].ActiveUsers + } + return items[i].CountryID < items[j].CountryID + }) + if len(items) > 5000 { + items = items[:5000] + } + return items +} + func (r *Repository) queryLuckyGiftPools(ctx context.Context, app, statTZ, startDay, endDay string, countryID int64, regionID int64) ([]LuckyGiftPoolStat, error) { args := []any{app, normalizeStatTZ(statTZ), startDay, endDay} filter := "" @@ -1817,7 +1979,7 @@ func isSuperLuckyPool(poolID string) bool { func reportMetricSources() []ReportMetricSource { return []ReportMetricSource{ {Key: "new_users", Label: "注册", Status: "available", Source: "UserRegistered", Definition: "统计窗口内完成注册的用户数;registered_users 和 registrations 是同一口径别名。"}, - {Key: "active_users", Label: "活跃用户", Status: "available", Source: "RoomUserJoined / GameOrderSettled", Definition: "统计服务按用户维度去重后的日活,进房和游戏结算都会沉淀为本地活跃事实。"}, + {Key: "active_users", Label: "活跃用户", Status: "available", Source: "stat_social_user_day + stat_social_identity_day", Definition: "Social 用户日宽表先按同一登录会话把匿名设备归并到登录账号,再按 canonical 用户日去重;多日汇总为活跃人天。"}, {Key: "paid_users", Label: "付费用户", Status: "available", Source: "stat_recharge_day_payers", Definition: "统计窗口内发生充值的去重用户数;当前 Lalu 付费用户等同充值用户。"}, {Key: "recharge_users", Label: "充值用户", Status: "available", Source: "stat_recharge_day_payers", Definition: "统计窗口内发生充值的去重用户数;当前 Lalu 由 paid_users 派生。"}, {Key: "recharge_usd_minor", Label: "总充值", Status: "available", Source: "WalletRechargeRecorded", Definition: "所有充值渠道的美元最小单位总额,历史行缺总额时用可拆分渠道合计兜底。"}, @@ -1841,10 +2003,10 @@ func reportMetricSources() []ReportMetricSource { {Key: "salary_transfer_coin", Label: "工资兑换金币", Status: "available", Source: "WalletBalanceChanged biz_type=salary_transfer_to_coin_seller / wallet_transactions", Definition: "用户工资钱包转给币商时,币商 COIN_SELLER_COIN 入账的金币数量;国家/区域按发起转账用户归属。"}, {Key: "avg_mic_online_ms", Label: "平均麦上时间", Status: "available", Source: "user_mic_daily_stats", Definition: "麦上总时长 / 当日麦上用户数,只统计 mic_online_ms > 0 的用户。"}, {Key: "mic_online_ms", Label: "麦上总时长", Status: "available", Source: "user_mic_daily_stats.mic_online_ms", Definition: "用户每日麦上时长按国家/区域聚合后的毫秒总和。"}, - {Key: "arpu_usd_minor", Label: "ARPU", Status: "available", Source: "stat_app_day_country", Definition: "总充值 / 活跃用户,返回美元最小单位。"}, + {Key: "arpu_usd_minor", Label: "ARPU", Status: "available", Source: "stat_app_day_country + canonical Social DAU", Definition: "业务事实总充值 / canonical Social 活跃用户,返回美元最小单位。"}, {Key: "arppu_usd_minor", Label: "ARPPU", Status: "available", Source: "stat_app_day_country", Definition: "总充值 / 付费用户,返回美元最小单位。"}, - {Key: "paid_conversion_rate", Label: "付费转化率", Status: "available", Source: "stat_app_day_country", Definition: "付费用户 / 活跃用户;当前 Lalu 付费用户等同充值用户。"}, - {Key: "recharge_conversion_rate", Label: "充值转化率", Status: "available", Source: "stat_app_day_country", Definition: "充值用户 / 活跃用户;当前 Lalu 充值用户由 paid_users 派生。"}, + {Key: "paid_conversion_rate", Label: "付费转化率", Status: "available", Source: "stat_recharge_day_payers + canonical Social DAU", Definition: "付费用户 / canonical Social 活跃用户;当前 Lalu 付费用户等同充值用户。"}, + {Key: "recharge_conversion_rate", Label: "充值转化率", Status: "available", Source: "stat_recharge_day_payers + canonical Social DAU", Definition: "充值用户 / canonical Social 活跃用户;当前 Lalu 充值用户由 paid_users 派生。"}, } } diff --git a/services/statistics-service/internal/storage/mysql/query_test.go b/services/statistics-service/internal/storage/mysql/query_test.go index b64d1de3..90e3191a 100644 --- a/services/statistics-service/internal/storage/mysql/query_test.go +++ b/services/statistics-service/internal/storage/mysql/query_test.go @@ -27,6 +27,271 @@ func TestGiftDebitConsumptionOwnersDoNotOverlap(t *testing.T) { } } +func TestCanonicalizeSocialUserDaysMergesIdentityWithoutLosingDeviceCount(t *testing.T) { + if socialRetentionLookaheadDays([]string{SocialSectionActive}) != 0 || + socialRetentionLookaheadDays([]string{SocialSectionNewUsers}) != 1 || + socialRetentionLookaheadDays([]string{SocialSectionActive, SocialSectionRetention}) != 30 { + t.Fatal("social retention lookahead must stay section-bounded") + } + rows := []socialRequirementUserDay{ + {StatDay: "2026-07-01", Subject: "d:device-A", DeviceID: "device-A", CountryID: 999, RegionID: 999, UserRole: "user", AppFirstOpen: 1, Active: 1, AppStayMS: 60_000, RoomStayMS: 20_000}, + {StatDay: "2026-07-01", Subject: "u:123", UserID: 123, DirectUser: true, DeviceID: "device-A", CountryID: 86, RegionID: 210, UserRole: "host", AppFirstOpen: 1, Active: 1, AppStayMS: 30_000, RoomOnlineMS: 45_000}, + } + resolved := map[socialIdentityDeviceDayKey]int64{ + {StatDay: "2026-07-01", DeviceID: "device-A"}: 123, + } + got := canonicalizeSocialUserDays(rows, resolved, 0, 0, []int64{210}) + if len(got) != 1 { + t.Fatalf("expected one canonical user-day, got %+v", got) + } + row := got[0] + if row.Subject != "u:123" || row.UserID != 123 || !row.DirectUser || row.CountryID != 86 || row.RegionID != 210 || row.UserRole != "host" || row.Active != 1 { + t.Fatalf("canonical identity/dimension mismatch: %+v", row) + } + if row.AppFirstOpen != 1 || row.AppStayMS != 90_000 || row.RoomStayMS != 45_000 { + t.Fatalf("canonical metric merge mismatch: %+v", row) + } + cube := buildCanonicalOverviewActiveCube(got) + if cube.Total != 1 || cube.ByDay["2026-07-01"] != 1 || cube.ByCountry[86].ActiveUsers != 1 || cube.ByCountry[86].RegionID != 210 || cube.ByDayCountry[dailyCountryKey("2026-07-01", 86)].ActiveUsers != 1 { + t.Fatalf("canonical overview active cube mismatch: %+v", cube) + } +} + +func TestCanonicalizeSocialUserDaysDirectTupleWithoutCountryDoesNotEraseKnownDimension(t *testing.T) { + rows := []socialRequirementUserDay{ + {StatDay: "2026-07-15", Subject: "d:device-A", DeviceID: "device-A", CountryID: 158, RegionID: 19, UserRole: "user", Active: 1}, + {StatDay: "2026-07-15", Subject: "u:123", UserID: 123, DirectUser: true, DeviceID: "device-A", CountryID: 0, RegionID: 999, UserRole: "host", Active: 1}, + } + resolved := map[socialIdentityDeviceDayKey]int64{ + {StatDay: "2026-07-15", DeviceID: "device-A"}: 123, + } + + got := canonicalizeSocialUserDays(rows, resolved, 0, 0, nil) + if len(got) != 1 { + t.Fatalf("expected one canonical user-day, got %+v", got) + } + if got[0].CountryID != 158 || got[0].RegionID != 19 || !got[0].DirectUser || got[0].UserRole != "host" { + t.Fatalf("direct tuple without country must preserve known device dimension: %+v", got[0]) + } +} + +func TestCanonicalOverviewActiveCubeKeepsUnknownCountryOnlyInTotals(t *testing.T) { + day := "2026-07-15" + cube := buildCanonicalOverviewActiveCube([]socialRequirementUserDay{ + {StatDay: day, Subject: "u:1", UserID: 1, CountryID: 158, RegionID: 19, Active: 1}, + {StatDay: day, Subject: "d:anonymous", DeviceID: "anonymous", CountryID: 0, RegionID: 0, Active: 1}, + {StatDay: day, Subject: "d:inactive", DeviceID: "inactive", CountryID: 0, RegionID: 0, Active: 0}, + }) + + if cube.Total != 2 || cube.ByDay[day] != 2 { + t.Fatalf("unknown-country DAU must remain in total counters: %+v", cube) + } + if cube.ByCountry[158].ActiveUsers != 1 || cube.ByDayCountry[dailyCountryKey(day, 158)].ActiveUsers != 1 { + t.Fatalf("known-country DAU mismatch: %+v", cube) + } + if _, ok := cube.ByCountry[0]; ok { + t.Fatalf("country breakdown must not expose country_id=0: %+v", cube.ByCountry) + } + if _, ok := cube.ByDayCountry[dailyCountryKey(day, 0)]; ok { + t.Fatalf("daily country breakdown must not expose country_id=0: %+v", cube.ByDayCountry) + } + + // 旧 stat_app_day_country 里的 0 维度可能先于 canonical Social 逻辑存在;overlay 也必须删掉旧行, + // 否则页面仍会看到 active_users=0 的“国家 0”空壳,金额字段还可能让它继续参与排序。 + countryRows := overlayCanonicalCountryActive([]CountryBreakdown{ + {CountryID: 0, RechargeUSDMinor: 100}, + {CountryID: 158, RechargeUSDMinor: 200}, + }, cube) + if len(countryRows) != 1 || countryRows[0].CountryID != 158 || countryRows[0].ActiveUsers != 1 { + t.Fatalf("country overlay must remove unknown legacy row: %+v", countryRows) + } + dailyRows := overlayCanonicalDailyCountryActive([]DailyCountryStat{ + {StatDay: day, CountryBreakdown: CountryBreakdown{CountryID: 0, RechargeUSDMinor: 100}}, + {StatDay: day, CountryBreakdown: CountryBreakdown{CountryID: 158, RechargeUSDMinor: 200}}, + }, cube) + if len(dailyRows) != 1 || dailyRows[0].CountryID != 158 || dailyRows[0].ActiveUsers != 1 { + t.Fatalf("daily country overlay must remove unknown legacy row: %+v", dailyRows) + } +} + +func TestSocialRetentionUserDayProjectionStaysNarrow(t *testing.T) { + for _, required := range []string{ + "stat_day", "subject_key", "user_id", "device_id", "country_id", "region_id", "user_role", + "registered_success", "active_user", "room_join_success", "mic_up_success", "gift_sent", "recharge_user", "game_bet_user", + } { + if !strings.Contains(socialRetentionUserDayProjection, required) { + t.Fatalf("retention projection misses %s: %s", required, socialRetentionUserDayProjection) + } + } + for _, forbidden := range []string{ + "app_stay_ms", "room_stay_ms", "recharge_usd_minor", "normal_gift_coin", "game_bet_coin", "output_coin", + } { + if strings.Contains(socialRetentionUserDayProjection, forbidden) { + t.Fatalf("retention projection unexpectedly includes wide metric %s: %s", forbidden, socialRetentionUserDayProjection) + } + } +} + +func TestSocialRetentionMetricsExcludeUnobservableCohorts(t *testing.T) { + day := "2026-07-01" + host := socialRequirementUserDay{ + StatDay: day, Subject: "u:1", UserID: 1, UserRole: "host", Registered: 1, Active: 1, + RoomJoinOK: 1, MicUp: 1, Gift: 1, GameBet: 1, Recharge: 1, + } + user := socialRequirementUserDay{StatDay: day, Subject: "u:2", UserID: 2, UserRole: "user", Registered: 1, Active: 1} + bySubjectDay := map[string]map[string]socialRequirementUserDay{ + host.Subject: {}, + user.Subject: {}, + } + for _, offset := range []int{1, 3, 7, 15, 30} { + targetDay := addStatDays(day, offset) + bySubjectDay[host.Subject][targetDay] = socialRequirementUserDay{ + StatDay: targetDay, Subject: host.Subject, UserID: host.UserID, Active: 1, + RoomJoinOK: 1, MicUp: 1, Gift: 1, GameBet: 1, Recharge: 1, + } + bySubjectDay[user.Subject][targetDay] = socialRequirementUserDay{ + StatDay: targetDay, Subject: user.Subject, UserID: user.UserID, Active: 1, + } + } + + // 即使未来观察行已经存在于索引,D+N 超过可观察日也必须保持字段缺失, + // 证明成熟度由统计日期控制,而不是把“查不到目标行”误当作唯一判断。 + immature := socialRetentionMetrics(day, day, []socialRequirementUserDay{host, user}, bySubjectDay, SocialSectionRetention, "all", "all", "all") + if len(immature) != 0 { + t.Fatalf("unobservable retention must be omitted: %+v", immature) + } + immatureMetrics := socialSectionMetrics(SocialSectionRetention, socialRequirementAggregate{}, immature) + for _, key := range []string{"active_d1_active_users", "active_d1_active_rate"} { + if _, ok := immatureMetrics[key]; ok { + t.Fatalf("unobservable metric %s must be absent: %+v", key, immatureMetrics) + } + } + immatureDailyMetrics := socialRetentionDailyMetrics(immatureMetrics, []socialRequirementUserDay{host, user}, "all", "all", "all") + for _, offset := range []int{1, 3, 7, 15, 30} { + key := "active_d" + strconv.Itoa(offset) + "_active_base_users" + if immatureDailyMetrics[key] != int64(2) { + t.Fatalf("unobservable daily base %s must expose canonical DAU: %+v", key, immatureDailyMetrics) + } + } + if _, ok := immatureDailyMetrics["active_d1_active_users"]; ok { + t.Fatalf("unobservable daily users must remain absent: %+v", immatureDailyMetrics) + } + if filtered := socialRetentionDailyMetrics(immatureMetrics, []socialRequirementUserDay{host, user}, "host", "paid", "new"); filtered["active_d1_active_base_users"] != int64(1) { + t.Fatalf("daily base must apply role/payer/new-user filters after canonicalization: %+v", filtered) + } + + d1 := socialRetentionMetrics(day, addStatDays(day, 1), []socialRequirementUserDay{host, user}, bySubjectDay, SocialSectionRetention, "all", "all", "all") + if d1["active_d1_active"].Base != 2 || d1["active_d1_active"].Users != 2 { + t.Fatalf("mature active D1 mismatch: %+v", d1["active_d1_active"]) + } + for _, key := range []string{ + "after_room_d1_active", "after_room_d1_room", + "after_mic_d1_active", "after_mic_d1_mic", + "after_gift_d1_active", "after_gift_d1_gift", + "after_game_d1_active", "after_game_d1_game", + "after_recharge_d1_active", "after_recharge_d1_recharge", + } { + if d1[key].Base != 1 || d1[key].Users != 1 { + t.Fatalf("mature behavior D1 %s mismatch: %+v", key, d1[key]) + } + } + for _, key := range []string{"active_d3_active", "active_d7_active", "active_d15_active", "active_d30_active"} { + if _, ok := d1[key]; ok { + t.Fatalf("future offset %s must remain absent: %+v", key, d1) + } + } + + allMature := socialRetentionMetrics(day, addStatDays(day, 30), []socialRequirementUserDay{host, user}, bySubjectDay, SocialSectionRetention, "all", "all", "all") + for _, offset := range []int{1, 3, 7, 15, 30} { + key := "active_d" + strconv.Itoa(offset) + "_active" + if allMature[key].Base != 2 || allMature[key].Users != 2 { + t.Fatalf("mature active D%d mismatch: %+v", offset, allMature[key]) + } + } + + newUserImmature := socialRetentionMetrics(day, day, []socialRequirementUserDay{host, user}, bySubjectDay, SocialSectionNewUsers, "all", "all", "all") + newUserImmatureMetrics := socialSectionMetrics(SocialSectionNewUsers, socialRequirementAggregate{}, newUserImmature) + for _, key := range []string{"new_host_d1_retention_rate", "new_user_d1_retention_rate"} { + if _, ok := newUserImmatureMetrics[key]; ok { + t.Fatalf("unobservable new-user metric %s must be absent: %+v", key, newUserImmatureMetrics) + } + } + newUserD1 := socialRetentionMetrics(day, addStatDays(day, 1), []socialRequirementUserDay{host, user}, bySubjectDay, SocialSectionNewUsers, "all", "all", "all") + for _, key := range []string{"new_host_d1_active", "new_user_d1_active"} { + if newUserD1[key].Base != 1 || newUserD1[key].Users != 1 { + t.Fatalf("mature new-user D1 %s mismatch: %+v", key, newUserD1[key]) + } + } + + // 汇总只合并成熟 cohort;平均值只对实际存在该指标的日行求均值。 + total := map[string]retentionMetric{} + mergeRetentionMetrics(total, d1) + mergeRetentionMetrics(total, immature) + totalMetrics := socialSectionMetrics(SocialSectionRetention, socialRequirementAggregate{}, total) + average := socialAverageRow([]SocialRequirementRow{ + {StatDay: day, Metrics: socialSectionMetrics(SocialSectionRetention, socialRequirementAggregate{}, d1)}, + {StatDay: addStatDays(day, 1), Metrics: immatureMetrics}, + }) + if totalMetrics["active_d1_active_base_users"] != int64(2) || totalMetrics["active_d1_active_users"] != int64(2) || average.Metrics["active_d1_active_users"] != float64(2) { + t.Fatalf("unobservable cohort polluted total/average: total=%+v average=%+v", totalMetrics, average.Metrics) + } + + for _, column := range socialRequirementColumns(SocialSectionRetention) { + if column.Key == "active_d1_active_rate" && column.Tooltip != "当日活跃用户中,次日继续进入 app 的比例" { + t.Fatalf("D1 tooltip mismatch: %q", column.Tooltip) + } + } +} + +func TestCanonicalOverviewActiveOverlaysReplaceLegacyDAUAndFillDimensions(t *testing.T) { + cube := canonicalOverviewActiveCube{ + Total: 11, + ByDay: map[string]int64{"2026-07-01": 8, "2026-07-02": 3}, + ByCountry: map[int64]canonicalOverviewActiveDimension{ + 86: {ActiveUsers: 8, RegionID: 210}, + 66: {ActiveUsers: 3, RegionID: 220}, + }, + ByDayCountry: map[string]canonicalOverviewActiveDimension{ + dailyCountryKey("2026-07-01", 86): {ActiveUsers: 8, RegionID: 210}, + dailyCountryKey("2026-07-02", 66): {ActiveUsers: 3, RegionID: 220}, + }, + } + + daily := overlayCanonicalDailyActive([]DailySeriesItem{{ + StatDay: "2026-07-01", Label: "2026-07-01", ActiveUsers: 999, PaidUsers: 2, RechargeUSDMinor: 100, + }}, cube) + if len(daily) != 2 || daily[0].ActiveUsers != 8 || daily[0].ARPUUSDMinor != 12 || daily[0].PayerRate != 0.25 || daily[1].StatDay != "2026-07-02" || daily[1].ActiveUsers != 3 { + t.Fatalf("daily canonical overlay mismatch: %+v", daily) + } + + countries := overlayCanonicalCountryActive([]CountryBreakdown{ + {CountryID: 86, RegionID: 999, ActiveUsers: 999, PaidUsers: 2, RechargeUSDMinor: 100}, + {CountryID: 99, RegionID: 230, ActiveUsers: 777, RechargeUSDMinor: 50}, + }, cube) + countryByID := map[int64]CountryBreakdown{} + for _, item := range countries { + countryByID[item.CountryID] = item + } + if countryByID[86].ActiveUsers != 8 || countryByID[86].RegionID != 210 || countryByID[86].ARPUUSDMinor != 12 || countryByID[86].PaidConversionRate != 0.25 { + t.Fatalf("existing country canonical overlay mismatch: %+v", countryByID[86]) + } + if countryByID[66].ActiveUsers != 3 || countryByID[66].RegionID != 220 { + t.Fatalf("canonical-only country row missing: %+v", countryByID[66]) + } + if countryByID[99].ActiveUsers != 0 || countryByID[99].RechargeUSDMinor != 50 { + t.Fatalf("legacy-only country must retain business facts but not legacy DAU: %+v", countryByID[99]) + } + + dailyCountries := overlayCanonicalDailyCountryActive([]DailyCountryStat{{ + StatDay: "2026-07-01", Label: "2026-07-01", CountryBreakdown: CountryBreakdown{ + CountryID: 86, RegionID: 999, ActiveUsers: 999, PaidUsers: 2, RechargeUSDMinor: 100, + }, + }}, cube) + if len(dailyCountries) != 2 || dailyCountries[0].ActiveUsers != 8 || dailyCountries[0].RegionID != 210 || dailyCountries[0].PayerRate != 0.25 || dailyCountries[1].StatDay != "2026-07-02" || dailyCountries[1].CountryID != 66 || dailyCountries[1].ActiveUsers != 3 { + t.Fatalf("daily country canonical overlay mismatch: %+v", dailyCountries) + } +} + func TestQueryOverviewUsesActivityLuckyGiftDayStats(t *testing.T) { ctx := context.Background() _, file, _, _ := runtime.Caller(0) @@ -124,26 +389,28 @@ func TestConsumeAppTrackingEventsStoresRawEventsAndDeduplicates(t *testing.T) { occurredAt := time.Date(2026, 7, 2, 23, 59, 59, 0, time.UTC).UnixMilli() result, err := repository.ConsumeAppTrackingEvents(appcode.WithContext(ctx, "lalu"), []AppTrackingEvent{ { - AppCode: "lalu", - EventID: "evt-banner-1", - EventName: "banner_view", - EventType: "view", - Screen: "home", - TargetType: "banner", - TargetID: "17", - UserID: 42, - DeviceID: "dev-1", - SessionID: "sess-1", - Platform: "ios", - AppVersion: "1.2.3", - Language: "en-US", - Timezone: "Asia/Shanghai", - CountryID: 86, - RegionID: 210, - DurationMS: 12, - Success: true, - Properties: json.RawMessage(`{"slot":"top"}`), - OccurredAtMS: occurredAt, + AppCode: "lalu", + EventID: "evt-banner-1", + EventName: "banner_view", + EventType: "view", + Screen: "home", + TargetType: "banner", + TargetID: "17", + UserID: 42, + DeviceID: "dev-1", + SessionID: "sess-1", + ClientSessionID: "client-sess-1", + AuthSessionID: "auth-sess-1", + Platform: "ios", + AppVersion: "1.2.3", + Language: "en-US", + Timezone: "Asia/Shanghai", + CountryID: 86, + RegionID: 210, + DurationMS: 12, + Success: true, + Properties: json.RawMessage(`{"slot":"top"}`), + OccurredAtMS: occurredAt, }, }) if err != nil { @@ -172,25 +439,151 @@ func TestConsumeAppTrackingEventsStoresRawEventsAndDeduplicates(t *testing.T) { } var count int64 - var statDay, screen, identityKey, propertiesJSON string + var statDay, screen, identityKey, clientSessionID, authSessionID, propertiesJSON string var userID, countryID, regionID, durationMS int64 var success bool if err := repository.db.QueryRowContext(ctx, ` - SELECT COUNT(*), MAX(CAST(stat_day AS CHAR)), MAX(screen), MAX(identity_key), MAX(user_id), MAX(country_id), MAX(region_id), + SELECT COUNT(*), MAX(CAST(stat_day AS CHAR)), MAX(screen), MAX(identity_key), + MAX(client_session_id), MAX(auth_session_id), MAX(user_id), MAX(country_id), MAX(region_id), MAX(duration_ms), MAX(success), COALESCE(MAX(CAST(properties_json AS CHAR)), '{}') FROM app_tracking_events WHERE app_code = 'lalu' AND event_id = 'evt-banner-1' - `).Scan(&count, &statDay, &screen, &identityKey, &userID, &countryID, ®ionID, &durationMS, &success, &propertiesJSON); err != nil { + `).Scan(&count, &statDay, &screen, &identityKey, &clientSessionID, &authSessionID, &userID, &countryID, ®ionID, &durationMS, &success, &propertiesJSON); err != nil { t.Fatalf("query app tracking event: %v", err) } - if count != 1 || statDay != "2026-07-02" || screen != "home" || identityKey != "u:42" || userID != 42 || countryID != 86 || regionID != 210 || durationMS != 12 || !success { - t.Fatalf("stored event mismatch: count=%d statDay=%s screen=%s identityKey=%s userID=%d countryID=%d regionID=%d durationMS=%d success=%v", count, statDay, screen, identityKey, userID, countryID, regionID, durationMS, success) + if count != 1 || statDay != "2026-07-02" || screen != "home" || identityKey != "u:42" || clientSessionID != "client-sess-1" || authSessionID != "auth-sess-1" || userID != 42 || countryID != 86 || regionID != 210 || durationMS != 12 || !success { + t.Fatalf("stored event mismatch: count=%d statDay=%s screen=%s identityKey=%s clientSessionID=%s authSessionID=%s userID=%d countryID=%d regionID=%d durationMS=%d success=%v", count, statDay, screen, identityKey, clientSessionID, authSessionID, userID, countryID, regionID, durationMS, success) } if DecodeJSON(propertiesJSON)["slot"] != "top" { t.Fatalf("properties_json mismatch: %s", propertiesJSON) } } +func TestSocialIdentityCanonicalizesAnonymousAndLoggedSession(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_social_identity_test", + }) + repository, err := Open(ctx, statsSchema.DSN) + if err != nil { + t.Fatalf("open repository: %v", err) + } + t.Cleanup(func() { _ = repository.Close() }) + + start := time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC) + events := []AppTrackingEvent{ + // Both pre-login rows are stored as d:device-A. The authenticated event + // establishes the client-session bridge without rewriting those rows. + {AppCode: "lalu", EventID: "identity:first-open", EventName: "app_first_open", DeviceID: "device-A", ClientSessionID: "client-session-A", Success: true, OccurredAtMS: start.UnixMilli()}, + {AppCode: "lalu", EventID: "identity:anonymous-session", EventName: "app_session", DeviceID: "device-A", ClientSessionID: "client-session-A", DurationMS: 120_000, Success: true, OccurredAtMS: start.Add(time.Minute).UnixMilli()}, + {AppCode: "lalu", EventID: "identity:login", EventName: "home_view", UserID: 123, DeviceID: "device-A", ClientSessionID: "client-session-A", AuthSessionID: "auth-session-A", CountryID: 86, RegionID: 210, Success: true, OccurredAtMS: start.Add(2 * time.Minute).UnixMilli()}, + {AppCode: "lalu", EventID: "identity:d1", EventName: "home_view", UserID: 123, DeviceID: "device-A", ClientSessionID: "client-session-A", AuthSessionID: "auth-session-A", CountryID: 86, RegionID: 999, Success: true, OccurredAtMS: start.Add(24*time.Hour + time.Minute).UnixMilli()}, + } + if _, err := repository.ConsumeAppTrackingEvents(appcode.WithContext(ctx, "lalu"), events); err != nil { + t.Fatalf("consume identity events: %v", err) + } + + result, err := repository.QuerySocialRequirements(ctx, SocialRequirementsQuery{ + AppCode: "lalu", + StartMS: start.UnixMilli(), + EndMS: start.Add(24 * time.Hour).UnixMilli(), + RegionIDs: []int64{210}, + }) + if err != nil { + t.Fatalf("query canonical social requirements: %v", err) + } + active := socialTestSection(t, result, SocialSectionActive) + if socialMetricInt(t, active.Total, "active_users") != 1 || math.Abs(socialMetricFloat(t, active.Total, "avg_app_stay_min")-2) > 0.0001 { + t.Fatalf("anonymous and logged rows were not canonicalized: %+v", active.Total.Metrics) + } + newUsers := socialTestSection(t, result, SocialSectionNewUsers) + if socialMetricInt(t, newUsers.Total, "app_download_users") != 1 { + t.Fatalf("device download count changed after identity merge: %+v", newUsers.Total.Metrics) + } + retention := socialTestSection(t, result, SocialSectionRetention) + if socialMetricInt(t, retention.Total, "active_d1_active_base_users") != 1 || + socialMetricInt(t, retention.Total, "active_d1_active_users") != 1 || + math.Abs(socialMetricFloat(t, retention.Total, "active_d1_active_rate")-1) > 0.0001 { + t.Fatalf("canonical retention mismatch: %+v", retention.Total.Metrics) + } + + // The operation-wide response must consume the exact same canonical user-day + // as Data Requirements. This fixture has both d:device-A and u:123, so any + // direct SUM(active_user) implementation would incorrectly return two. + overview, err := repository.QueryOverview(ctx, OverviewQuery{ + AppCode: "lalu", + StartMS: start.UnixMilli(), + EndMS: start.Add(24 * time.Hour).UnixMilli(), + }) + if err != nil { + t.Fatalf("query canonical overview: %v", err) + } + if overview.ActiveUsers != 1 || len(overview.DailySeries) != 1 || overview.DailySeries[0].ActiveUsers != 1 { + t.Fatalf("overview and daily DAU must share canonical identity: %+v", overview) + } + if len(overview.CountryBreakdown) != 1 || overview.CountryBreakdown[0].CountryID != 86 || overview.CountryBreakdown[0].RegionID != 210 || overview.CountryBreakdown[0].ActiveUsers != 1 { + t.Fatalf("country DAU must use the direct account dimensions: %+v", overview.CountryBreakdown) + } + if len(overview.DailyCountryBreakdown) != 1 || overview.DailyCountryBreakdown[0].CountryID != 86 || overview.DailyCountryBreakdown[0].RegionID != 210 || overview.DailyCountryBreakdown[0].ActiveUsers != 1 { + t.Fatalf("daily country DAU must use the direct account dimensions: %+v", overview.DailyCountryBreakdown) + } +} + +func TestSocialIdentityMarksConcurrentAccountSwitchAmbiguous(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_identity_switch", + }) + repository, err := Open(ctx, statsSchema.DSN) + if err != nil { + t.Fatalf("open repository: %v", err) + } + t.Cleanup(func() { _ = repository.Close() }) + + start := time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC) + if _, err := repository.ConsumeAppTrackingEvents(appcode.WithContext(ctx, "lalu"), []AppTrackingEvent{{ + AppCode: "lalu", EventID: "switch:anonymous", EventName: "home_view", DeviceID: "shared-device", ClientSessionID: "shared-process-session", Success: true, OccurredAtMS: start.UnixMilli(), + }}); err != nil { + t.Fatalf("consume anonymous event: %v", err) + } + + // Deliberately race two accounts in one process session. The device lock + // must serialize the current reads so the last writer cannot leave a falsely + // resolved user behind. + errors := make(chan error, 2) + for userID := int64(1); userID <= 2; userID++ { + userID := userID + go func() { + _, consumeErr := repository.ConsumeAppTrackingEvents(appcode.WithContext(ctx, "lalu"), []AppTrackingEvent{{ + AppCode: "lalu", EventID: "switch:user:" + strconv.FormatInt(userID, 10), EventName: "home_view", UserID: userID, DeviceID: "shared-device", ClientSessionID: "shared-process-session", Success: true, OccurredAtMS: start.Add(time.Duration(userID) * time.Minute).UnixMilli(), + }}) + errors <- consumeErr + }() + } + for index := 0; index < 2; index++ { + if err := <-errors; err != nil { + t.Fatalf("consume concurrent account event: %v", err) + } + } + + var resolvedUserID int64 + var state, source string + if err := repository.db.QueryRowContext(ctx, ` + SELECT resolved_user_id, resolution_state, resolution_source + FROM stat_social_identity_day + WHERE app_code = 'lalu' AND stat_tz = 'UTC' AND stat_day = '2026-07-01' AND device_id = 'shared-device' + `).Scan(&resolvedUserID, &state, &source); err != nil { + t.Fatalf("query identity resolution: %v", err) + } + if resolvedUserID != 0 || state != "ambiguous" || source != "client_session" { + t.Fatalf("account switch must remain ambiguous: user=%d state=%s source=%s", resolvedUserID, state, source) + } +} + func TestQueryAppTrackingFunnelAggregatesStepsAndD1Cohorts(t *testing.T) { ctx := context.Background() _, file, _, _ := runtime.Caller(0) @@ -355,6 +748,7 @@ func TestQuerySocialRequirementsAggregatesP0ToP5(t *testing.T) { {AppCode: "lalu", EventID: "social:follow-user:1001", EventName: "follow_host", UserID: user1, DeviceID: "dev-1001", CountryID: 86, RegionID: 210, Success: true, OccurredAtMS: start.Add(7 * time.Minute).UnixMilli()}, {AppCode: "lalu", EventID: "social:follow-room:1001", EventName: "follow_room", UserID: user1, DeviceID: "dev-1001", CountryID: 86, RegionID: 210, Success: true, OccurredAtMS: start.Add(8 * time.Minute).UnixMilli()}, {AppCode: "lalu", EventID: "social:d1-active:1001", EventName: "home_view", UserID: user1, DeviceID: "dev-1001", CountryID: 86, RegionID: 210, Success: true, OccurredAtMS: start.Add(24*time.Hour + time.Minute).UnixMilli()}, + {AppCode: "lalu", EventID: "social:d1-room:1001", EventName: "room_join_success", UserID: user1, DeviceID: "dev-1001", CountryID: 86, RegionID: 210, Success: true, OccurredAtMS: start.Add(24*time.Hour + 2*time.Minute).UnixMilli()}, } { if _, err := repository.ConsumeAppTrackingEvents(appcode.WithContext(ctx, "lalu"), []AppTrackingEvent{event}); err != nil { t.Fatalf("consume app event %s: %v", event.EventName, err) @@ -482,6 +876,21 @@ func TestQuerySocialRequirementsAggregatesP0ToP5(t *testing.T) { math.Abs(socialMetricFloat(t, retention.Total, "after_room_d1_room_rate")-1) > 0.0001 { t.Fatalf("P2 retention metrics mismatch: %+v", retention.Total.Metrics) } + // 单独请求 retention 必须走窄列投影,同时保持与全 section 查询相同的 + // canonical 身份归并、区域过滤和留存结果。 + retentionOnly, err := repository.QuerySocialRequirements(ctx, SocialRequirementsQuery{ + AppCode: "lalu", StartMS: query.StartMS, EndMS: query.EndMS, + RegionIDs: []int64{210}, Section: SocialSectionRetention, + }) + if err != nil { + t.Fatalf("query narrow retention requirements: %v", err) + } + retentionOnlySection := socialTestSection(t, retentionOnly, SocialSectionRetention) + if socialMetricInt(t, retentionOnlySection.Total, "active_d1_active_base_users") != 2 || + socialMetricInt(t, retentionOnlySection.Total, "active_d1_active_users") != 1 || + math.Abs(socialMetricFloat(t, retentionOnlySection.Total, "active_d1_active_rate")-0.5) > 0.0001 { + t.Fatalf("narrow retention projection changed canonical result: %+v", retentionOnlySection.Total.Metrics) + } active := socialTestSection(t, result, SocialSectionActive) if socialMetricInt(t, active.Total, "active_users") != 2 || socialMetricInt(t, active.Total, "room_join_success_users") != 1 || @@ -727,6 +1136,45 @@ func TestConsumeUserRegisteredCountsOnlyNewRegistration(t *testing.T) { } } +func TestConsumeUserActiveFallsBackToStatisticsUserDimension(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_active_dimension_fallback_test", + }) + repository, err := Open(ctx, statsSchema.DSN) + if err != nil { + t.Fatalf("open repository: %v", err) + } + t.Cleanup(func() { _ = repository.Close() }) + + userID := int64(327300172394536960) + if err := repository.ConsumeUserRegionChanged(ctx, UserRegionChangedEvent{ + AppCode: "lalu", EventID: "region:known-before-room", UserID: userID, + CountryID: 158, RegionID: 19, OccurredAtMS: time.Date(2026, 7, 15, 1, 0, 0, 0, time.UTC).UnixMilli(), + }); err != nil { + t.Fatalf("consume user dimension: %v", err) + } + if err := repository.ConsumeUserActive(ctx, UserActiveEvent{ + AppCode: "lalu", EventID: "room:legacy-without-dimension", EventType: "RoomUserJoined", UserID: userID, + CountryID: 0, RegionID: 0, OccurredAtMS: time.Date(2026, 7, 15, 2, 0, 0, 0, time.UTC).UnixMilli(), + }); err != nil { + t.Fatalf("consume room active: %v", err) + } + + for _, table := range []string{"stat_user_day_activity", "stat_social_user_day"} { + var countryID, regionID int64 + query := "SELECT country_id, region_id FROM " + table + " WHERE app_code = 'lalu' AND stat_tz = 'UTC' AND stat_day = '2026-07-15' AND user_id = ?" + if err := repository.db.QueryRowContext(ctx, query, userID).Scan(&countryID, ®ionID); err != nil { + t.Fatalf("query %s dimension: %v", table, err) + } + if countryID != 158 || regionID != 19 { + t.Fatalf("%s must use statistics-owned user dimension, got country=%d region=%d", table, countryID, regionID) + } + } +} + func TestConsumeReportMetricsAggregatesWalletSalaryGrantAndMic(t *testing.T) { ctx := context.Background() _, file, _, _ := runtime.Caller(0) @@ -1074,19 +1522,21 @@ func TestQueryOverviewReturnsPreviousPeriodDeltaRates(t *testing.T) { ('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) } + seedCanonicalActiveUsers(t, ctx, repository, "lalu", StatTZUTC, "2026-06-05", 210, 0, 8, 10_000) + seedCanonicalActiveUsers(t, ctx, repository, "lalu", StatTZUTC, "2026-06-06", 210, 0, 12, 20_000) 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 { + if overview.ActiveUsers != 12 || overview.RechargeDeltaRate != 1 || overview.NewUserRechargeDeltaRate != 1 || math.Abs(overview.ActiveUsersDeltaRate-0.5) > 0.000001 { t.Fatalf("top delta rates mismatch: %+v", overview) } - if overview.PaidUsersDeltaRate != 1.5 || overview.ARPUDeltaRate != 0 || overview.ARPPUDeltaRate != -0.2 { + if overview.ARPUUSDMinor != 16 || overview.PaidUsersDeltaRate != 1.5 || math.Abs(overview.ARPUDeltaRate-(1.0/3.0)) > 0.000001 || overview.ARPPUDeltaRate != -0.2 { t.Fatalf("user delta rates mismatch: %+v", overview) } - if overview.RechargeUsers != overview.PaidUsers || overview.PaidConversionRate != 0.25 || overview.RechargeConversionRate != 0.25 || overview.PayerRateDeltaPP != 5 { + if overview.RechargeUsers != overview.PaidUsers || math.Abs(overview.PaidConversionRate-(5.0/12.0)) > 0.000001 || math.Abs(overview.RechargeConversionRate-(5.0/12.0)) > 0.000001 || math.Abs(overview.PayerRateDeltaPP-(100.0/6.0)) > 0.000001 || math.Abs(overview.PaidConversionRateDeltaPP-(100.0/6.0)) > 0.000001 || math.Abs(overview.RechargeConversionRateDeltaPP-(100.0/6.0)) > 0.000001 { t.Fatalf("conversion aliases mismatch: %+v", overview) } if overview.GiftCoinSpentDeltaRate != 1 || overview.CoinSellerTransferDeltaRate != 1.5 || overview.LuckyGiftTurnoverDeltaRate != 3 || overview.LuckyGiftPayoutDeltaRate != 1 || overview.LuckyGiftProfitDeltaRate != 5 { @@ -1311,6 +1761,8 @@ func TestQueryOverviewReturnsCountryBreakdownAndIncludesCoinSellerRecharge(t *te ('lalu', '2026-06-06', 99, 220, 3, 1, 900, 0, 0, 900, 1)`); err != nil { t.Fatalf("seed country statistics: %v", err) } + seedCanonicalActiveUsers(t, ctx, repository, "lalu", StatTZUTC, "2026-06-06", 86, 210, 8, 30_000) + seedCanonicalActiveUsers(t, ctx, repository, "lalu", StatTZUTC, "2026-06-06", 66, 210, 4, 40_000) 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}) @@ -1320,7 +1772,7 @@ func TestQueryOverviewReturnsCountryBreakdownAndIncludesCoinSellerRecharge(t *te if overview.RechargeUSDMinor != 650 || overview.CoinSellerRechargeUSDMinor != 400 || overview.CoinSellerStockCoin != 880000 { t.Fatalf("overview recharge mismatch: %+v", overview) } - if overview.RechargeUsers != 3 || overview.PaidConversionRate != 0.2 || overview.RechargeConversionRate != 0.2 { + if overview.ActiveUsers != 12 || overview.ARPUUSDMinor != 54 || overview.RechargeUsers != 3 || overview.PaidConversionRate != 0.25 || overview.RechargeConversionRate != 0.25 { t.Fatalf("overview conversion fields mismatch: %+v", overview) } if len(overview.CountryBreakdown) != 2 { @@ -1329,7 +1781,7 @@ func TestQueryOverviewReturnsCountryBreakdownAndIncludesCoinSellerRecharge(t *te if overview.CountryBreakdown[0].CountryID != 86 || overview.CountryBreakdown[0].RechargeUSDMinor != 550 || overview.CountryBreakdown[0].CoinSellerStockCoin != 880000 || overview.CountryBreakdown[0].ARPPUUSDMinor != 275 { t.Fatalf("first country breakdown mismatch: %+v", overview.CountryBreakdown[0]) } - if overview.CountryBreakdown[0].RechargeUsers != 2 || overview.CountryBreakdown[0].PaidConversionRate != 0.2 || overview.CountryBreakdown[0].RechargeConversionRate != 0.2 { + if overview.CountryBreakdown[0].ActiveUsers != 8 || overview.CountryBreakdown[0].ARPUUSDMinor != 68 || overview.CountryBreakdown[0].RechargeUsers != 2 || overview.CountryBreakdown[0].PaidConversionRate != 0.25 || overview.CountryBreakdown[0].RechargeConversionRate != 0.25 { t.Fatalf("first country conversion fields mismatch: %+v", overview.CountryBreakdown[0]) } } @@ -1357,6 +1809,9 @@ func TestQueryOverviewReturnsDailyCountryBreakdownAndSuperLuckyGift(t *testing.T ('lalu', '2026-06-06', 86, 210, 12, 3, 150, 9000, 1200, 300, 1)`); err != nil { t.Fatalf("seed app country stats: %v", err) } + seedCanonicalActiveUsers(t, ctx, repository, "lalu", StatTZUTC, "2026-06-05", 86, 210, 8, 50_000) + seedCanonicalActiveUsers(t, ctx, repository, "lalu", StatTZUTC, "2026-06-05", 66, 210, 4, 60_000) + seedCanonicalActiveUsers(t, ctx, repository, "lalu", StatTZUTC, "2026-06-06", 86, 210, 9, 70_000) if _, err := repository.db.ExecContext(ctx, ` INSERT INTO stat_lucky_gift_pool_day_country ( app_code, stat_day, country_id, region_id, pool_id, turnover_coin, payout_coin, updated_at_ms @@ -1375,6 +1830,9 @@ func TestQueryOverviewReturnsDailyCountryBreakdownAndSuperLuckyGift(t *testing.T if overview.SuperLuckyGiftTurnover != 1600 || overview.SuperLuckyGiftPayout != 300 || overview.SuperLuckyGiftProfit != 1300 { t.Fatalf("super lucky overview mismatch: %+v", overview) } + if overview.ActiveUsers != 21 || len(overview.DailySeries) != 2 || overview.DailySeries[0].ActiveUsers != 12 || overview.DailySeries[1].ActiveUsers != 9 { + t.Fatalf("overview and daily DAU must come from canonical Social: %+v", overview.DailySeries) + } if len(overview.DailyCountryBreakdown) != 3 { t.Fatalf("daily country breakdown length mismatch: %+v", overview.DailyCountryBreakdown) } @@ -1382,7 +1840,7 @@ func TestQueryOverviewReturnsDailyCountryBreakdownAndSuperLuckyGift(t *testing.T if first.StatDay != "2026-06-05" || first.CountryID != 86 || first.CoinSellerStockCoin != 7000 || first.SuperLuckyGiftTurnover != 700 || first.SuperLuckyGiftProfitRate <= 0 { t.Fatalf("first daily country row mismatch: %+v", first) } - if first.RechargeUsers != 2 || first.PaidConversionRate != 0.2 || first.RechargeConversionRate != 0.2 { + if first.ActiveUsers != 8 || first.RechargeUsers != 2 || first.PaidConversionRate != 0.25 || first.RechargeConversionRate != 0.25 { t.Fatalf("first daily country conversion fields mismatch: %+v", first) } if len(overview.ReportMetricSources) == 0 { @@ -1518,6 +1976,30 @@ func requireNilRetention(t *testing.T, name string, users *int64, base *int64, r } } +// seedCanonicalActiveUsers intentionally writes a value that can differ from +// stat_app_day_country.active_users. Overview tests then prove DAU and every +// related denominator are sourced from the canonical Social user-day table. +func seedCanonicalActiveUsers(t *testing.T, ctx context.Context, repository *Repository, app, statTZ, day string, countryID, regionID int64, count int, firstUserID int64) { + t.Helper() + if count <= 0 { + return + } + placeholders := make([]string, 0, count) + args := make([]any, 0, count*7) + for offset := 0; offset < count; offset++ { + userID := firstUserID + int64(offset) + placeholders = append(placeholders, "(?, ?, ?, ?, ?, '', ?, ?, 1, 1)") + args = append(args, app, statTZ, day, "u:"+strconv.FormatInt(userID, 10), userID, countryID, regionID) + } + if _, err := repository.db.ExecContext(ctx, ` + INSERT INTO stat_social_user_day ( + app_code, stat_tz, stat_day, subject_key, user_id, device_id, + country_id, region_id, active_user, updated_at_ms + ) VALUES `+strings.Join(placeholders, ","), args...); err != nil { + t.Fatalf("seed canonical active users for %s/%s/%s: %v", app, statTZ, day, err) + } +} + // 回看口径下观察日整天零活跃时没有 stat_app_day_country 载体行; // 序列/按日国家下钻必须合成占位行,把真实的 0% 留存保住,而不是让该观察日消失。 func TestQueryOverviewSynthesizesRetentionRowsForZeroActivityDays(t *testing.T) { diff --git a/services/statistics-service/internal/storage/mysql/repository.go b/services/statistics-service/internal/storage/mysql/repository.go index fcf945ff..9a87008e 100644 --- a/services/statistics-service/internal/storage/mysql/repository.go +++ b/services/statistics-service/internal/storage/mysql/repository.go @@ -5,6 +5,7 @@ import ( "database/sql" "encoding/json" "errors" + "sort" "strings" "time" @@ -122,7 +123,8 @@ func (r *Repository) Migrate(ctx context.Context) error { target_type VARCHAR(64) NOT NULL DEFAULT '', target_id VARCHAR(128) NOT NULL DEFAULT '', user_id BIGINT NOT NULL DEFAULT 0, device_id VARCHAR(128) NOT NULL DEFAULT '', identity_key VARCHAR(160) GENERATED ALWAYS AS (CASE WHEN user_id > 0 THEN CONCAT('u:', user_id) ELSE CONCAT('d:', device_id) END) VIRTUAL, - session_id VARCHAR(160) NOT NULL DEFAULT '', platform VARCHAR(32) NOT NULL DEFAULT '', + session_id VARCHAR(160) NOT NULL DEFAULT '', client_session_id VARCHAR(160) NOT NULL DEFAULT '', + auth_session_id VARCHAR(160) NOT NULL DEFAULT '', platform VARCHAR(32) NOT NULL DEFAULT '', app_version VARCHAR(64) NOT NULL DEFAULT '', language VARCHAR(32) NOT NULL DEFAULT '', timezone VARCHAR(64) NOT NULL DEFAULT '', country_id BIGINT NOT NULL DEFAULT 0, region_id BIGINT NOT NULL DEFAULT 0, duration_ms BIGINT NOT NULL DEFAULT 0, @@ -216,6 +218,34 @@ func (r *Repository) Migrate(ctx context.Context) error { KEY idx_stat_social_user_day_region (app_code, stat_tz, stat_day, region_id), KEY idx_stat_social_user_day_filter (app_code, stat_tz, stat_day, user_role, recharge_user) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, + `CREATE TABLE IF NOT EXISTS stat_social_identity_session_user ( + app_code VARCHAR(32) NOT NULL, device_id VARCHAR(128) COLLATE utf8mb4_bin NOT NULL, + client_session_id VARCHAR(160) COLLATE utf8mb4_bin NOT NULL, + user_id BIGINT NOT NULL, first_seen_at_ms BIGINT NOT NULL, updated_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, device_id, client_session_id, user_id), + KEY idx_social_identity_session_user (app_code, user_id, first_seen_at_ms) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, + `CREATE TABLE IF NOT EXISTS stat_social_identity_device_lock ( + app_code VARCHAR(32) NOT NULL, device_id VARCHAR(128) COLLATE utf8mb4_bin NOT NULL, + created_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, device_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, + `CREATE TABLE IF NOT EXISTS stat_social_identity_session_day ( + app_code VARCHAR(32) NOT NULL, stat_tz VARCHAR(64) NOT NULL, stat_day DATE NOT NULL, + device_id VARCHAR(128) COLLATE utf8mb4_bin NOT NULL, + client_session_id VARCHAR(160) COLLATE utf8mb4_bin NOT NULL, + first_seen_at_ms BIGINT NOT NULL, updated_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, device_id, client_session_id, stat_tz, stat_day), + KEY idx_social_identity_session_day (app_code, stat_tz, stat_day, device_id, client_session_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, + `CREATE TABLE IF NOT EXISTS stat_social_identity_day ( + app_code VARCHAR(32) NOT NULL, stat_tz VARCHAR(64) NOT NULL, stat_day DATE NOT NULL, + device_id VARCHAR(128) COLLATE utf8mb4_bin NOT NULL, resolved_user_id BIGINT NOT NULL DEFAULT 0, + resolution_state VARCHAR(16) NOT NULL DEFAULT 'unresolved', + resolution_source VARCHAR(32) NOT NULL DEFAULT 'client_session', updated_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, stat_tz, stat_day, device_id), + KEY idx_social_identity_day_user (app_code, stat_tz, stat_day, resolved_user_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_tz VARCHAR(64) NOT NULL DEFAULT 'UTC', stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, region_id BIGINT NOT NULL DEFAULT 0, @@ -381,6 +411,10 @@ func (r *Repository) Migrate(ctx context.Context) error { } alterStatements := []string{ `ALTER TABLE app_tracking_events ADD COLUMN identity_key VARCHAR(160) GENERATED ALWAYS AS (CASE WHEN user_id > 0 THEN CONCAT('u:', user_id) ELSE CONCAT('d:', device_id) END) VIRTUAL AFTER device_id`, + // INSTANT only updates metadata for these defaulted columns. MySQL 8.4 + // rejects an explicit LOCK=NONE with INSTANT, so retain the default lock. + `ALTER TABLE app_tracking_events ADD COLUMN client_session_id VARCHAR(160) NOT NULL DEFAULT '', ALGORITHM=INSTANT`, + `ALTER TABLE app_tracking_events ADD COLUMN auth_session_id VARCHAR(160) NOT NULL DEFAULT '', ALGORITHM=INSTANT`, `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`, @@ -765,27 +799,29 @@ type SelfGameH5Event struct { } type AppTrackingEvent struct { - AppCode string - EventID string - EventName string - EventType string - Screen string - TargetType string - TargetID string - UserID int64 - DeviceID string - SessionID string - Platform string - AppVersion string - Language string - Timezone string - CountryID int64 - RegionID int64 - DurationMS int64 - Success bool - ErrorCode string - Properties json.RawMessage - OccurredAtMS int64 + AppCode string + EventID string + EventName string + EventType string + Screen string + TargetType string + TargetID string + UserID int64 + DeviceID string + SessionID string + ClientSessionID string + AuthSessionID string + Platform string + AppVersion string + Language string + Timezone string + CountryID int64 + RegionID int64 + DurationMS int64 + Success bool + ErrorCode string + Properties json.RawMessage + OccurredAtMS int64 } type AppTrackingReportResult struct { @@ -1501,7 +1537,14 @@ func (r *Repository) ConsumeUserRoomDailyStatsUpdated(ctx context.Context, event 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 { - countryID, regionID := normalizeDimension(event.CountryID, event.RegionID) + // RoomUserJoined 的新版事实应自带完整国家/区域,但历史 outbox 和迁移期 producer 可能缺字段。 + // 只回退 statistics-service 自己消费 UserRegistered/UserRegionChanged 建立的维度投影,既修正已知用户, + // 又不跨服务回查 user owner 明细;维度投影尚未到达时仍保留 0,Social 宽表可由后续有效事实补齐, + // 旧 activity 聚合则保持原始事实并由查询层排除未知国家,不能在这里无账搬迁历史计数。 + countryID, regionID, err := r.dimensionForUser(ctx, tx, event.AppCode, event.UserID, event.CountryID, event.RegionID) + if err != nil { + return err + } for _, scope := range statDayScopesFromContext(ctx, event.OccurredAtMS) { if err := applyActive(ctx, tx, event.AppCode, scope.tz, scope.day, countryID, regionID, event.UserID, event.OccurredAtMS, nowMS); err != nil { return err @@ -1664,6 +1707,28 @@ func (r *Repository) ConsumeSelfGameH5Event(ctx context.Context, event SelfGameH } func (r *Repository) ConsumeAppTrackingEvents(ctx context.Context, events []AppTrackingEvent) (AppTrackingReportResult, error) { + var lastResult AppTrackingReportResult + var lastErr error + for attempt := 0; attempt < 5; attempt++ { + lastResult, lastErr = r.consumeAppTrackingEventsOnce(ctx, events) + if lastErr == nil || !isRetryableMySQLError(lastErr) { + return lastResult, lastErr + } + // Identity rows add one transactional lock per device. Concurrent batches + // can still deadlock with unrelated aggregate rows, so retry the entire + // idempotent batch just like owner-fact consumers do. + timer := time.NewTimer(time.Duration(attempt+1) * 50 * time.Millisecond) + select { + case <-ctx.Done(): + timer.Stop() + return AppTrackingReportResult{}, ctx.Err() + case <-timer.C: + } + } + return lastResult, lastErr +} + +func (r *Repository) consumeAppTrackingEventsOnce(ctx context.Context, events []AppTrackingEvent) (AppTrackingReportResult, error) { if r == nil || r.db == nil { return AppTrackingReportResult{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") } @@ -1672,25 +1737,37 @@ func (r *Repository) ConsumeAppTrackingEvents(ctx context.Context, events []AppT if !apptracking.ValidBatchSize(len(events)) { return AppTrackingReportResult{}, xerr.New(xerr.InvalidArgument, "app tracking events batch is invalid") } + // Device locks live until this batch commits. A stable device/event order + // makes two overlapping batches acquire them consistently and removes the + // common A->B / B->A deadlock without changing the idempotent response. + orderedEvents := append([]AppTrackingEvent(nil), events...) + sort.SliceStable(orderedEvents, func(i, j int) bool { + leftDevice, rightDevice := strings.TrimSpace(orderedEvents[i].DeviceID), strings.TrimSpace(orderedEvents[j].DeviceID) + if leftDevice != rightDevice { + return leftDevice < rightDevice + } + return strings.TrimSpace(orderedEvents[i].EventID) < strings.TrimSpace(orderedEvents[j].EventID) + }) tx, err := r.db.BeginTx(ctx, nil) if err != nil { return AppTrackingReportResult{}, err } defer func() { _ = tx.Rollback() }() - for _, event := range events { + for _, event := range orderedEvents { normalized, propertiesJSON, err := normalizeAppTrackingEvent(ctx, event, nowMS) if err != nil { return AppTrackingReportResult{}, err } affected, err := insertUnique(ctx, tx, ` - INSERT IGNORE INTO app_tracking_events ( - app_code, event_id, event_name, event_type, screen, target_type, target_id, - user_id, device_id, session_id, platform, app_version, language, timezone, - country_id, region_id, duration_ms, success, error_code, properties_json, - occurred_at_ms, received_at_ms, stat_day - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CAST(? AS JSON), ?, ?, ?) - `, normalized.AppCode, normalized.EventID, normalized.EventName, normalized.EventType, normalized.Screen, + INSERT IGNORE INTO app_tracking_events ( + app_code, event_id, event_name, event_type, screen, target_type, target_id, + user_id, device_id, session_id, client_session_id, auth_session_id, platform, app_version, language, timezone, + country_id, region_id, duration_ms, success, error_code, properties_json, + occurred_at_ms, received_at_ms, stat_day + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CAST(? AS JSON), ?, ?, ?) + `, normalized.AppCode, normalized.EventID, normalized.EventName, normalized.EventType, normalized.Screen, normalized.TargetType, normalized.TargetID, normalized.UserID, normalized.DeviceID, normalized.SessionID, + normalized.ClientSessionID, normalized.AuthSessionID, normalized.Platform, normalized.AppVersion, normalized.Language, normalized.Timezone, normalized.CountryID, normalized.RegionID, normalized.DurationMS, normalized.Success, normalized.ErrorCode, propertiesJSON, normalized.OccurredAtMS, nowMS, statDay(normalized.OccurredAtMS)) @@ -1699,6 +1776,11 @@ func (r *Repository) ConsumeAppTrackingEvents(ctx context.Context, events []AppT } if affected > 0 { result.Stored++ + // 身份观察和原始埋点、旧宽表必须在同一事务提交;否则页面可能短暂看到 + // 新 d:/u: 行却仍使用旧解析关系,造成 DAU 与留存随请求时点抖动。 + if err := applySocialTrackingIdentity(ctx, tx, normalized, nowMS); err != nil { + return AppTrackingReportResult{}, err + } for _, scope := range statDayScopesFromContext(ctx, normalized.OccurredAtMS) { delta, ok := socialDeltaForAppTrackingEvent(normalized, scope, nowMS) if !ok { @@ -2370,6 +2452,14 @@ func normalizeAppTrackingEvent(ctx context.Context, event AppTrackingEvent, rece if err != nil { return AppTrackingEvent{}, "", err } + event.ClientSessionID, err = normalizeAppTrackingText(event.ClientSessionID, apptracking.MaxSessionIDBytes) + if err != nil { + return AppTrackingEvent{}, "", err + } + event.AuthSessionID, err = normalizeAppTrackingText(event.AuthSessionID, apptracking.MaxSessionIDBytes) + if err != nil { + return AppTrackingEvent{}, "", err + } event.Platform, err = normalizeAppTrackingText(strings.ToLower(event.Platform), apptracking.MaxPlatformBytes) if err != nil { return AppTrackingEvent{}, "", err diff --git a/services/statistics-service/internal/storage/mysql/social_identity.go b/services/statistics-service/internal/storage/mysql/social_identity.go new file mode 100644 index 00000000..9a0985f9 --- /dev/null +++ b/services/statistics-service/internal/storage/mysql/social_identity.go @@ -0,0 +1,230 @@ +package mysql + +import ( + "context" + "database/sql" + "strings" + + "hyapp/pkg/appcode" +) + +const missingClientSessionID = "__missing_client_session__" + +type socialIdentityDayKey struct { + StatTZ string + StatDay string +} + +// applySocialTrackingIdentity records only identity evidence. It deliberately +// never moves or rewrites stat_social_user_day rows: that table contains additive +// money and duration fields which cannot be safely undone when events arrive out +// of order. Query-time canonicalization consumes the small day-resolution table +// and leaves the financial read model untouched. +func applySocialTrackingIdentity(ctx context.Context, tx *sql.Tx, event AppTrackingEvent, nowMS int64) error { + app := appcode.Normalize(event.AppCode) + deviceID := strings.TrimSpace(event.DeviceID) + clientSessionID := strings.TrimSpace(event.ClientSessionID) + if app == "" || deviceID == "" { + return nil + } + + if event.UserID <= 0 { + // Only events that actually create a d: row may participate in the + // device-day resolution. page_open and failed actions otherwise introduce + // phantom unresolved sessions that permanently block a valid login merge. + contributesSocialRow := false + for _, scope := range statDayScopesFromContext(ctx, event.OccurredAtMS) { + if _, ok := socialDeltaForAppTrackingEvent(event, scope, nowMS); ok { + contributesSocialRow = true + break + } + } + if !contributesSocialRow { + return nil + } + } else if clientSessionID == "" { + // Old authenticated clients still produce a direct u: fact, but without + // the process session they cannot link any earlier anonymous row. Return + // before taking a device lock on this high-volume compatibility path. + return nil + } + if err := lockSocialIdentityDevice(ctx, tx, app, deviceID, nowMS); err != nil { + return err + } + + if event.UserID <= 0 { + // Old clients do not send client_session_id. A single unresolved sentinel + // per device/day blocks a different resolved session from swallowing those + // anonymous events; conservative under-count correction is safer than a + // false account merge on shared devices. + if clientSessionID == "" { + clientSessionID = missingClientSessionID + } + for _, scope := range statDayScopesFromContext(ctx, event.OccurredAtMS) { + affected, err := insertUnique(ctx, tx, ` + INSERT IGNORE INTO stat_social_identity_session_day ( + app_code, stat_tz, stat_day, device_id, client_session_id, first_seen_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?) + `, app, scope.tz, scope.day, deviceID, clientSessionID, event.OccurredAtMS, nowMS) + if err != nil { + return err + } + if affected > 0 { + if err := recomputeSocialIdentityDay(ctx, tx, app, scope.tz, scope.day, deviceID, nowMS); err != nil { + return err + } + } + } + return nil + } + + inserted, err := insertUnique(ctx, tx, ` + INSERT IGNORE INTO stat_social_identity_session_user ( + app_code, device_id, client_session_id, user_id, first_seen_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?) + `, app, deviceID, clientSessionID, normalizeID(event.UserID), event.OccurredAtMS, nowMS) + if err != nil || inserted == 0 { + return err + } + + // A session can cross a Beijing/UTC midnight. When its first authenticated + // event arrives, recompute every earlier anonymous day observed for that same + // device+client session so D1/D3/D7 retention sees one canonical account. + rows, err := tx.QueryContext(ctx, ` + SELECT stat_tz, DATE_FORMAT(stat_day, '%Y-%m-%d') + FROM stat_social_identity_session_day + WHERE app_code = ? AND device_id = ? AND client_session_id = ? + ORDER BY stat_tz, stat_day + FOR UPDATE + `, app, deviceID, clientSessionID) + if err != nil { + return err + } + days := make([]socialIdentityDayKey, 0, 2) + for rows.Next() { + var key socialIdentityDayKey + if err := rows.Scan(&key.StatTZ, &key.StatDay); err != nil { + _ = rows.Close() + return err + } + days = append(days, key) + } + if err := rows.Err(); err != nil { + _ = rows.Close() + return err + } + if err := rows.Close(); err != nil { + return err + } + for _, day := range days { + if err := recomputeSocialIdentityDay(ctx, tx, app, day.StatTZ, day.StatDay, deviceID, nowMS); err != nil { + return err + } + } + return nil +} + +func recomputeSocialIdentityDay(ctx context.Context, tx *sql.Tx, app, statTZ, statDay, deviceID string, nowMS int64) error { + rows, err := tx.QueryContext(ctx, ` + SELECT d.client_session_id, u.user_id + FROM stat_social_identity_session_day d + LEFT JOIN stat_social_identity_session_user u + ON u.app_code = d.app_code + AND u.device_id = d.device_id + AND u.client_session_id = d.client_session_id + WHERE d.app_code = ? AND d.stat_tz = ? AND d.stat_day = ? AND d.device_id = ? + ORDER BY d.client_session_id, u.user_id + FOR UPDATE + `, app, normalizeStatTZ(statTZ), statDay, deviceID) + if err != nil { + return err + } + sessionUsers := map[string]map[int64]struct{}{} + for rows.Next() { + var sessionID string + var userID sql.NullInt64 + if err := rows.Scan(&sessionID, &userID); err != nil { + _ = rows.Close() + return err + } + if sessionUsers[sessionID] == nil { + sessionUsers[sessionID] = map[int64]struct{}{} + } + if userID.Valid && userID.Int64 > 0 { + sessionUsers[sessionID][userID.Int64] = struct{}{} + } + } + if err := rows.Err(); err != nil { + _ = rows.Close() + return err + } + if err := rows.Close(); err != nil { + return err + } + + state, resolvedUserID := "unresolved", int64(0) + resolutionSource := "client_session" + ambiguous := false + unresolved := false + for _, users := range sessionUsers { + if len(users) == 0 { + unresolved = true + continue + } + if len(users) > 1 { + ambiguous = true + continue + } + for userID := range users { + if resolvedUserID == 0 { + resolvedUserID = userID + } else if resolvedUserID != userID { + ambiguous = true + } + } + } + if ambiguous { + state, resolvedUserID = "ambiguous", 0 + } else if !unresolved && len(sessionUsers) > 0 && resolvedUserID > 0 { + state = "resolved" + } else { + resolvedUserID = 0 + } + if len(sessionUsers) == 1 { + if _, onlyMissingSession := sessionUsers[missingClientSessionID]; onlyMissingSession { + // A legacy client cannot establish an exact session bridge. Keep that + // evidence conservative, but let a later bounded historical replay + // replace it instead of giving it permanent client-session authority. + resolutionSource = "missing_client_session" + } + } + + _, err = tx.ExecContext(ctx, ` + INSERT INTO stat_social_identity_day ( + app_code, stat_tz, stat_day, device_id, resolved_user_id, + resolution_state, resolution_source, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + resolved_user_id = VALUES(resolved_user_id), + resolution_state = VALUES(resolution_state), + resolution_source = VALUES(resolution_source), + updated_at_ms = VALUES(updated_at_ms) + `, app, normalizeStatTZ(statTZ), statDay, deviceID, resolvedUserID, state, resolutionSource, nowMS) + return err +} + +func lockSocialIdentityDevice(ctx context.Context, tx *sql.Tx, app, deviceID string, nowMS int64) error { + if _, err := tx.ExecContext(ctx, ` + INSERT IGNORE INTO stat_social_identity_device_lock (app_code, device_id, created_at_ms) + VALUES (?, ?, ?) + `, appcode.Normalize(app), strings.TrimSpace(deviceID), nowMS); err != nil { + return err + } + var lockedDeviceID string + return tx.QueryRowContext(ctx, ` + SELECT device_id + FROM stat_social_identity_device_lock + WHERE app_code = ? AND device_id = ? + FOR UPDATE + `, appcode.Normalize(app), strings.TrimSpace(deviceID)).Scan(&lockedDeviceID) +} diff --git a/services/statistics-service/internal/storage/mysql/social_requirements_query.go b/services/statistics-service/internal/storage/mysql/social_requirements_query.go index 7ffeb34e..4a18406a 100644 --- a/services/statistics-service/internal/storage/mysql/social_requirements_query.go +++ b/services/statistics-service/internal/storage/mysql/social_requirements_query.go @@ -101,6 +101,9 @@ type socialRequirementUserDay struct { StatDay string Subject string UserID int64 + DirectUser bool + DeviceID string + CountryID int64 RegionID int64 UserRole string AppFirstOpen int64 @@ -218,6 +221,12 @@ type retentionMetric struct { Users int64 } +// retention-only 请求只需要这些身份、筛选和留存行为列。保持投影集中定义, +// 避免后续无意把金额、时长等约 50 列重新带回最长 61 天的留存扫描。 +const socialRetentionUserDayProjection = `DATE_FORMAT(stat_day, '%Y-%m-%d'), subject_key, user_id, device_id, + country_id, region_id, user_role, registered_success, active_user, + room_join_success, mic_up_success, gift_sent, recharge_user, game_bet_user` + func (r *Repository) QuerySocialRequirements(ctx context.Context, query SocialRequirementsQuery) (SocialRequirements, error) { app := appcode.Normalize(query.AppCode) if app == "" { @@ -234,14 +243,28 @@ func (r *Repository) QuerySocialRequirements(ctx context.Context, query SocialRe } startDay := statDayIn(startMS, statTZ) endDay := statDayIn(endMS-1, statTZ) + observableDay := statDayIn(time.Now().UnixMilli(), statTZ) days := socialDayRange(startDay, endDay) - // 留存指标需要读取 cohort 日之后的 D30 行;这些仍是本服务已沉淀的用户日宽表,不回查 owner service。 - rows, err := r.querySocialUserDays(ctx, app, statTZ, startDay, addStatDays(endDay, 30), query.CountryID, query.RegionID, query.RegionIDs) + sections := socialRequestedSections(query.Section) + lookaheadDays := socialRetentionLookaheadDays(sections) + // 只有 P0 次留或 P2 留存需要读取查询结束日之后的观察行;单独查看活跃、 + // 营收、送礼、游戏时不再固定多扫 30 天的 50 列用户日宽表。 + queryEndDay := addStatDays(endDay, lookaheadDays) + var allRows []socialRequirementUserDay + var err error + if len(sections) == 1 && sections[0] == SocialSectionRetention { + allRows, err = r.querySocialRetentionUserDays(ctx, app, statTZ, startDay, queryEndDay) + } else { + allRows, err = r.querySocialUserDays(ctx, app, statTZ, startDay, queryEndDay, 0, 0, nil) + } if err != nil { return SocialRequirements{}, err } - byDay, bySubjectDay := indexSocialRows(rows) - sections := socialRequestedSections(query.Section) + rows := filterSocialRequirementUserDays(allRows, query.CountryID, query.RegionID, query.RegionIDs) + byDay, _ := indexSocialRows(rows) + // 区域只筛 cohort 基准日;D+N 观察日保留完整 canonical 活跃索引。 + // 用户次日跨区仍算回来,不能因为目标日维度不同被误判为流失。 + _, bySubjectDay := indexSocialRows(allRows) var gameBreakdown []SocialRequirementGame for _, section := range sections { if section == SocialSectionGame { @@ -264,17 +287,28 @@ func (r *Repository) QuerySocialRequirements(ctx context.Context, query SocialRe } for _, section := range sections { sectionRows := make([]SocialRequirementRow, 0, len(days)) + averageRows := make([]SocialRequirementRow, 0, len(days)) totalAgg := socialRequirementAggregate{} totalRetention := map[string]retentionMetric{} for _, day := range days { agg := aggregateSocialRows(byDay[day], section, query.UserRole, query.PayerType, query.NewUserType) totalAgg.add(agg) - retention := socialRetentionMetrics(day, byDay[day], bySubjectDay, section, query.UserRole, query.PayerType, query.NewUserType) + retention := map[string]retentionMetric{} + if socialSectionNeedsRetention(section) { + retention = socialRetentionMetrics(day, observableDay, byDay[day], bySubjectDay, section, query.UserRole, query.PayerType, query.NewUserType) + } mergeRetentionMetrics(totalRetention, retention) + metrics := socialSectionMetrics(section, agg, retention) + averageRows = append(averageRows, SocialRequirementRow{StatDay: day, Label: day, Metrics: metrics}) + // 日行始终展示基准日 canonical DAU,方便当前日判断 cohort 规模; + // 汇总和平均仍使用注入前的 metrics,只合并已经到达观察日的 cohort。 + if section == SocialSectionRetention { + metrics = socialRetentionDailyMetrics(metrics, byDay[day], query.UserRole, query.PayerType, query.NewUserType) + } sectionRows = append(sectionRows, SocialRequirementRow{ StatDay: day, Label: day, - Metrics: socialSectionMetrics(section, agg, retention), + Metrics: metrics, }) } sectionOut := SocialRequirementSection{ @@ -288,7 +322,7 @@ func (r *Repository) QuerySocialRequirements(ctx context.Context, query SocialRe Columns: socialRequirementColumns(section), MetricDefinitions: socialRequirementMetricDefinitions(section), Total: SocialRequirementRow{StatDay: "total", Label: "汇总", Metrics: socialSectionMetrics(section, totalAgg, totalRetention)}, - Average: socialAverageRow(sectionRows), + Average: socialAverageRow(averageRows), DailySeries: sectionRows, } if section == SocialSectionGame { @@ -326,26 +360,31 @@ func socialAverageRow(rows []SocialRequirementRow) SocialRequirementRow { return SocialRequirementRow{StatDay: "average", Label: "平均值", Metrics: metrics} } +func socialRetentionLookaheadDays(sections []string) int { + lookahead := 0 + for _, section := range sections { + switch section { + case SocialSectionRetention: + return 30 + case SocialSectionNewUsers: + lookahead = 1 + } + } + return lookahead +} + +func socialSectionNeedsRetention(section string) bool { + return section == SocialSectionRetention || section == SocialSectionNewUsers +} + func (r *Repository) querySocialUserDays(ctx context.Context, app string, statTZ string, startDay string, endDay string, countryID int64, regionID int64, regionIDs []int64) ([]socialRequirementUserDay, error) { args := []any{appcode.Normalize(app), normalizeStatTZ(statTZ), startDay, endDay} conditions := []string{"app_code = ?", "stat_tz = ?", "stat_day BETWEEN ? AND ?"} - if countryID > 0 { - conditions = append(conditions, "country_id = ?") - args = append(args, countryID) - } - if regionID > 0 { - conditions = append(conditions, "region_id = ?") - args = append(args, regionID) - } else if ids := normalizePositiveIDs(regionIDs); len(ids) > 0 { - placeholders := make([]string, 0, len(ids)) - for _, id := range ids { - placeholders = append(placeholders, "?") - args = append(args, id) - } - conditions = append(conditions, "region_id IN ("+strings.Join(placeholders, ",")+")") - } + // 匿名行通常没有国家/区域,而登录后的 u: 行才带用户维度。必须先在完整 + // app+day 小宽表范围内完成 canonical 合并,再应用维度过滤;提前在 SQL 里 + // 过滤会丢掉同一用户登录前的活跃,并让区域 DAU 再次出现 d/u 口径偏差。 rows, err := r.db.QueryContext(ctx, ` - SELECT DATE_FORMAT(stat_day, '%Y-%m-%d'), subject_key, user_id, region_id, user_role, + SELECT DATE_FORMAT(stat_day, '%Y-%m-%d'), subject_key, user_id, device_id, country_id, region_id, user_role, app_first_open, registered_success, active_user, room_join_success, room_join_fail, mic_up_success, gift_sent, normal_gift_sent, lucky_gift_sent, super_lucky_gift_sent, recharge_user, first_recharge_user, repeat_recharge_user, game_bet_user, self_game_bet_user, @@ -367,7 +406,7 @@ func (r *Repository) querySocialUserDays(ctx context.Context, app string, statTZ out := []socialRequirementUserDay{} for rows.Next() { var item socialRequirementUserDay - if err := rows.Scan(&item.StatDay, &item.Subject, &item.UserID, &item.RegionID, &item.UserRole, + if err := rows.Scan(&item.StatDay, &item.Subject, &item.UserID, &item.DeviceID, &item.CountryID, &item.RegionID, &item.UserRole, &item.AppFirstOpen, &item.Registered, &item.Active, &item.RoomJoinOK, &item.RoomJoinNG, &item.MicUp, &item.Gift, &item.NormalGift, &item.LuckyGift, &item.SuperGift, &item.Recharge, &item.FirstRecharge, &item.RepeatRecharge, &item.GameBet, &item.SelfGameBet, @@ -380,19 +419,349 @@ func (r *Repository) querySocialUserDays(ctx context.Context, app string, statTZ &item.OtherConsumeCoin, &item.OutputCoin); err != nil { return nil, err } - // 在房时长口径:客户端 room_stay 埋点(杀进程/闪退整段丢失)和服务端进退房事实 room_online_ms - // 双轨并存,取 GREATEST 避免切换期数据断层;埋点按 app 版本灰度下线后该口径自然收敛到服务端事实。 - if item.RoomStayMS < item.RoomOnlineMS { - item.RoomStayMS = item.RoomOnlineMS - } - // 在房时长下界修正:上麦必在房内,麦时长(服务端事实,权威)是房时长的天然下界。 - // 服务端在房事实上线后保留该钳制作为兜底(如回灌历史区间尚无服务端事实)。 - if item.RoomStayMS < item.MicStayMS { - item.RoomStayMS = item.MicStayMS - } + item.DirectUser = item.UserID > 0 out = append(out, item) } - return out, rows.Err() + if err := rows.Err(); err != nil { + return nil, err + } + identityByDeviceDay, err := r.querySocialIdentityDays(ctx, app, statTZ, startDay, endDay) + if err != nil { + return nil, err + } + return canonicalizeSocialUserDays(out, identityByDeviceDay, countryID, regionID, regionIDs), nil +} + +// querySocialRetentionUserDays keeps the full identity population until after +// d:/u: canonicalization. Country/region and role/payer/new-user filters cannot +// be pushed into SQL because the authoritative dimensions may live only on the +// logged-in u: row while the anonymous d: row carries part of the activity. +func (r *Repository) querySocialRetentionUserDays(ctx context.Context, app, statTZ, startDay, endDay string) ([]socialRequirementUserDay, error) { + rows, err := r.db.QueryContext(ctx, ` + SELECT `+socialRetentionUserDayProjection+` + FROM stat_social_user_day + WHERE app_code = ? AND stat_tz = ? AND stat_day BETWEEN ? AND ? + ORDER BY stat_day, subject_key + `, appcode.Normalize(app), normalizeStatTZ(statTZ), startDay, endDay) + if err != nil { + return nil, err + } + defer rows.Close() + + out := []socialRequirementUserDay{} + for rows.Next() { + var item socialRequirementUserDay + if err := rows.Scan( + &item.StatDay, &item.Subject, &item.UserID, &item.DeviceID, + &item.CountryID, &item.RegionID, &item.UserRole, &item.Registered, &item.Active, + &item.RoomJoinOK, &item.MicUp, &item.Gift, &item.Recharge, &item.GameBet, + ); err != nil { + return nil, err + } + item.DirectUser = item.UserID > 0 + out = append(out, item) + } + if err := rows.Err(); err != nil { + return nil, err + } + + identityByDeviceDay, err := r.querySocialIdentityDays(ctx, app, statTZ, startDay, endDay) + if err != nil { + return nil, err + } + return canonicalizeSocialUserDays(out, identityByDeviceDay, 0, 0, nil), nil +} + +type socialIdentityDeviceDayKey struct { + StatDay string + DeviceID string +} + +// canonicalOverviewActiveDimension is the compact DAU projection consumed by +// the operation-wide overview. ActiveUsers is a sum of canonical user-days; +// RegionID follows the existing country-breakdown contract where one country +// row carries the greatest observed region ID after the requested region filter. +type canonicalOverviewActiveDimension struct { + ActiveUsers int64 + RegionID int64 +} + +type canonicalOverviewActiveCube struct { + Total int64 + ByDay map[string]int64 + ByCountry map[int64]canonicalOverviewActiveDimension + ByDayCountry map[string]canonicalOverviewActiveDimension +} + +func newCanonicalOverviewActiveCube() canonicalOverviewActiveCube { + return canonicalOverviewActiveCube{ + ByDay: map[string]int64{}, + ByCountry: map[int64]canonicalOverviewActiveDimension{}, + ByDayCountry: map[string]canonicalOverviewActiveDimension{}, + } +} + +// queryCanonicalOverviewActiveCube deliberately reads only the identity and +// dimension columns needed by DAU. The PK prefixes bound both scans by +// app+timezone+day; canonicalization stays in memory because a direct SQL SUM +// would count the same session once as d: and again as u:. +func (r *Repository) queryCanonicalOverviewActiveCube(ctx context.Context, app, statTZ, startDay, endDay string, countryID, regionID int64) (canonicalOverviewActiveCube, error) { + rows, err := r.db.QueryContext(ctx, ` + SELECT DATE_FORMAT(stat_day, '%Y-%m-%d'), subject_key, user_id, device_id, + country_id, region_id, user_role, active_user + FROM stat_social_user_day + WHERE app_code = ? AND stat_tz = ? AND stat_day BETWEEN ? AND ? + AND (active_user > 0 OR user_id > 0) + ORDER BY stat_day, subject_key + `, appcode.Normalize(app), normalizeStatTZ(statTZ), startDay, endDay) + if err != nil { + return canonicalOverviewActiveCube{}, err + } + defer rows.Close() + + userDays := []socialRequirementUserDay{} + for rows.Next() { + var item socialRequirementUserDay + if err := rows.Scan(&item.StatDay, &item.Subject, &item.UserID, &item.DeviceID, + &item.CountryID, &item.RegionID, &item.UserRole, &item.Active); err != nil { + return canonicalOverviewActiveCube{}, err + } + item.DirectUser = item.UserID > 0 + userDays = append(userDays, item) + } + if err := rows.Err(); err != nil { + return canonicalOverviewActiveCube{}, err + } + + identityByDeviceDay, err := r.querySocialIdentityDays(ctx, app, statTZ, startDay, endDay) + if err != nil { + return canonicalOverviewActiveCube{}, err + } + canonicalRows := canonicalizeSocialUserDays(userDays, identityByDeviceDay, countryID, regionID, nil) + return buildCanonicalOverviewActiveCube(canonicalRows), nil +} + +func buildCanonicalOverviewActiveCube(canonicalRows []socialRequirementUserDay) canonicalOverviewActiveCube { + cube := newCanonicalOverviewActiveCube() + for _, row := range canonicalRows { + if row.Active <= 0 { + continue + } + cube.Total++ + cube.ByDay[row.StatDay]++ + // 匿名设备在无法安全归并到账号时仍属于真实 DAU,因此保留在总计和按日总计;country_id=0 + // 只是“尚无国家维度”,不是一个国家。国家/按日国家明细只能承载有效国家,不能把 0 暴露成伪国家。 + if row.CountryID <= 0 { + continue + } + + country := cube.ByCountry[row.CountryID] + country.ActiveUsers++ + if row.RegionID > country.RegionID { + country.RegionID = row.RegionID + } + cube.ByCountry[row.CountryID] = country + + dayCountryKey := dailyCountryKey(row.StatDay, row.CountryID) + dayCountry := cube.ByDayCountry[dayCountryKey] + dayCountry.ActiveUsers++ + if row.RegionID > dayCountry.RegionID { + dayCountry.RegionID = row.RegionID + } + cube.ByDayCountry[dayCountryKey] = dayCountry + } + return cube +} + +func (r *Repository) querySocialIdentityDays(ctx context.Context, app, statTZ, startDay, endDay string) (map[socialIdentityDeviceDayKey]int64, error) { + rows, err := r.db.QueryContext(ctx, ` + SELECT DATE_FORMAT(stat_day, '%Y-%m-%d'), device_id, resolved_user_id + FROM stat_social_identity_day + WHERE app_code = ? AND stat_tz = ? AND stat_day BETWEEN ? AND ? + AND resolution_state = 'resolved' AND resolved_user_id > 0 + `, appcode.Normalize(app), normalizeStatTZ(statTZ), startDay, endDay) + if err != nil { + return nil, err + } + defer rows.Close() + resolved := map[socialIdentityDeviceDayKey]int64{} + for rows.Next() { + var day, deviceID string + var userID int64 + if err := rows.Scan(&day, &deviceID, &userID); err != nil { + return nil, err + } + if deviceID = strings.TrimSpace(deviceID); deviceID != "" && userID > 0 { + resolved[socialIdentityDeviceDayKey{StatDay: day, DeviceID: deviceID}] = userID + } + } + return resolved, rows.Err() +} + +// canonicalizeSocialUserDays keeps stat_social_user_day as the immutable source +// of financial/duration facts and only rewrites identity in memory. This avoids +// destructive primary-key moves and keeps a replay idempotent even when late +// events or an account switch changes the device-day resolution. +func canonicalizeSocialUserDays(rows []socialRequirementUserDay, resolved map[socialIdentityDeviceDayKey]int64, countryID, regionID int64, regionIDs []int64) []socialRequirementUserDay { + merged := map[string]socialRequirementUserDay{} + firstOpenDevices := map[string]map[string]struct{}{} + for _, row := range rows { + if row.UserID <= 0 { + if userID := resolved[socialIdentityDeviceDayKey{StatDay: row.StatDay, DeviceID: strings.TrimSpace(row.DeviceID)}]; userID > 0 { + row.UserID = userID + row.Subject = "u:" + strconv.FormatInt(userID, 10) + } + } + key := row.StatDay + "\x00" + row.Subject + if row.AppFirstOpen > 0 { + deviceID := strings.TrimSpace(row.DeviceID) + if deviceID == "" { + // Old u: rows may not retain a device. Use the physical subject as a + // stable one-count fallback; known d/u rows still dedupe by device ID. + deviceID = "subject:" + row.Subject + } + if firstOpenDevices[key] == nil { + firstOpenDevices[key] = map[string]struct{}{} + } + firstOpenDevices[key][deviceID] = struct{}{} + } + if current, ok := merged[key]; ok { + merged[key] = mergeSocialRequirementUserDay(current, row) + } else { + merged[key] = row + } + } + out := make([]socialRequirementUserDay, 0, len(merged)) + for key, row := range merged { + row.AppFirstOpen = int64(len(firstOpenDevices[key])) + // Client room_stay and authoritative server room_online are parallel + // measurements, not additive copies. Clamp only after d:/u: fields have + // been summed so the same interval is not counted twice. + if row.RoomStayMS < row.RoomOnlineMS { + row.RoomStayMS = row.RoomOnlineMS + } + if row.RoomStayMS < row.MicStayMS { + row.RoomStayMS = row.MicStayMS + } + out = append(out, row) + } + sort.Slice(out, func(i, j int) bool { + if out[i].StatDay != out[j].StatDay { + return out[i].StatDay < out[j].StatDay + } + return out[i].Subject < out[j].Subject + }) + return filterSocialRequirementUserDays(out, countryID, regionID, regionIDs) +} + +func mergeSocialRequirementUserDay(current, next socialRequirementUserDay) socialRequirementUserDay { + if current.UserID == 0 { + current.UserID = next.UserID + } + if current.DeviceID == "" { + current.DeviceID = next.DeviceID + } + // Country and region are one dimension tuple. A direct same-day u: row is + // authoritative only when it carries a real country; a legacy row with just a + // region cannot erase the anonymous row's known country because region alone + // has no valid country ownership semantics. No cross-day dimension is borrowed. + if next.DirectUser && !current.DirectUser { + if next.CountryID > 0 { + current.CountryID, current.RegionID = next.CountryID, next.RegionID + } + current.UserRole = next.UserRole + current.DirectUser = true + } else if next.DirectUser == current.DirectUser { + if current.CountryID == 0 && current.RegionID == 0 && (next.CountryID > 0 || next.RegionID > 0) { + current.CountryID, current.RegionID = next.CountryID, next.RegionID + } + if normalizeSocialUserRole(next.UserRole) == "host" { + current.UserRole = next.UserRole + } + } + // canonicalizeSocialUserDays replaces this flag with the distinct known + // device count after all rows merge; MAX is only the empty-device fallback. + current.AppFirstOpen = maxSocialFlag(current.AppFirstOpen, next.AppFirstOpen) + current.Registered = maxSocialFlag(current.Registered, next.Registered) + current.Active = maxSocialFlag(current.Active, next.Active) + current.RoomJoinOK = maxSocialFlag(current.RoomJoinOK, next.RoomJoinOK) + current.RoomJoinNG = maxSocialFlag(current.RoomJoinNG, next.RoomJoinNG) + current.MicUp = maxSocialFlag(current.MicUp, next.MicUp) + current.Gift = maxSocialFlag(current.Gift, next.Gift) + current.NormalGift = maxSocialFlag(current.NormalGift, next.NormalGift) + current.LuckyGift = maxSocialFlag(current.LuckyGift, next.LuckyGift) + current.SuperGift = maxSocialFlag(current.SuperGift, next.SuperGift) + current.Recharge = maxSocialFlag(current.Recharge, next.Recharge) + current.FirstRecharge = maxSocialFlag(current.FirstRecharge, next.FirstRecharge) + current.RepeatRecharge = maxSocialFlag(current.RepeatRecharge, next.RepeatRecharge) + current.GameBet = maxSocialFlag(current.GameBet, next.GameBet) + current.SelfGameBet = maxSocialFlag(current.SelfGameBet, next.SelfGameBet) + current.ProbabilityBet = maxSocialFlag(current.ProbabilityBet, next.ProbabilityBet) + current.Chat = maxSocialFlag(current.Chat, next.Chat) + current.FollowUser = maxSocialFlag(current.FollowUser, next.FollowUser) + current.FollowRoom = maxSocialFlag(current.FollowRoom, next.FollowRoom) + current.GiftPanel = maxSocialFlag(current.GiftPanel, next.GiftPanel) + current.ProbabilityPanel = maxSocialFlag(current.ProbabilityPanel, next.ProbabilityPanel) + current.AppStayMS += next.AppStayMS + current.RoomStayMS += next.RoomStayMS + current.RoomOnlineMS += next.RoomOnlineMS + current.MicStayMS += next.MicStayMS + current.RechargeCount += next.RechargeCount + current.RechargeUSDMinor += next.RechargeUSDMinor + current.GoogleRechargeUSDMinor += next.GoogleRechargeUSDMinor + current.ThirdPartyRechargeUSDMinor += next.ThirdPartyRechargeUSDMinor + current.CoinSellerRechargeUSDMinor += next.CoinSellerRechargeUSDMinor + current.FirstRechargeUSDMinor += next.FirstRechargeUSDMinor + current.RepeatRechargeUSDMinor += next.RepeatRechargeUSDMinor + current.NormalGiftCoin += next.NormalGiftCoin + current.LuckyGiftCoin += next.LuckyGiftCoin + current.SuperGiftCoin += next.SuperGiftCoin + current.LuckyGiftPayoutCoin += next.LuckyGiftPayoutCoin + current.SuperGiftPayoutCoin += next.SuperGiftPayoutCoin + current.GameBetCoin += next.GameBetCoin + current.GameBetCount += next.GameBetCount + current.SelfGameBetCoin += next.SelfGameBetCoin + current.SelfGameBetCount += next.SelfGameBetCount + current.ProbabilityBetCoin += next.ProbabilityBetCoin + current.ProbabilityBetCount += next.ProbabilityBetCount + current.OtherConsumeCoin += next.OtherConsumeCoin + current.OutputCoin += next.OutputCoin + return current +} + +func maxSocialFlag(left, right int64) int64 { + if right > left { + return right + } + return left +} + +func filterSocialRequirementUserDays(rows []socialRequirementUserDay, countryID, regionID int64, regionIDs []int64) []socialRequirementUserDay { + allowedRegions := map[int64]struct{}{} + if regionID <= 0 { + for _, id := range normalizePositiveIDs(regionIDs) { + allowedRegions[id] = struct{}{} + } + } + if countryID <= 0 && regionID <= 0 && len(allowedRegions) == 0 { + return rows + } + out := make([]socialRequirementUserDay, 0, len(rows)) + for _, row := range rows { + if countryID > 0 && row.CountryID != countryID { + continue + } + if regionID > 0 && row.RegionID != regionID { + continue + } + if len(allowedRegions) > 0 { + if _, ok := allowedRegions[row.RegionID]; !ok { + continue + } + } + out = append(out, row) + } + return out } func indexSocialRows(rows []socialRequirementUserDay) (map[string][]socialRequirementUserDay, map[string]map[string]socialRequirementUserDay) { @@ -414,7 +783,9 @@ func aggregateSocialRows(rows []socialRequirementUserDay, section string, role s if !socialRowMatchesSection(row, section, role, payerType, newUserType) { continue } - agg.AppFirstOpen += flagValue(row.AppFirstOpen) + // 下载/首次打开是设备口径;身份归并只消除用户行为的 d/u 重复, + // 不能把同一账号在两台设备上的两次安装压成 1。 + agg.AppFirstOpen += normalizeID(row.AppFirstOpen) agg.Registered += flagValue(row.Registered) if flagValue(row.Registered) > 0 && normalizeSocialUserRole(row.UserRole) == "host" { agg.NewHostUsers++ @@ -568,8 +939,9 @@ func (a *socialRequirementAggregate) add(other socialRequirementAggregate) { a.OutputCoin += other.OutputCoin } -func socialRetentionMetrics(day string, rows []socialRequirementUserDay, bySubjectDay map[string]map[string]socialRequirementUserDay, section string, role string, payerType string, newUserType string) map[string]retentionMetric { +func socialRetentionMetrics(day string, observableDay string, rows []socialRequirementUserDay, bySubjectDay map[string]map[string]socialRequirementUserDay, section string, role string, payerType string, newUserType string) map[string]retentionMetric { out := map[string]retentionMetric{} + d1Observable := addStatDays(day, 1) <= observableDay for _, row := range rows { if !socialRowMatchesSection(row, section, role, payerType, newUserType) { continue @@ -577,34 +949,36 @@ func socialRetentionMetrics(day string, rows []socialRequirementUserDay, bySubje // 文档口径:用户次留/3/7/15/30日留以「当日全体活跃用户」为基数,次日继续活跃算留存; // 新用户(注册 cohort)留存只保留在 P0 的分身份次留里。 for _, offset := range []int{1, 3, 7, 15, 30} { - if row.Active > 0 { + // D+N 尚未到达时,缺少目标日事实表示“不可观察”,不能当成 0 人回访。 + // 不创建 metric key 可让日行显示空值,并让汇总/平均自然排除未成熟 cohort。 + if row.Active > 0 && addStatDays(day, offset) <= observableDay { addSocialRetention(out, "active_d"+intLabel(offset)+"_active", row, bySubjectDay, offset, func(target socialRequirementUserDay) bool { return target.Active > 0 }) } } - if row.RoomJoinOK > 0 { + if d1Observable && row.RoomJoinOK > 0 { addSocialRetention(out, "after_room_d1_active", row, bySubjectDay, 1, func(target socialRequirementUserDay) bool { return target.Active > 0 }) addSocialRetention(out, "after_room_d1_room", row, bySubjectDay, 1, func(target socialRequirementUserDay) bool { return target.RoomJoinOK > 0 }) } - if row.MicUp > 0 { + if d1Observable && row.MicUp > 0 { addSocialRetention(out, "after_mic_d1_active", row, bySubjectDay, 1, func(target socialRequirementUserDay) bool { return target.Active > 0 }) addSocialRetention(out, "after_mic_d1_mic", row, bySubjectDay, 1, func(target socialRequirementUserDay) bool { return target.MicUp > 0 }) } - if row.Gift > 0 { + if d1Observable && row.Gift > 0 { addSocialRetention(out, "after_gift_d1_active", row, bySubjectDay, 1, func(target socialRequirementUserDay) bool { return target.Active > 0 }) addSocialRetention(out, "after_gift_d1_gift", row, bySubjectDay, 1, func(target socialRequirementUserDay) bool { return target.Gift > 0 }) } - if row.GameBet > 0 { + if d1Observable && row.GameBet > 0 { addSocialRetention(out, "after_game_d1_active", row, bySubjectDay, 1, func(target socialRequirementUserDay) bool { return target.Active > 0 }) addSocialRetention(out, "after_game_d1_game", row, bySubjectDay, 1, func(target socialRequirementUserDay) bool { return target.GameBet > 0 }) } - if row.Recharge > 0 { + if d1Observable && row.Recharge > 0 { addSocialRetention(out, "after_recharge_d1_active", row, bySubjectDay, 1, func(target socialRequirementUserDay) bool { return target.Active > 0 }) addSocialRetention(out, "after_recharge_d1_recharge", row, bySubjectDay, 1, func(target socialRequirementUserDay) bool { return target.Recharge > 0 }) } - if row.Registered > 0 && normalizeSocialUserRole(row.UserRole) == "host" { + if d1Observable && row.Registered > 0 && normalizeSocialUserRole(row.UserRole) == "host" { addSocialRetention(out, "new_host_d1_active", row, bySubjectDay, 1, func(target socialRequirementUserDay) bool { return target.Active > 0 }) } - if row.Registered > 0 && normalizeSocialUserRole(row.UserRole) != "host" { + if d1Observable && row.Registered > 0 && normalizeSocialUserRole(row.UserRole) != "host" { addSocialRetention(out, "new_user_d1_active", row, bySubjectDay, 1, func(target socialRequirementUserDay) bool { return target.Active > 0 }) } } @@ -629,6 +1003,26 @@ func mergeRetentionMetrics(total map[string]retentionMetric, next map[string]ret } } +// socialRetentionDailyMetrics adds the cohort size independently from the +// observation result. This lets an immature day expose its canonical DAU base +// while users/rate remain absent; aggregate rows keep using only mature metrics. +func socialRetentionDailyMetrics(mature map[string]any, rows []socialRequirementUserDay, role, payerType, newUserType string) map[string]any { + out := make(map[string]any, len(mature)+5) + for key, value := range mature { + out[key] = value + } + var base int64 + for _, row := range rows { + if row.Active > 0 && socialRowMatchesSection(row, SocialSectionRetention, role, payerType, newUserType) { + base++ + } + } + for _, offset := range []int{1, 3, 7, 15, 30} { + out["active_d"+intLabel(offset)+"_active_base_users"] = base + } + return out +} + func socialSectionMetrics(section string, agg socialRequirementAggregate, retention map[string]retentionMetric) map[string]any { switch section { case SocialSectionRevenue: @@ -722,24 +1116,24 @@ func socialSectionMetrics(section string, agg socialRequirementAggregate, retent "probability_game_bet_arppu_coin": div(agg.ProbabilityBetCoin, agg.ProbabilityBet), } default: - return map[string]any{ - "app_download_users": agg.AppFirstOpen, - "registered_users": agg.Registered, - "new_host_users": agg.NewHostUsers, - "new_normal_users": agg.NewNormalUsers, - "registration_success_rate": ratio(agg.Registered, agg.AppFirstOpen), - "room_join_success_users": agg.RegisteredRoomJoinOK, - "room_join_fail_users": agg.RegisteredRoomJoinNG, - "room_join_success_rate": ratio(agg.RegisteredRoomJoinOK, agg.Registered), - "room_join_fail_rate": ratio(agg.RegisteredRoomJoinNG, agg.Registered), - "mic_up_users": agg.RegisteredMicUp, - "mic_up_rate": ratio(agg.RegisteredMicUp, agg.RegisteredRoomJoinOK), - "gift_users": agg.RegisteredRoomGift, - "gift_rate": ratio(agg.RegisteredRoomGift, agg.RegisteredRoomJoinOK), - "recharge_users": agg.RegisteredRecharge, - "recharge_rate": ratio(agg.RegisteredRecharge, agg.Registered), - "game_users": agg.RegisteredGame, - "game_conversion_rate": ratio(agg.RegisteredGame, agg.Registered), + out := map[string]any{ + "app_download_users": agg.AppFirstOpen, + "registered_users": agg.Registered, + "new_host_users": agg.NewHostUsers, + "new_normal_users": agg.NewNormalUsers, + "registration_success_rate": ratio(agg.Registered, agg.AppFirstOpen), + "room_join_success_users": agg.RegisteredRoomJoinOK, + "room_join_fail_users": agg.RegisteredRoomJoinNG, + "room_join_success_rate": ratio(agg.RegisteredRoomJoinOK, agg.Registered), + "room_join_fail_rate": ratio(agg.RegisteredRoomJoinNG, agg.Registered), + "mic_up_users": agg.RegisteredMicUp, + "mic_up_rate": ratio(agg.RegisteredMicUp, agg.RegisteredRoomJoinOK), + "gift_users": agg.RegisteredRoomGift, + "gift_rate": ratio(agg.RegisteredRoomGift, agg.RegisteredRoomJoinOK), + "recharge_users": agg.RegisteredRecharge, + "recharge_rate": ratio(agg.RegisteredRecharge, agg.Registered), + "game_users": agg.RegisteredGame, + "game_conversion_rate": ratio(agg.RegisteredGame, agg.Registered), // P0 全部限定当天注册的新用户:时长按新用户累计、除以对应行为的新用户数。 "avg_app_stay_min": minutesPerUser(agg.RegisteredAppStayMS, agg.Registered), "avg_room_stay_min": minutesPerUser(agg.RegisteredRoomStayMS, agg.RegisteredRoomJoinOK), @@ -748,9 +1142,16 @@ func socialSectionMetrics(section string, agg socialRequirementAggregate, retent "follow_user_users": agg.RegisteredFollowUser, "follow_room_users": agg.RegisteredFollowRoom, "chat_users": agg.RegisteredChat, - "new_host_d1_retention_rate": retentionRate(retention, "new_host_d1_active"), - "new_user_d1_retention_rate": retentionRate(retention, "new_user_d1_active"), } + // 未成熟的 D1 cohort 不会产生 retention key;此时省略字段,让前端显示“--”, + // 同时避免总计和日均把尚未发生的观察日按 0% 计算。 + if _, ok := retention["new_host_d1_active"]; ok { + out["new_host_d1_retention_rate"] = retentionRate(retention, "new_host_d1_active") + } + if _, ok := retention["new_user_d1_active"]; ok { + out["new_user_d1_retention_rate"] = retentionRate(retention, "new_user_d1_active") + } + return out } } @@ -945,7 +1346,7 @@ func socialRequirementColumns(section string) []SocialRequirementColumn { return []SocialRequirementColumn{ {Key: "active_d1_active_base_users", Label: "活跃用户基数", Type: "count", Tooltip: "当日进入 app 的全体活跃用户数(不限新用户)"}, {Key: "active_d1_active_users", Label: "次留人数", Type: "count", Tooltip: "当日活跃用户中,次日继续进入 app 的人数"}, - {Key: "active_d1_active_rate", Label: "用户次留", Type: "ratio", Tooltip: "昨日活跃用户中,今日继续活跃的比例"}, + {Key: "active_d1_active_rate", Label: "用户次留", Type: "ratio", Tooltip: "当日活跃用户中,次日继续进入 app 的比例"}, {Key: "active_d3_active_rate", Label: "用户3日留", Type: "ratio"}, {Key: "active_d7_active_rate", Label: "用户7日留", Type: "ratio"}, {Key: "active_d15_active_rate", Label: "用户15日留", Type: "ratio"}, diff --git a/services/user-service/configs/config.docker.yaml b/services/user-service/configs/config.docker.yaml index f30e1a93..7bca562e 100644 --- a/services/user-service/configs/config.docker.yaml +++ b/services/user-service/configs/config.docker.yaml @@ -114,5 +114,6 @@ jwt: issuer: "hyapp" access_token_ttl_sec: 604800 refresh_token_ttl_sec: 2592000 + refresh_rotation_grace_sec: 30 signing_alg: "HS256" signing_secret: "dev-shared-secret" diff --git a/services/user-service/configs/config.tencent.example.yaml b/services/user-service/configs/config.tencent.example.yaml index d6bf3dc2..f26cbda5 100644 --- a/services/user-service/configs/config.tencent.example.yaml +++ b/services/user-service/configs/config.tencent.example.yaml @@ -120,5 +120,6 @@ jwt: issuer: "hyapp" access_token_ttl_sec: 604800 refresh_token_ttl_sec: 2592000 + refresh_rotation_grace_sec: 30 signing_alg: "HS256" signing_secret: "${USER_SERVICE_JWT_SECRET}" diff --git a/services/user-service/configs/config.yaml b/services/user-service/configs/config.yaml index c26d979c..e2c98528 100644 --- a/services/user-service/configs/config.yaml +++ b/services/user-service/configs/config.yaml @@ -115,5 +115,6 @@ jwt: issuer: "hyapp" access_token_ttl_sec: 604800 refresh_token_ttl_sec: 2592000 + refresh_rotation_grace_sec: 30 signing_alg: "HS256" signing_secret: "dev-shared-secret" 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 7e99825c..2a7f14f8 100644 --- a/services/user-service/deploy/mysql/initdb/001_user_service.sql +++ b/services/user-service/deploy/mysql/initdb/001_user_service.sql @@ -551,6 +551,8 @@ CREATE TABLE IF NOT EXISTS user_cp_applications ( gift_animation_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '触发申请的礼物动画', gift_count INT NOT NULL DEFAULT 0 COMMENT '触发申请的礼物数量', gift_value BIGINT NOT NULL DEFAULT 0 COMMENT '触发申请的礼物亲密值/热度值', + gift_coin_value BIGINT NOT NULL DEFAULT 0 COMMENT '触发申请时 wallet 结算出的礼物金币价值;历史缺失时保持 0', + formation_feed_eligible TINYINT(1) NOT NULL DEFAULT 0 COMMENT '成立礼物 feed 固定资格:金币价值严格大于 5000', billing_receipt_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包扣费回执 ID', source_room_event_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '来源 room outbox 事件 ID', source_command_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '来源房间命令 ID', @@ -565,6 +567,7 @@ CREATE TABLE IF NOT EXISTS user_cp_applications ( KEY idx_user_cp_app_pair_status (app_code, requester_user_id, target_user_id, status, relation_type), KEY idx_user_cp_app_admin_created (app_code, created_at_ms, application_id), KEY idx_user_cp_app_admin_filter (app_code, status, relation_type, created_at_ms, application_id), + KEY idx_user_cp_app_formation_feed (app_code, status, relation_type, formation_feed_eligible, decided_at_ms, application_id), KEY idx_user_cp_app_expire (app_code, status, expires_at_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户 CP 关系申请表'; @@ -1331,6 +1334,12 @@ CREATE TABLE IF NOT EXISTS auth_sessions ( session_id VARCHAR(96) NOT NULL PRIMARY KEY COMMENT '会话 ID', user_id BIGINT NOT NULL COMMENT '用户 ID', refresh_token_hash VARCHAR(128) NOT NULL COMMENT '刷新令牌哈希值', + token_family_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '令牌族根 session ID', + generation BIGINT NOT NULL DEFAULT 0 COMMENT '令牌族内单调代际,首代为 0', + parent_session_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '直接父代 session ID', + rotated_to_session_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '轮换产生的直接子代 session ID', + rotation_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '轮换时间,UTC epoch ms', + rotation_request_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '首次轮换 refresh 幂等键', device_id VARCHAR(128) NOT NULL COMMENT '设备 ID', expires_at_ms BIGINT NOT NULL COMMENT '过期时间,UTC epoch ms', last_heartbeat_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '最近 App 心跳时间,UTC epoch ms', @@ -1343,10 +1352,44 @@ CREATE TABLE IF NOT EXISTS auth_sessions ( updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', UNIQUE KEY uk_auth_sessions_refresh_token_hash (app_code, refresh_token_hash), KEY idx_auth_sessions_user_id (app_code, user_id), + KEY idx_auth_sessions_token_family (app_code, token_family_id, generation), KEY idx_auth_sessions_heartbeat (app_code, last_heartbeat_at_ms), KEY idx_auth_sessions_expires_at (app_code, expires_at_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='认证会话表'; +-- refresh 轮换结果必须和 session 替换同事务落 MySQL,才能覆盖多实例并发和提交后响应丢失;这里只保存 AES-GCM 密文。 +CREATE TABLE IF NOT EXISTS auth_refresh_outcomes ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码', + parent_session_id VARCHAR(96) NOT NULL COMMENT '被消费的父 session ID', + child_session_id VARCHAR(96) NOT NULL COMMENT '首次轮换产生的子 session ID', + refresh_request_id VARCHAR(96) NOT NULL COMMENT '客户端 refresh 幂等键;旧客户端由 token hash 派生', + token_ciphertext VARBINARY(4096) NOT NULL COMMENT 'AES-GCM 加密后的完整 token pair', + created_at_ms BIGINT NOT NULL COMMENT '轮换时间,UTC epoch ms', + expires_at_ms BIGINT NOT NULL COMMENT '幂等密文过期时间,UTC epoch ms', + PRIMARY KEY (app_code, parent_session_id), + KEY idx_auth_refresh_outcomes_request (app_code, refresh_request_id), + KEY idx_auth_refresh_outcomes_expires (expires_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='refresh token 轮换短期幂等结果'; + +CREATE TABLE IF NOT EXISTS auth_session_denylist_jobs ( + job_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '补偿任务 ID', + app_code VARCHAR(32) NOT NULL COMMENT '应用编码', + session_id VARCHAR(96) NOT NULL COMMENT '需要写入 gateway Redis denylist 的 session ID', + reason VARCHAR(64) NOT NULL COMMENT 'REFRESH_ROTATED、USER_LOGOUT 或 REFRESH_TOKEN_REUSE', + status VARCHAR(16) NOT NULL DEFAULT 'pending' COMMENT 'pending/processing/retryable/delivered', + attempts INT NOT NULL DEFAULT 0 COMMENT '认领次数', + next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '下次重试时间,UTC epoch ms', + locked_by VARCHAR(96) NOT NULL DEFAULT '' COMMENT '当前 worker ID', + locked_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT '处理租约截止时间,UTC epoch ms', + last_error VARCHAR(512) NOT NULL DEFAULT '' COMMENT '最近失败摘要,不含 token 原文', + deny_until_ms BIGINT NOT NULL COMMENT '该 sid 历史 access JWT 最晚拒绝时刻(含安全余量),UTC epoch ms', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + UNIQUE KEY uk_auth_session_denylist_job (app_code, session_id), + KEY idx_auth_session_denylist_pending (status, next_retry_at_ms, job_id), + KEY idx_auth_session_denylist_cleanup (deny_until_ms, job_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='session family 撤销到 Redis denylist 的持久补偿任务'; + -- 老环境已经存在 auth_sessions 时,CREATE TABLE IF NOT EXISTS 不会补 App 心跳字段。 SET @ddl := IF( (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_sessions' AND COLUMN_NAME = 'last_heartbeat_at_ms') = 0, diff --git a/services/user-service/deploy/mysql/migrations/017_cp_application_gift_coin_value.sql b/services/user-service/deploy/mysql/migrations/017_cp_application_gift_coin_value.sql new file mode 100644 index 00000000..24d0058a --- /dev/null +++ b/services/user-service/deploy/mysql/migrations/017_cp_application_gift_coin_value.sql @@ -0,0 +1,56 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +USE hyapp_user; + +-- 单列追加在 MySQL 8 上使用 INSTANT 元数据变更,不重写 user_cp_applications 大表。 +-- 默认 0 明确表示历史行没有精确 wallet 礼物金币价值;禁止用 gift_value 热度值回填。 +SET @cp_application_gift_coin_value_exists = ( + SELECT COUNT(*) + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'user_cp_applications' + AND COLUMN_NAME = 'gift_coin_value' +); +SET @cp_application_gift_coin_value_ddl = IF( + @cp_application_gift_coin_value_exists = 0, + 'ALTER TABLE user_cp_applications ADD COLUMN gift_coin_value BIGINT NOT NULL DEFAULT 0 COMMENT ''触发申请时 wallet 结算出的礼物金币价值;历史缺失时保持 0'' AFTER gift_value, ALGORITHM=INSTANT', + 'SELECT 1' +); +PREPARE cp_application_gift_coin_value_stmt FROM @cp_application_gift_coin_value_ddl; +EXECUTE cp_application_gift_coin_value_stmt; +DEALLOCATE PREPARE cp_application_gift_coin_value_stmt; + +-- 固定资格列让无命中场景走 eligible=1 的空索引范围;历史默认 0,不扫描也不把热度误当金币回填。 +SET @cp_application_formation_feed_eligible_exists = ( + SELECT COUNT(*) + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'user_cp_applications' + AND COLUMN_NAME = 'formation_feed_eligible' +); +SET @cp_application_formation_feed_eligible_ddl = IF( + @cp_application_formation_feed_eligible_exists = 0, + 'ALTER TABLE user_cp_applications ADD COLUMN formation_feed_eligible TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''成立礼物 feed 固定资格:金币价值严格大于 5000'' AFTER gift_coin_value, ALGORITHM=INSTANT', + 'SELECT 1' +); +PREPARE cp_application_formation_feed_eligible_stmt FROM @cp_application_formation_feed_eligible_ddl; +EXECUTE cp_application_formation_feed_eligible_stmt; +DEALLOCATE PREPARE cp_application_formation_feed_eligible_stmt; + +-- feed 从 eligible=1 的 accepted CP 申请按决定时间倒序扫描;等值前缀同时避免全表扫描与全表排序。 +-- 在线新增索引仍会扫描整张申请表并消耗 IO/临时空间,生产执行应安排低峰并先确认磁盘余量。 +SET @cp_application_formation_feed_index_exists = ( + SELECT COUNT(*) + FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'user_cp_applications' + AND INDEX_NAME = 'idx_user_cp_app_formation_feed' +); +SET @cp_application_formation_feed_index_ddl = IF( + @cp_application_formation_feed_index_exists = 0, + 'ALTER TABLE user_cp_applications ADD INDEX idx_user_cp_app_formation_feed (app_code, status, relation_type, formation_feed_eligible, decided_at_ms, application_id), ALGORITHM=INPLACE, LOCK=NONE', + 'SELECT 1' +); +PREPARE cp_application_formation_feed_index_stmt FROM @cp_application_formation_feed_index_ddl; +EXECUTE cp_application_formation_feed_index_stmt; +DEALLOCATE PREPARE cp_application_formation_feed_index_stmt; diff --git a/services/user-service/deploy/mysql/migrations/018_auth_refresh_token_rotation.sql b/services/user-service/deploy/mysql/migrations/018_auth_refresh_token_rotation.sql new file mode 100644 index 00000000..17774c54 --- /dev/null +++ b/services/user-service/deploy/mysql/migrations/018_auth_refresh_token_rotation.sql @@ -0,0 +1,150 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +USE hyapp_user; + +-- refresh token rotation family + 30 秒幂等结果。 +-- +-- 性能边界:auth_sessions 是登录热表,新增列均为 NOT NULL 常量默认值,MySQL 8.0 使用 +-- ALGORITHM=INSTANT 只改数据字典,不回填全表。MySQL 8.4 禁止 INSTANT 同时显式指定 LOCK 子句; +-- 若目标实例不支持 INSTANT,语句会直接失败, +-- 不能静默退化成 COPY;应在低峰期用云数据库 Online DDL 工具执行同列变更。 +-- family 索引必须扫描 auth_sessions 构建 B-Tree,因此单独使用 INPLACE/LOCK=NONE;它不复制表,但会消耗 IO/CPU, +-- 6 列合并为一次 INSTANT ALTER,只获取一次 MDL 并消耗一个 instant row version;目标表接近 row-version +-- 上限时仍应先检查 INFORMATION_SCHEMA.INNODB_TABLES.TOTAL_ROW_VERSIONS。 +SET @auth_session_column_ddl := CONCAT_WS(', ', + IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_sessions' AND COLUMN_NAME = 'token_family_id') = 0, + 'ADD COLUMN token_family_id VARCHAR(96) NOT NULL DEFAULT '''' COMMENT ''令牌族根 session ID''', NULL), + IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_sessions' AND COLUMN_NAME = 'generation') = 0, + 'ADD COLUMN generation BIGINT NOT NULL DEFAULT 0 COMMENT ''令牌族内单调代际,首代为 0''', NULL), + IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_sessions' AND COLUMN_NAME = 'parent_session_id') = 0, + 'ADD COLUMN parent_session_id VARCHAR(96) NOT NULL DEFAULT '''' COMMENT ''直接父代 session ID''', NULL), + IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_sessions' AND COLUMN_NAME = 'rotated_to_session_id') = 0, + 'ADD COLUMN rotated_to_session_id VARCHAR(96) NOT NULL DEFAULT '''' COMMENT ''轮换产生的直接子代 session ID''', NULL), + IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_sessions' AND COLUMN_NAME = 'rotation_at_ms') = 0, + 'ADD COLUMN rotation_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''轮换时间,UTC epoch ms''', NULL), + IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_sessions' AND COLUMN_NAME = 'rotation_request_id') = 0, + 'ADD COLUMN rotation_request_id VARCHAR(96) NOT NULL DEFAULT '''' COMMENT ''首次轮换 refresh 幂等键''', NULL) +); +SET @ddl := IF( + @auth_session_column_ddl = '', + 'SELECT 1', + CONCAT('ALTER TABLE auth_sessions ', @auth_session_column_ddl, ', ALGORITHM=INSTANT') +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +CREATE TABLE IF NOT EXISTS auth_refresh_outcomes ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码', + parent_session_id VARCHAR(96) NOT NULL COMMENT '被消费的父 session ID', + child_session_id VARCHAR(96) NOT NULL COMMENT '首次轮换产生的子 session ID', + refresh_request_id VARCHAR(96) NOT NULL COMMENT '客户端 refresh 幂等键;旧客户端由 token hash 派生', + token_ciphertext VARBINARY(4096) NOT NULL COMMENT 'AES-GCM 加密后的完整 token pair', + created_at_ms BIGINT NOT NULL COMMENT '轮换时间,UTC epoch ms', + expires_at_ms BIGINT NOT NULL COMMENT '幂等密文过期时间,UTC epoch ms', + PRIMARY KEY (app_code, parent_session_id), + KEY idx_auth_refresh_outcomes_request (app_code, refresh_request_id), + KEY idx_auth_refresh_outcomes_expires (expires_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='refresh token 轮换短期幂等结果'; + +CREATE TABLE IF NOT EXISTS auth_session_denylist_jobs ( + job_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '补偿任务 ID', + app_code VARCHAR(32) NOT NULL COMMENT '应用编码', + session_id VARCHAR(96) NOT NULL COMMENT '需要写入 gateway Redis denylist 的 session ID', + reason VARCHAR(64) NOT NULL COMMENT 'REFRESH_ROTATED、USER_LOGOUT 或 REFRESH_TOKEN_REUSE', + status VARCHAR(16) NOT NULL DEFAULT 'pending' COMMENT 'pending/processing/retryable/delivered', + attempts INT NOT NULL DEFAULT 0 COMMENT '认领次数', + next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '下次重试时间,UTC epoch ms', + locked_by VARCHAR(96) NOT NULL DEFAULT '' COMMENT '当前 worker ID', + locked_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT '处理租约截止时间,UTC epoch ms', + last_error VARCHAR(512) NOT NULL DEFAULT '' COMMENT '最近失败摘要,不含 token 原文', + deny_until_ms BIGINT NOT NULL COMMENT '该 sid 历史 access JWT 最晚拒绝时刻(含安全余量),UTC epoch ms', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + UNIQUE KEY uk_auth_session_denylist_job (app_code, session_id), + KEY idx_auth_session_denylist_pending (status, next_retry_at_ms, job_id), + KEY idx_auth_session_denylist_cleanup (deny_until_ms, job_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='session family 撤销到 Redis denylist 的持久补偿任务'; + +-- 本 migration 可能在早期试运行版本创建过 job 表;补列使用 INSTANT,不扫描业务热表。 +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_session_denylist_jobs' AND COLUMN_NAME = 'deny_until_ms') = 0, + 'ALTER TABLE auth_session_denylist_jobs ADD COLUMN deny_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''历史 access JWT 最晚拒绝时刻(含安全余量),UTC epoch ms'', ALGORITHM=INSTANT', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- 仅早期试运行 job 表需要一次有界回填;它不是 auth_sessions 热表。按历史最大 7d access TTL + 60s +-- 安全余量恢复 deadline,避免新增列默认 0 后把仍有效保护事实立即清理;生产仍应在低峰观察受影响行数。 +UPDATE auth_session_denylist_jobs +SET deny_until_ms = created_at_ms + 604860000 +WHERE deny_until_ms = 0; + +-- 上线前版本允许同 sid 按 reason 多行;先合并为 deny_until 最大的一行,再改成每 sid 唯一,避免短 TTL job 覆盖长 TTL。 +DELETE older +FROM auth_session_denylist_jobs older +JOIN auth_session_denylist_jobs keeper + ON keeper.app_code = older.app_code + AND keeper.session_id = older.session_id + AND (keeper.deny_until_ms > older.deny_until_ms + OR (keeper.deny_until_ms = older.deny_until_ms AND keeper.job_id > older.job_id)); + +SET @denylist_unique_columns := ( + SELECT GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX SEPARATOR ',') + FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_session_denylist_jobs' AND INDEX_NAME = 'uk_auth_session_denylist_job' +); +SET @denylist_unique_non_unique := ( + SELECT MIN(NON_UNIQUE) + FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_session_denylist_jobs' AND INDEX_NAME = 'uk_auth_session_denylist_job' +); +SET @ddl := CASE + WHEN @denylist_unique_columns IS NULL THEN + 'ALTER TABLE auth_session_denylist_jobs ADD UNIQUE INDEX uk_auth_session_denylist_job (app_code, session_id), ALGORITHM=INPLACE, LOCK=NONE' + WHEN @denylist_unique_columns <> 'app_code,session_id' OR @denylist_unique_non_unique <> 0 THEN + 'ALTER TABLE auth_session_denylist_jobs DROP INDEX uk_auth_session_denylist_job, ADD UNIQUE INDEX uk_auth_session_denylist_job (app_code, session_id), ALGORITHM=INPLACE, LOCK=NONE' + ELSE 'SELECT 1' +END; +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SET @denylist_cleanup_columns := ( + SELECT GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX SEPARATOR ',') + FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_session_denylist_jobs' AND INDEX_NAME = 'idx_auth_session_denylist_cleanup' +); +SET @ddl := CASE + WHEN @denylist_cleanup_columns IS NULL THEN + 'ALTER TABLE auth_session_denylist_jobs ADD INDEX idx_auth_session_denylist_cleanup (deny_until_ms, job_id), ALGORITHM=INPLACE, LOCK=NONE' + WHEN @denylist_cleanup_columns <> 'deny_until_ms,job_id' THEN + 'ALTER TABLE auth_session_denylist_jobs DROP INDEX idx_auth_session_denylist_cleanup, ADD INDEX idx_auth_session_denylist_cleanup (deny_until_ms, job_id), ALGORITHM=INPLACE, LOCK=NONE' + ELSE 'SELECT 1' +END; +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SET @family_index_columns := ( + SELECT GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX SEPARATOR ',') + FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_sessions' AND INDEX_NAME = 'idx_auth_sessions_token_family' +); +SET @family_index_non_unique := ( + SELECT MIN(NON_UNIQUE) + FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'auth_sessions' AND INDEX_NAME = 'idx_auth_sessions_token_family' +); +SET @ddl := CASE + WHEN @family_index_columns IS NULL THEN + 'ALTER TABLE auth_sessions ADD INDEX idx_auth_sessions_token_family (app_code, token_family_id, generation), ALGORITHM=INPLACE, LOCK=NONE' + WHEN @family_index_columns <> 'app_code,token_family_id,generation' OR @family_index_non_unique <> 1 THEN + 'ALTER TABLE auth_sessions DROP INDEX idx_auth_sessions_token_family, ADD INDEX idx_auth_sessions_token_family (app_code, token_family_id, generation), ALGORITHM=INPLACE, LOCK=NONE' + ELSE 'SELECT 1' +END; +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; diff --git a/services/user-service/internal/app/app.go b/services/user-service/internal/app/app.go index 1a2680dc..87444a8c 100644 --- a/services/user-service/internal/app/app.go +++ b/services/user-service/internal/app/app.go @@ -30,6 +30,7 @@ import ( "hyapp/pkg/tencentim" "hyapp/pkg/usermq" "hyapp/pkg/walletmq" + "hyapp/pkg/xerr" "hyapp/services/user-service/internal/config" cpdomain "hyapp/services/user-service/internal/domain/cp" invitedomain "hyapp/services/user-service/internal/domain/invite" @@ -87,8 +88,10 @@ type App struct { roomTimeSvc *roomtimeservice.Service // cpSvc 消费 room gift outbox,维护 CP/兄弟/姐妹申请和亲密值。 cpSvc *cpservice.Service - // loginRiskRedisClose 关闭登录风险 Redis cache;cache 不作为启动硬依赖。 + // loginRiskRedisClose 关闭登录风险/session denylist Redis;denylist 是启动硬依赖。 loginRiskRedisClose func() error + // sessionDenylistEpoch 记录完成全量重水合时的 Redis run_id,变化时必须再次重放。 + sessionDenylistEpoch string // cpLeaderboardRedisClose 关闭 CP 亲密榜 Redis 读模型连接。 cpLeaderboardRedisClose func() error // cfg 保存 worker 运行参数,避免 Run 阶段重新读配置。 @@ -153,18 +156,23 @@ func New(cfg config.Config) (*App, error) { var ipDecisionCache authservice.IPDecisionCache var registerRiskConfigCache authservice.RegisterRiskConfigCache var loginRiskRedisClose func() error - if cfg.LoginRisk.Enabled && cfg.LoginRisk.RedisAddr != "" { - redisClient, redisErr := authservice.NewLoginRiskRedisClient(startupCtx, cfg.LoginRisk.RedisAddr, cfg.LoginRisk.RedisPassword, cfg.LoginRisk.RedisDB) - if redisErr == nil { - riskCache := authservice.NewRedisIPDecisionCache(redisClient) - ipDecisionCache = riskCache - registerRiskConfigCache = riskCache - loginRiskRedisClose = redisClient.Close - } else { - // IP 风控 Redis 缓存按文档 fail-open;启动继续,worker 仍会写 MySQL 审计。 - logx.Warn(startupCtx, "login_risk_redis_unavailable") - } + if cfg.LoginRisk.RedisAddr == "" { + _ = listener.Close() + _ = mysqlRepo.Close() + return nil, xerr.New(xerr.Unavailable, "session denylist Redis address is required") } + // IP 风控可关闭,但 session denylist 已是 refresh/logout 的认证安全依赖,必须独立建连并 fail-fast。 + // 启动 Ping 失败时不对外 healthy;否则 Redis 恢复后本进程也没有 client/worker,只会让全量 refresh 永久 UNAVAILABLE。 + redisClient, redisErr := authservice.NewLoginRiskRedisClient(startupCtx, cfg.LoginRisk.RedisAddr, cfg.LoginRisk.RedisPassword, cfg.LoginRisk.RedisDB) + if redisErr != nil { + _ = listener.Close() + _ = mysqlRepo.Close() + return nil, redisErr + } + riskCache := authservice.NewRedisIPDecisionCache(redisClient) + ipDecisionCache = riskCache + registerRiskConfigCache = riskCache + loginRiskRedisClose = redisClient.Close var cpLeaderboardStore cpservice.IntimacyLeaderboardStore var cpLeaderboardRedisClose func() error if cfg.CPIntimacyLeaderboard.Enabled { @@ -276,11 +284,12 @@ func New(cfg config.Config) (*App, error) { // auth service 负责登录、session 和 token;用户主数据和短号事务仍通过各自领域存储完成。 authSvc := authservice.New(authservice.Config{ - Issuer: cfg.JWT.Issuer, - AccessTokenTTLSec: cfg.JWT.AccessTokenTTLSec, - RefreshTokenTTLSec: cfg.JWT.RefreshTokenTTLSec, - SigningAlg: cfg.JWT.SigningAlg, - SigningSecret: cfg.JWT.SigningSecret, + Issuer: cfg.JWT.Issuer, + AccessTokenTTLSec: cfg.JWT.AccessTokenTTLSec, + RefreshTokenTTLSec: cfg.JWT.RefreshTokenTTLSec, + RefreshRotationGraceSec: cfg.JWT.RefreshRotationGraceSec, + SigningAlg: cfg.JWT.SigningAlg, + SigningSecret: cfg.JWT.SigningSecret, }, authservice.WithAuthRepository(authRepo), authservice.WithUserRepository(userRepo), @@ -466,14 +475,20 @@ func (a *App) Run() error { a.health.MarkStopped() return err } - a.runUserOutboxWorker() - // 只有 listener 进入 Serve 后才标记 serving,避免健康检查提前放行。 - a.health.MarkServing() defer func() { a.workers.StopAndWait() shutdownMQConsumers(a.mqConsumers) a.shutdownUserOutboxProducer() }() + if err := a.rehydrateSessionDenylist(context.Background()); err != nil { + // denylist 是 access JWT 撤销的安全事实;Redis/重水合失败时不能先对外 healthy 再放行旧 token。 + a.health.MarkStopped() + return err + } + a.runUserOutboxWorker() + a.runSessionDenylistWorker() + // 只有 listener 进入 Serve 后才标记 serving,避免健康检查提前放行。 + a.health.MarkServing() err := a.server.Serve(a.listener) a.health.MarkStopped() if errors.Is(err, grpc.ErrServerStopped) { @@ -484,6 +499,135 @@ func (a *App) Run() error { return err } +func (a *App) rehydrateSessionDenylist(ctx context.Context) error { + if a.authSvc == nil || a.loginRiskRedisClose == nil { + return xerr.New(xerr.Unavailable, "session denylist Redis is not configured") + } + workerID := "auth-session-denylist-hydrate-" + a.cfg.NodeID + for epochAttempt := 0; epochAttempt < 3; epochAttempt++ { + epochBefore, err := a.authSvc.SessionDenylistEpoch(ctx) + if err != nil { + return err + } + // 每批只读 1000 行且 cursor 循环到固定 max job_id;hydration 不认领/锁 job,随后 drain 新增 pending 后健康检查才可放行。 + if _, err := a.authSvc.RehydrateAllSessionDenylistJobs(ctx, 1000); err != nil { + return err + } + for { + processed, err := a.authSvc.ProcessSessionDenylistBatch(ctx, workerID, 100) + if err != nil { + return err + } + if processed < 100 { + break + } + } + epochAfter, err := a.authSvc.SessionDenylistEpoch(ctx) + if err != nil { + return err + } + if epochBefore == epochAfter { + a.sessionDenylistEpoch = epochAfter + return nil + } + } + return xerr.New(xerr.Unavailable, "session denylist Redis changed during hydration") +} + +func (a *App) runSessionDenylistWorker() { + if a.authSvc == nil || a.loginRiskRedisClose == nil { + // 生产 New 已强制 Redis 连通并在启动 hydration 失败时退出;这里只防御不完整的测试/工具装配。 + return + } + workerID := "auth-session-denylist-" + a.cfg.NodeID + a.workers.Go(func(ctx context.Context) { + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + for { + processed, err := a.authSvc.ProcessSessionDenylistBatch(ctx, workerID, 100) + if err != nil && !errors.Is(err, context.Canceled) { + logx.Error(ctx, "auth_session_denylist_retry_failed", err, slog.String("worker_id", workerID)) + } + if processed >= 100 { + continue + } + select { + case <-ctx.Done(): + return + case <-ticker.C: + } + } + }) + // Redis AOF/volume 覆盖正常重启;run_id 变化检测再覆盖独立重启/主从切换,且只有 epoch 变化才全量重水合, + // 不用每小时无条件重写全部 sid。INFO 临时失败只告警并在下一轮重试。 + a.workers.Go(func(ctx context.Context) { + lastEpoch := a.sessionDenylistEpoch + ticker := time.NewTicker(30 * time.Second) + defer ticker.Stop() + for { + epoch, err := a.authSvc.SessionDenylistEpoch(ctx) + if err != nil { + if !errors.Is(err, context.Canceled) { + logx.Error(ctx, "auth_session_denylist_epoch_read_failed", err, slog.String("worker_id", workerID)) + } + } else if lastEpoch == "" { + lastEpoch = epoch + } else if epoch != lastEpoch { + if err := a.rehydrateSessionDenylist(ctx); err != nil { + if !errors.Is(err, context.Canceled) { + logx.Error(ctx, "auth_session_denylist_epoch_rehydrate_failed", err, slog.String("worker_id", workerID)) + } + } else { + // rehydrate 内部会在 Redis run_id 变化时重试到稳定 epoch;必须采用它最终确认的值, + // 不能回写本轮调用前捕获的旧 epoch,否则下一轮会重复全量重水合。 + lastEpoch = a.sessionDenylistEpoch + } + } + select { + case <-ctx.Done(): + return + case <-ticker.C: + } + } + }) + // 已越过 deny_until 的补偿事实按小时小批清理;多实例各跑一次只会造成可接受的幂等索引扫描, + // 不把清理塞进每秒轮询,避免空队列时持续制造无意义 MySQL DELETE QPS。 + a.workers.Go(func(ctx context.Context) { + ticker := time.NewTicker(time.Hour) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + // 单轮最多 10x1000,批满继续追赶日增量但限制 IO 峰值;连续打满会留下可观测 backlog 告警。 + if saturated, err := a.cleanupAuthSessionPersistence(ctx, 1000, 10); err != nil && !errors.Is(err, context.Canceled) { + logx.Error(ctx, "auth_session_persistence_cleanup_failed", err, slog.String("worker_id", workerID)) + } else if saturated { + logx.Warn(ctx, "auth_session_persistence_cleanup_backlog", slog.String("worker_id", workerID)) + } + } + } + }) +} + +func (a *App) cleanupAuthSessionPersistence(ctx context.Context, batchSize int, maxBatches int) (bool, error) { + for batch := 0; batch < maxBatches; batch++ { + deletedJobs, err := a.authSvc.CleanupExpiredSessionDenylistJobs(ctx, batchSize) + if err != nil { + return false, err + } + deletedOutcomes, err := a.authSvc.CleanupExpiredRefreshOutcomes(ctx, batchSize) + if err != nil { + return false, err + } + if deletedJobs < batchSize && deletedOutcomes < batchSize { + return false, nil + } + } + return true, nil +} + // Close 关闭 gRPC 服务和底层持久化连接。 func (a *App) Close() { a.closeOnce.Do(func() { @@ -876,7 +1020,7 @@ func roomGiftCPEventFromRoomMessage(body []byte) (cpdomain.GiftEvent, bool, erro return cpdomain.GiftEvent{}, false, err } // CP worker 必须接收所有送礼事实:没有 active 关系时仓储层只让 CP/兄弟/姐妹礼物生成申请; - // 已有 active 关系时,普通、幸运和超级幸运礼物都按 wallet 已结算的 GiftValue 增加亲密值。 + // 已有 active 关系时 GiftValue 继续增加亲密值,而 CoinSpent 独立保留 wallet 结算出的礼物金币价值,二者不能互相回填。 return cpdomain.GiftEvent{ AppCode: appcode.Normalize(envelope.GetAppCode()), EventID: envelope.GetEventId(), @@ -888,6 +1032,7 @@ func roomGiftCPEventFromRoomMessage(body []byte) (cpdomain.GiftEvent, bool, erro GiftID: sent.GetGiftId(), GiftCount: sent.GetGiftCount(), GiftValue: sent.GetGiftValue(), + CoinSpent: sent.GetCoinSpent(), BillingReceiptID: sent.GetBillingReceiptId(), VisibleRegionID: sent.GetVisibleRegionId(), CommandID: sent.GetCommandId(), diff --git a/services/user-service/internal/config/config.go b/services/user-service/internal/config/config.go index 697dca98..126b7474 100644 --- a/services/user-service/internal/config/config.go +++ b/services/user-service/internal/config/config.go @@ -267,6 +267,8 @@ type JWTConfig struct { AccessTokenTTLSec int64 `yaml:"access_token_ttl_sec"` // RefreshTokenTTLSec 是服务端 session/refresh token 有效期。 RefreshTokenTTLSec int64 `yaml:"refresh_token_ttl_sec"` + // RefreshRotationGraceSec 是直接上一代 refresh token 幂等恢复窗口,默认 30 秒。 + RefreshRotationGraceSec int64 `yaml:"refresh_rotation_grace_sec"` // SigningAlg 当前只支持 HS256。 SigningAlg string `yaml:"signing_alg"` // SigningSecret 是 HS256 签名密钥,生产不能使用默认开发值。 @@ -356,11 +358,12 @@ func Default() Config { RequestTimeoutMs: 5000, }, JWT: JWTConfig{ - Issuer: "hyapp", - AccessTokenTTLSec: 604800, - RefreshTokenTTLSec: 2592000, - SigningAlg: "HS256", - SigningSecret: "dev-shared-secret", + Issuer: "hyapp", + AccessTokenTTLSec: 604800, + RefreshTokenTTLSec: 2592000, + RefreshRotationGraceSec: 30, + SigningAlg: "HS256", + SigningSecret: "dev-shared-secret", }, Log: logx.Config{ Level: "info", @@ -458,6 +461,9 @@ func Load(path string) (Config, error) { if cfg.LoginRisk.ProviderTimeoutMs <= 0 { cfg.LoginRisk.ProviderTimeoutMs = 800 } + if cfg.JWT.RefreshRotationGraceSec <= 0 { + cfg.JWT.RefreshRotationGraceSec = 30 + } for index, provider := range cfg.LoginRisk.Providers { cfg.LoginRisk.Providers[index] = strings.TrimSpace(provider) } diff --git a/services/user-service/internal/domain/auth/auth.go b/services/user-service/internal/domain/auth/auth.go index d3351aea..fe6a475e 100644 --- a/services/user-service/internal/domain/auth/auth.go +++ b/services/user-service/internal/domain/auth/auth.go @@ -61,6 +61,18 @@ type Session struct { UserID int64 // RefreshTokenHash 是 refresh token 的 hash,持久化层不得保存原文。 RefreshTokenHash string + // TokenFamilyID 把一次登录后连续轮换出的 session 串成同一个安全边界;检测到重放时整族失效。 + TokenFamilyID string + // Generation 是 session 在 token family 内的单调代际,首个登录 session 为 0。 + Generation int64 + // ParentSessionID 指向直接上一代 session;只有直接父代允许命中短暂轮换宽限期。 + ParentSessionID string + // RotatedToSessionID 只在已成功轮换的父 session 上有值,用于恢复同一次轮换的幂等响应。 + RotatedToSessionID string + // RotationAtMs 是父 session 被轮换的 UTC epoch ms,宽限期只能从该事实时间开始计算。 + RotationAtMs int64 + // RotationRequestID 保存首次消费该 refresh token 的客户端幂等键。 + RotationRequestID string // DeviceID 绑定 refresh token 轮换设备,防止跨设备复用。 DeviceID string // ExpiresAtMs 是 refresh session 过期时间。 @@ -83,6 +95,58 @@ type Session struct { UpdatedAtMs int64 } +// RefreshRotationStatus 是 repository 对一次 refresh 消费的原子判定。 +type RefreshRotationStatus string + +const ( + // RefreshRotationCreated 表示当前 refresh token 首次被消费并成功产生下一代。 + RefreshRotationCreated RefreshRotationStatus = "created" + // RefreshRotationGraceHit 表示直接父代在宽限期内重试,必须复用首次落库的同一 token pair。 + RefreshRotationGraceHit RefreshRotationStatus = "grace_hit" + // RefreshRotationReuseDetected 表示旧 token 已越过直接父代或宽限期,整条 token family 已被吊销。 + RefreshRotationReuseDetected RefreshRotationStatus = "reuse_detected" +) + +// RefreshRotationCommand 把候选下一代和加密幂等响应交给 repository 原子提交。 +// TokenCiphertext 是 AES-GCM 密文,数据库永远不保存 access/refresh token 原文。 +type RefreshRotationCommand struct { + AppCode string + RefreshTokenHash string + DeviceID string + RefreshRequestID string + NowMs int64 + GracePeriodMs int64 + // DenyUntilMs 固化本次撤销涉及 access JWT 的最晚拒绝时刻,不能被未来 TTL 配置缩短。 + DenyUntilMs int64 + NewSession Session + TokenCiphertext []byte + OutcomeExpiresAtMs int64 +} + +// RefreshRotationResult 返回轮换、宽限复用或重放撤销的持久化事实。 +type RefreshRotationResult struct { + Status RefreshRotationStatus + SourceSession Session + ActiveSession Session + RefreshRequestID string + TokenCiphertext []byte + FamilySessionIDs []string + FamilyNewlyRevoked bool +} + +// SessionDenylistJob 是 MySQL 持久化的 gateway Redis denylist 补偿事实。 +// family revoke 与 job 同事务提交,避免 MySQL 已撤销而进程崩溃导致旧 access JWT 永久漏拦截。 +type SessionDenylistJob struct { + JobID int64 + AppCode string + SessionID string + Reason string + Attempts int + // DenyUntilMs 是该 sid 的历史 access JWT 全部自然过期(含安全余量)的时刻。 + DenyUntilMs int64 + CreatedAtMs int64 +} + // ThirdPartyIdentity 是 provider + subject 到用户的稳定绑定。 type ThirdPartyIdentity struct { // AppCode 把 provider subject 限定在当前 App 内,避免多个 App 共享 provider 命名空间。 diff --git a/services/user-service/internal/domain/cp/cp.go b/services/user-service/internal/domain/cp/cp.go index e2be586b..128ebb5c 100644 --- a/services/user-service/internal/domain/cp/cp.go +++ b/services/user-service/internal/domain/cp/cp.go @@ -103,9 +103,19 @@ type GiftSnapshot struct { GiftAnimationURL string GiftCount int32 GiftValue int64 + CoinSpent int64 BillingReceiptID string } +// FormationGiftFeedItem 是组 CP 成立礼物的只读展示模型;金额固定使用 wallet 结算出的礼物金币价值,不复用热度字段。 +type FormationGiftFeedItem struct { + FormationID string + GiftCoinValue int64 + Requester UserProfile + Target UserProfile + FormedAtMS int64 +} + // Application 表达一次关系申请,只有 target 用户可以处理 pending 状态。 type Application struct { ApplicationID string @@ -176,6 +186,7 @@ type GiftEvent struct { GiftID string GiftCount int32 GiftValue int64 + CoinSpent int64 BillingReceiptID string VisibleRegionID int64 CommandID string diff --git a/services/user-service/internal/service/auth/audit.go b/services/user-service/internal/service/auth/audit.go index 6e56b16a..11c9c211 100644 --- a/services/user-service/internal/service/auth/audit.go +++ b/services/user-service/internal/service/auth/audit.go @@ -18,6 +18,8 @@ type Meta struct { AppCode string // RequestID 是 gateway 透传的请求 ID,用于登录审计。 RequestID string + // RefreshRequestID 是客户端为一次 refresh 尝试生成的稳定幂等键;网络重试必须复用,普通链路为空。 + RefreshRequestID string // ClientIP 是客户端 IP。 ClientIP string // UserAgent 是客户端 UA。 diff --git a/services/user-service/internal/service/auth/risk_cache.go b/services/user-service/internal/service/auth/risk_cache.go index 35a11b6b..97a2c9a2 100644 --- a/services/user-service/internal/service/auth/risk_cache.go +++ b/services/user-service/internal/service/auth/risk_cache.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "errors" + "fmt" "strings" "time" @@ -16,6 +17,23 @@ type RedisIPDecisionCache struct { client *redis.Client } +var setRevokedSessionMaxTTLScript = redis.NewScript(` +local current_ttl = redis.call('PTTL', KEYS[1]) +local requested_ttl = tonumber(ARGV[2]) +if current_ttl == -2 then + redis.call('PSETEX', KEYS[1], requested_ttl, ARGV[1]) + return requested_ttl +end +if current_ttl == -1 then + return current_ttl +end +if current_ttl < requested_ttl then + redis.call('PSETEX', KEYS[1], requested_ttl, ARGV[1]) + return requested_ttl +end +return current_ttl +`) + func NewRedisIPDecisionCache(client *redis.Client) *RedisIPDecisionCache { return &RedisIPDecisionCache{client: client} } @@ -57,7 +75,33 @@ func (c *RedisIPDecisionCache) SetIPDecision(ctx context.Context, appCode string } func (c *RedisIPDecisionCache) SetRevokedSession(ctx context.Context, appCode string, sessionID string, reason string, ttl time.Duration) error { - return c.client.Set(ctx, revokedSessionKey(appCode, sessionID), strings.TrimSpace(reason), ttl).Err() + if c == nil || c.client == nil { + return errors.New("session denylist redis client is unavailable") + } + ttlMs := ttl.Milliseconds() + if ttlMs <= 0 { + return fmt.Errorf("session denylist TTL must be positive") + } + // 多来源会并发撤销同一 sid(rotation/reuse/logout/risk);普通 SET 会让较短旧任务覆盖较长 deny_until。 + // Lua 原子比较 PTTL,只允许延长绝对保护时间;已有永久 key 也绝不被改短。 + return setRevokedSessionMaxTTLScript.Run(ctx, c.client, []string{revokedSessionKey(appCode, sessionID)}, strings.TrimSpace(reason), ttlMs).Err() +} + +func (c *RedisIPDecisionCache) SessionDenylistEpoch(ctx context.Context) (string, error) { + if c == nil || c.client == nil { + return "", errors.New("session denylist redis client is unavailable") + } + info, err := c.client.Info(ctx, "server").Result() + if err != nil { + return "", err + } + for _, line := range strings.Split(info, "\n") { + key, value, found := strings.Cut(strings.TrimSpace(line), ":") + if found && key == "run_id" && strings.TrimSpace(value) != "" { + return strings.TrimSpace(value), nil + } + } + return "", errors.New("redis run_id is unavailable") } func (c *RedisIPDecisionCache) GetIPWhitelist(ctx context.Context, appCode string) ([]string, bool, error) { diff --git a/services/user-service/internal/service/auth/service.go b/services/user-service/internal/service/auth/service.go index d7480dbb..a35ec872 100644 --- a/services/user-service/internal/service/auth/service.go +++ b/services/user-service/internal/service/auth/service.go @@ -3,9 +3,12 @@ package auth import ( "context" + "log/slog" "time" "hyapp/pkg/idgen" + "hyapp/pkg/logx" + "hyapp/pkg/xerr" authdomain "hyapp/services/user-service/internal/domain/auth" invitedomain "hyapp/services/user-service/internal/domain/invite" userdomain "hyapp/services/user-service/internal/domain/user" @@ -52,18 +55,36 @@ type AuthRepository interface { CreateSession(ctx context.Context, session authdomain.Session) error // FindActiveSessionByRefreshHash 通过 refresh token hash 查找未过期未吊销 session。 FindActiveSessionByRefreshHash(ctx context.Context, refreshTokenHash string, nowMs int64) (authdomain.Session, error) + // FindSessionByRefreshHash 返回包含已轮换 session 在内的完整 lineage,用于判断 grace 与 token reuse。 + FindSessionByRefreshHash(ctx context.Context, refreshTokenHash string) (authdomain.Session, error) // FindActiveSessionByID 通过 session_id 查找未过期未吊销 session,用于只重签 access token 的链路。 FindActiveSessionByID(ctx context.Context, sessionID string, nowMs int64) (authdomain.Session, error) // FindLatestActiveSessionByUser 返回用户最新未过期未吊销 session,供后台重签 access token;无会话返回 NotFound。 FindLatestActiveSessionByUser(ctx context.Context, userID int64, nowMs int64) (authdomain.Session, error) - // ReplaceSession 原子吊销旧 session 并创建新 session。 - ReplaceSession(ctx context.Context, oldSessionID string, newSession authdomain.Session, revokedAtMs int64) error + // RotateRefreshSession 原子完成旧 session 吊销、新 session 创建和加密幂等响应落库。 + RotateRefreshSession(ctx context.Context, command authdomain.RefreshRotationCommand) (authdomain.RefreshRotationResult, error) // RevokeSession 按 session_id 或 refresh token hash 吊销 session。 RevokeSession(ctx context.Context, sessionID string, refreshTokenHash string, revokedAtMs int64) (bool, error) + // RevokeSessionFamily 原子吊销显式 logout 所属 token family,并返回需要写 gateway denylist 的全部 sid。 + RevokeSessionFamily(ctx context.Context, sessionID string, refreshTokenHash string, revokedAtMs int64, denyUntilMs int64, requestID string) (string, []string, bool, error) // RevokeSessionWithReason 按 session_id 幂等吊销 session,并持久化撤销来源。 RevokeSessionWithReason(ctx context.Context, sessionID string, revokedAtMs int64, reason string, requestID string, revokedBy string) (bool, error) // RevokeUserDeviceSessionsForRisk 按风险源 session 定位同一设备后续 session,吊销 active session,并返回需要写入 denylist 的 session_id。 RevokeUserDeviceSessionsForRisk(ctx context.Context, sourceSessionID string, userID int64, revokedAtMs int64, reason string, requestID string, revokedBy string) ([]string, error) + // ClaimSessionDenylistJobs 认领 family revoke 同事务写出的 Redis denylist 补偿事实。 + ClaimSessionDenylistJobs(ctx context.Context, workerID string, nowMs int64, lockUntilMs int64, limit int) ([]authdomain.SessionDenylistJob, error) + // MarkSessionDenylistJobDelivered 标记 sid 已写入 gateway Redis denylist。 + MarkSessionDenylistJobDelivered(ctx context.Context, jobID int64, appCode string, sessionID string, reason string, appliedDenyUntilMs int64, nowMs int64, nextRehydrateAtMs int64) error + // MarkSessionDenylistJobRetryable 释放失败 job 并安排下一次重试。 + MarkSessionDenylistJobRetryable(ctx context.Context, jobID int64, errorMessage string, nextRetryAtMs int64, nowMs int64) error + // MaxSessionDenylistJobID 固化一次启动重水合的上界,避免并发新 job 让分页永不结束。 + MaxSessionDenylistJobID(ctx context.Context) (int64, error) + // ListSessionDenylistJobsForHydration 忽略 status/lease 按稳定 cursor 读取未过期事实,启动恢复不依赖通用 claim。 + ListSessionDenylistJobsForHydration(ctx context.Context, nowMs int64, afterJobID int64, throughJobID int64, limit int) ([]authdomain.SessionDenylistJob, int64, error) + // DeleteExpiredSessionDenylistJobs 只按持久化 deny_until 清理已经没有有效 access JWT 的事实。 + DeleteExpiredSessionDenylistJobs(ctx context.Context, nowMs int64, limit int) (int, error) + // DeleteExpiredRefreshOutcomes 按 expires_at 索引清理过宽限期的加密 token pair。 + DeleteExpiredRefreshOutcomes(ctx context.Context, nowMs int64, limit int) (int, error) // UpdateSessionHeartbeat 刷新当前 App 登录会话心跳,必须校验 session 仍属于当前用户且未过期未吊销。 UpdateSessionHeartbeat(ctx context.Context, sessionID string, userID int64, heartbeatAtMs int64, requestID string) (authdomain.Session, error) // FindThirdPartyIdentity 查找 provider + subject 的绑定。 @@ -162,12 +183,26 @@ type Config struct { AccessTokenTTLSec int64 // RefreshTokenTTLSec 是服务端 refresh session 有效期。 RefreshTokenTTLSec int64 + // RefreshRotationGraceSec 允许直接上一代 refresh token 在响应丢失或并发时复用首次结果的秒数。 + RefreshRotationGraceSec int64 // SigningAlg 当前只支持 HS256。 SigningAlg string // SigningSecret 是 HS256 签名密钥。 SigningSecret string } +// RefreshMetricRecorder 是 refresh rotation 四个低基数指标的最小记录边界。 +// 默认实现输出稳定结构化事件,现有日志采集可直接按 metric + app_code 聚合计数。 +type RefreshMetricRecorder interface { + Increment(ctx context.Context, metric string, appCode string) +} + +type logRefreshMetricRecorder struct{} + +func (logRefreshMetricRecorder) Increment(ctx context.Context, metric string, appCode string) { + logx.Info(ctx, "auth_refresh_metric", slog.String("metric", metric), slog.String("app_code", appCode)) +} + // LoginRiskPolicy 保存 IP 风控 worker 的判定和缓存策略。 type LoginRiskPolicy struct { Enabled bool @@ -191,6 +226,11 @@ type IPDecisionCache interface { SetUserWhitelist(ctx context.Context, appCode string, userIDs []int64, ttl time.Duration) error } +// SessionDenylistEpochReader 暴露 Redis 进程 run_id;变化意味着重启/failover,需要从 MySQL 全量重水合未过期 job。 +type SessionDenylistEpochReader interface { + SessionDenylistEpoch(ctx context.Context) (string, error) +} + // RegisterRiskConfigCache 是注册风控配置的 Redis 快取边界。 // 该缓存只做读放大优化,MySQL 仍是配置的持久事实来源。 type RegisterRiskConfigCache interface { @@ -255,6 +295,8 @@ type Service struct { registrationLevelBadgeIssuer RegistrationLevelBadgeIssuer // imAccountImporter 在用户创建成功后补齐腾讯 IM 账号;UserSig 入口仍会兜底补偿历史账号。 imAccountImporter IMAccountImporter + // refreshMetrics 只记录固定指标名和 App 维度,避免 session/user 等高基数标签污染指标系统。 + refreshMetrics RefreshMetricRecorder } // Option 调整 auth service 的依赖和策略。 @@ -271,6 +313,7 @@ func New(cfg Config, options ...Option) *Service { now: time.Now, allocateMaxAttempts: 8, loginRiskPolicy: DefaultLoginRiskPolicy(), + refreshMetrics: logRefreshMetricRecorder{}, } for _, option := range options { @@ -281,6 +324,23 @@ func New(cfg Config, options ...Option) *Service { return svc } +// WithRefreshMetricRecorder 允许测试或后续 metrics exporter 注入计数器实现。 +func WithRefreshMetricRecorder(recorder RefreshMetricRecorder) Option { + return func(s *Service) { + if recorder != nil { + s.refreshMetrics = recorder + } + } +} + +func (s *Service) SessionDenylistEpoch(ctx context.Context) (string, error) { + reader, ok := s.ipDecisionCache.(SessionDenylistEpochReader) + if !ok || reader == nil { + return "", xerr.New(xerr.Unavailable, "session denylist Redis epoch is unavailable") + } + return reader.SessionDenylistEpoch(ctx) +} + func DefaultLoginRiskPolicy() LoginRiskPolicy { return LoginRiskPolicy{ Enabled: true, diff --git a/services/user-service/internal/service/auth/service_test.go b/services/user-service/internal/service/auth/service_test.go index 90b5a321..488c0ffc 100644 --- a/services/user-service/internal/service/auth/service_test.go +++ b/services/user-service/internal/service/auth/service_test.go @@ -5,8 +5,10 @@ import ( "context" "encoding/json" "errors" + "fmt" "net/http" "net/http/httptest" + "os" "strings" "sync" "testing" @@ -20,6 +22,7 @@ import ( "hyapp/services/user-service/internal/testutil/mysqltest" jwt "github.com/golang-jwt/jwt/v5" + "github.com/redis/go-redis/v9" ) const testAccessTokenTTLSec int64 = 604800 @@ -68,6 +71,36 @@ type memoryDecisionCache struct { err error } +type memoryRefreshMetrics struct { + mu sync.Mutex + counts map[string]int +} + +type failingRotateAuthRepository struct { + // 嵌入真实 repository 让测试只替换 rotation commit,其他查找仍走同一个 MySQL schema。 + authservice.AuthRepository +} + +func (r failingRotateAuthRepository) RotateRefreshSession(context.Context, authdomain.RefreshRotationCommand) (authdomain.RefreshRotationResult, error) { + return authdomain.RefreshRotationResult{}, errors.New("forced rotation commit failure") +} + +func newMemoryRefreshMetrics() *memoryRefreshMetrics { + return &memoryRefreshMetrics{counts: make(map[string]int)} +} + +func (m *memoryRefreshMetrics) Increment(_ context.Context, metric string, appCode string) { + m.mu.Lock() + defer m.mu.Unlock() + m.counts[appCode+":"+metric]++ +} + +func (m *memoryRefreshMetrics) count(appCode string, metric string) int { + m.mu.Lock() + defer m.mu.Unlock() + return m.counts[appCode+":"+metric] +} + func newMemoryDecisionCache() *memoryDecisionCache { return &memoryDecisionCache{ ip: make(map[string]authservice.IPDecision), @@ -447,8 +480,9 @@ func TestThirdPartyUserSetsPasswordThenLogsIn(t *testing.T) { t.Fatalf("refresh client version audit mismatch: app_version=%q build_number=%q", auditedAppVersion, auditedBuildNumber) } - if _, err := svc.RefreshToken(ctx, loginToken.RefreshToken, "ios", authservice.Meta{}); !xerr.IsCode(err, xerr.SessionRevoked) { - t.Fatalf("expected old refresh token revoked, got %v", err) + graceToken, err := svc.RefreshToken(ctx, loginToken.RefreshToken, "ios", authservice.Meta{}) + if err != nil || graceToken.AccessToken != refreshToken.AccessToken || graceToken.RefreshToken != refreshToken.RefreshToken || graceToken.SessionID != refreshToken.SessionID { + t.Fatalf("direct parent retry must return the exact first token pair: got=%+v err=%v want=%+v", graceToken, err, refreshToken) } revoked, err := svc.Logout(ctx, refreshToken.SessionID, refreshToken.RefreshToken, authservice.Meta{RequestID: "req-logout"}) @@ -466,8 +500,9 @@ func TestThirdPartyUserSetsPasswordThenLogsIn(t *testing.T) { } } -func TestRefreshTokenDenylistFailureDoesNotConsumeSession(t *testing.T) { - // refresh 轮换前必须先让旧 sid 进入 gateway denylist;Redis 失败时不能消耗 refresh token。 +func TestRefreshTokenDenylistFailureRecoversPersistedRotationOnRetry(t *testing.T) { + // MySQL 先原子提交 rotation/outcome/job;Redis 短暂失败时首个请求返回 unavailable, + // 同一个旧 refresh token 的重试必须从 grace outcome 恢复同一 token pair,不能再建 child 或分叉。 ctx := context.Background() repository := mysqltest.NewRepository(t) seedCountry(t, repository, "SG") @@ -481,21 +516,751 @@ func TestRefreshTokenDenylistFailureDoesNotConsumeSession(t *testing.T) { } cache.err = errors.New("redis unavailable") - if _, err := svc.RefreshToken(ctx, token.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RequestID: "req-refresh-fail"}); err == nil { - t.Fatal("RefreshToken should fail when access denylist write fails") + refreshMeta := authservice.Meta{AppCode: "lalu", RequestID: "req-refresh-fail", RefreshRequestID: "refresh-after-redis-outage"} + if _, err := svc.RefreshToken(ctx, token.RefreshToken, "dev-ios", refreshMeta); !xerr.IsCode(err, xerr.Unavailable) { + t.Fatalf("RefreshToken should surface unavailable when access denylist write fails: %v", err) + } + var revokedReason string + var childCount int + var outcomeCount int + var pendingJobs int + if err := repository.RawDB().QueryRowContext(ctx, `SELECT revoked_reason FROM auth_sessions WHERE session_id = ?`, token.SessionID).Scan(&revokedReason); err != nil { + t.Fatalf("query committed parent rotation failed: %v", err) + } + if err := repository.RawDB().QueryRowContext(ctx, `SELECT COUNT(*) FROM auth_sessions WHERE parent_session_id = ?`, token.SessionID).Scan(&childCount); err != nil { + t.Fatalf("query committed child failed: %v", err) + } + if err := repository.RawDB().QueryRowContext(ctx, `SELECT COUNT(*) FROM auth_refresh_outcomes WHERE parent_session_id = ?`, token.SessionID).Scan(&outcomeCount); err != nil { + t.Fatalf("query committed refresh outcome failed: %v", err) + } + if err := repository.RawDB().QueryRowContext(ctx, `SELECT COUNT(*) FROM auth_session_denylist_jobs WHERE session_id = ? AND status = 'pending'`, token.SessionID).Scan(&pendingJobs); err != nil { + t.Fatalf("query committed denylist job failed: %v", err) + } + if revokedReason != "REFRESH_ROTATED" || childCount != 1 || outcomeCount != 1 || pendingJobs != 1 { + t.Fatalf("rotation transaction mismatch: reason=%q children=%d outcomes=%d pending_jobs=%d", revokedReason, childCount, outcomeCount, pendingJobs) } cache.err = nil - refreshed, err := svc.RefreshToken(ctx, token.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RequestID: "req-refresh-retry"}) + refreshed, err := svc.RefreshToken(ctx, token.RefreshToken, "dev-ios", refreshMeta) if err != nil { - t.Fatalf("RefreshToken retry should still use original refresh token: %v", err) + t.Fatalf("RefreshToken retry must recover persisted outcome: %v", err) } if refreshed.SessionID == token.SessionID || refreshed.RefreshToken == token.RefreshToken { - t.Fatalf("retry must rotate session and refresh token: old=%+v new=%+v", token, refreshed) + t.Fatalf("recovered outcome must contain rotated session and refresh token: old=%+v new=%+v", token, refreshed) + } + again, err := svc.RefreshToken(ctx, token.RefreshToken, "dev-ios", refreshMeta) + if err != nil || again.AccessToken != refreshed.AccessToken || again.RefreshToken != refreshed.RefreshToken || again.SessionID != refreshed.SessionID { + t.Fatalf("subsequent grace retry must return exact persisted pair: first=%+v again=%+v err=%v", refreshed, again, err) } if got := cache.revoked["lalu:"+token.SessionID]; got != "REFRESH_ROTATED" { t.Fatalf("retry must denylist original session, got %q", got) } + var deliveredJobs int + if err := repository.RawDB().QueryRowContext(ctx, `SELECT COUNT(*) FROM auth_session_denylist_jobs WHERE session_id = ? AND status = 'delivered'`, token.SessionID).Scan(&deliveredJobs); err != nil { + t.Fatalf("query delivered denylist job failed: %v", err) + } + if deliveredJobs != 1 { + t.Fatalf("successful retry must close the durable denylist job, got %d", deliveredJobs) + } +} + +func TestRefreshTokenDatabaseFailureDoesNotDenyActiveSession(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + seedCountry(t, repository, "SG") + now := time.UnixMilli(1000) + cache := newMemoryDecisionCache() + normal := newAuthService(repository, &now, []int64{900044}, []string{"100044"}, authservice.WithIPDecisionCache(cache)) + + token, _, err := normal.LoginThirdParty(ctx, "wechat", "openid-refresh-db-failure", thirdPartyRegistration("ios"), authservice.Meta{AppCode: "lalu"}) + if err != nil { + t.Fatalf("login failed: %v", err) + } + failing := newAuthService(repository, &now, []int64{900045}, []string{"100045"}, + authservice.WithIPDecisionCache(cache), + authservice.WithAuthRepository(failingRotateAuthRepository{AuthRepository: repository}), + ) + if _, err := failing.RefreshToken(ctx, token.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RefreshRequestID: "db-failure"}); err == nil { + t.Fatal("refresh must surface the forced MySQL failure") + } + if got, ok := cache.revoked["lalu:"+token.SessionID]; ok { + t.Fatalf("failed DB rotation must not deny the still-active sid, got %q", got) + } + var revokedAt *int64 + var childCount int + var jobCount int + if err := repository.RawDB().QueryRowContext(ctx, `SELECT revoked_at_ms FROM auth_sessions WHERE session_id = ?`, token.SessionID).Scan(&revokedAt); err != nil { + t.Fatalf("query source session failed: %v", err) + } + if err := repository.RawDB().QueryRowContext(ctx, `SELECT COUNT(*) FROM auth_sessions WHERE parent_session_id = ?`, token.SessionID).Scan(&childCount); err != nil { + t.Fatalf("query child sessions failed: %v", err) + } + if err := repository.RawDB().QueryRowContext(ctx, `SELECT COUNT(*) FROM auth_session_denylist_jobs WHERE session_id = ?`, token.SessionID).Scan(&jobCount); err != nil { + t.Fatalf("query denylist jobs failed: %v", err) + } + if revokedAt != nil || childCount != 0 || jobCount != 0 { + t.Fatalf("failed DB rotation changed durable state: revoked_at=%v children=%d jobs=%d", revokedAt, childCount, jobCount) + } +} + +func TestRefreshDenylistDeadlineKeepsHistoricalSevenDayFloor(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + seedCountry(t, repository, "SG") + now := time.UnixMilli(1000) + cache := newMemoryDecisionCache() + loginSvc := newAuthService(repository, &now, []int64{900046}, []string{"100046"}, authservice.WithIPDecisionCache(cache)) + token, _, err := loginSvc.LoginThirdParty(ctx, "wechat", "openid-short-access-ttl", thirdPartyRegistration("ios"), authservice.Meta{AppCode: "lalu"}) + if err != nil { + t.Fatalf("login failed: %v", err) + } + + // 模拟 access TTL 从历史 7 天降到 1 小时;撤销 deadline 仍须覆盖已签发的历史 token。 + shortTTLSvc := authservice.New(authservice.Config{ + Issuer: "hyapp-test", + AccessTokenTTLSec: 3600, + RefreshTokenTTLSec: 2592000, + SigningAlg: "HS256", + SigningSecret: "test-secret", + }, + authservice.WithAuthRepository(repository), + authservice.WithUserRepository(repository), + authservice.WithIdentityRepository(repository), + authservice.WithCountryRegionRepository(repository), + authservice.WithClock(func() time.Time { return now }), + authservice.WithIPDecisionCache(cache), + ) + if _, err := shortTTLSvc.RefreshToken(ctx, token.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RefreshRequestID: "short-ttl-refresh"}); err != nil { + t.Fatalf("refresh with shorter current TTL failed: %v", err) + } + if got, want := cache.revTTL["lalu:"+token.SessionID], 7*24*time.Hour+time.Minute; got != want { + t.Fatalf("historical access TTL floor was shortened: got=%s want=%s", got, want) + } +} + +func TestSessionDenylistHydrationPaginatesAllStatesAndFailsOnRedisError(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + now := time.UnixMilli(1000) + const jobCount = 1001 + tx, err := repository.RawDB().BeginTx(ctx, nil) + if err != nil { + t.Fatalf("begin denylist seed transaction failed: %v", err) + } + statement, err := tx.PrepareContext(ctx, ` + INSERT INTO auth_session_denylist_jobs + (app_code, session_id, reason, status, attempts, next_retry_at_ms, locked_by, locked_until_ms, last_error, deny_until_ms, created_at_ms, updated_at_ms) + VALUES ('lalu', ?, 'REFRESH_TOKEN_REUSE', ?, 0, ?, ?, ?, '', ?, ?, ?) + `) + if err != nil { + _ = tx.Rollback() + t.Fatalf("prepare denylist seed failed: %v", err) + } + statuses := []string{"delivered", "processing", "retryable"} + for index := 0; index < jobCount; index++ { + status := statuses[index%len(statuses)] + lockedBy := "" + lockedUntilMs := int64(0) + if status == "processing" { + lockedBy = "old-pod" + lockedUntilMs = now.Add(time.Hour).UnixMilli() + } + // retryable 的 next_retry 在未来,证明 hydration 不受 worker 调度状态约束。 + if _, err := statement.ExecContext(ctx, fmt.Sprintf("hydrate-%04d", index), status, now.Add(time.Hour).UnixMilli(), lockedBy, lockedUntilMs, now.Add(8*24*time.Hour).UnixMilli(), now.UnixMilli(), now.UnixMilli()); err != nil { + _ = statement.Close() + _ = tx.Rollback() + t.Fatalf("seed denylist job %d failed: %v", index, err) + } + } + if err := statement.Close(); err != nil { + _ = tx.Rollback() + t.Fatalf("close denylist seed statement failed: %v", err) + } + if err := tx.Commit(); err != nil { + t.Fatalf("commit denylist seeds failed: %v", err) + } + + cache := newMemoryDecisionCache() + svc := newAuthService(repository, &now, []int64{900047}, []string{"100047"}, authservice.WithIPDecisionCache(cache)) + processed, err := svc.RehydrateAllSessionDenylistJobs(ctx, 100) + if err != nil || processed != jobCount { + t.Fatalf("hydrate all denylist jobs failed: processed=%d err=%v", processed, err) + } + if got := len(cache.revoked); got != jobCount { + t.Fatalf("hydration cursor skipped jobs: got=%d want=%d", got, jobCount) + } + for _, index := range []int{0, 500, 1000} { + if got := cache.revoked[fmt.Sprintf("lalu:hydrate-%04d", index)]; got != "REFRESH_TOKEN_REUSE" { + t.Fatalf("hydrated sid %d missing: %q", index, got) + } + } + + failingCache := newMemoryDecisionCache() + failingCache.err = errors.New("redis unavailable") + failingSvc := newAuthService(repository, &now, []int64{900048}, []string{"100048"}, authservice.WithIPDecisionCache(failingCache)) + processed, err = failingSvc.RehydrateAllSessionDenylistJobs(ctx, 100) + if err == nil || processed != 0 { + t.Fatalf("hydration must fail closed on Redis error: processed=%d err=%v", processed, err) + } +} + +func TestSessionDenylistDeliveredCASDoesNotHideExtendedDeadline(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + nowMs := int64(1000) + oldDenyUntilMs := nowMs + int64(time.Hour/time.Millisecond) + newDenyUntilMs := nowMs + int64((2*time.Hour)/time.Millisecond) + result, err := repository.RawDB().ExecContext(ctx, ` + INSERT INTO auth_session_denylist_jobs + (app_code, session_id, reason, status, attempts, next_retry_at_ms, locked_by, locked_until_ms, last_error, deny_until_ms, created_at_ms, updated_at_ms) + VALUES ('lalu', 'cas-extended-sid', 'REFRESH_ROTATED', 'processing', 1, 0, 'old-worker', 5000, '', ?, ?, ?) + `, oldDenyUntilMs, nowMs, nowMs) + if err != nil { + t.Fatalf("seed claimed denylist job failed: %v", err) + } + jobID, err := result.LastInsertId() + if err != nil { + t.Fatalf("read denylist job id failed: %v", err) + } + // 模拟 worker 写 Redis 旧 TTL 的同时,另一事务把同 sid 延长并重新置 pending。 + if _, err := repository.RawDB().ExecContext(ctx, ` + UPDATE auth_session_denylist_jobs + SET deny_until_ms = ?, reason = 'REFRESH_TOKEN_REUSE', status = 'pending', locked_by = '', locked_until_ms = 0 + WHERE job_id = ? + `, newDenyUntilMs, jobID); err != nil { + t.Fatalf("extend denylist deadline failed: %v", err) + } + if err := repository.MarkSessionDenylistJobDelivered(ctx, jobID, "lalu", "cas-extended-sid", "REFRESH_ROTATED", oldDenyUntilMs, nowMs, nowMs+1000); err != nil { + t.Fatalf("stale delivered CAS failed: %v", err) + } + var status string + var denyUntilMs int64 + if err := repository.RawDB().QueryRowContext(ctx, `SELECT status, deny_until_ms FROM auth_session_denylist_jobs WHERE job_id = ?`, jobID).Scan(&status, &denyUntilMs); err != nil { + t.Fatalf("query extended denylist job failed: %v", err) + } + if status != "pending" || denyUntilMs != newDenyUntilMs { + t.Fatalf("stale worker hid extended deadline: status=%s deny_until=%d want=%d", status, denyUntilMs, newDenyUntilMs) + } +} + +func TestRedisSessionDenylistTTLOnlyExtends(t *testing.T) { + redisAddr := strings.TrimSpace(os.Getenv("HYAPP_TEST_REDIS_ADDR")) + if redisAddr == "" { + t.Skip("HYAPP_TEST_REDIS_ADDR is not configured") + } + ctx := context.Background() + client := redis.NewClient(&redis.Options{Addr: redisAddr}) + t.Cleanup(func() { _ = client.Close() }) + if err := client.Ping(ctx).Err(); err != nil { + t.Fatalf("connect test Redis failed: %v", err) + } + const key = "auth:revoked_session:lalu:ttl-only-extends" + t.Cleanup(func() { _ = client.Del(context.Background(), key).Err() }) + if err := client.Del(ctx, key).Err(); err != nil { + t.Fatalf("clear test denylist key failed: %v", err) + } + cache := authservice.NewRedisIPDecisionCache(client) + if err := cache.SetRevokedSession(ctx, "lalu", "ttl-only-extends", "LONG", 10*time.Second); err != nil { + t.Fatalf("write initial denylist TTL failed: %v", err) + } + if err := cache.SetRevokedSession(ctx, "lalu", "ttl-only-extends", "SHORT", time.Second); err != nil { + t.Fatalf("write shorter denylist TTL failed: %v", err) + } + shortAttemptTTL, err := client.PTTL(ctx, key).Result() + if err != nil { + t.Fatalf("read denylist TTL after shorter attempt failed: %v", err) + } + value, err := client.Get(ctx, key).Result() + if err != nil { + t.Fatalf("read denylist reason after shorter attempt failed: %v", err) + } + if shortAttemptTTL < 9*time.Second || value != "LONG" { + t.Fatalf("shorter stale write reduced protection: ttl=%s value=%q", shortAttemptTTL, value) + } + if err := cache.SetRevokedSession(ctx, "lalu", "ttl-only-extends", "EXTENDED", 20*time.Second); err != nil { + t.Fatalf("extend denylist TTL failed: %v", err) + } + extendedTTL, err := client.PTTL(ctx, key).Result() + if err != nil { + t.Fatalf("read extended denylist TTL failed: %v", err) + } + value, err = client.Get(ctx, key).Result() + if err != nil { + t.Fatalf("read extended denylist reason failed: %v", err) + } + if extendedTTL < 19*time.Second || value != "EXTENDED" { + t.Fatalf("longer write did not extend protection: ttl=%s value=%q", extendedTTL, value) + } + if epoch, err := cache.SessionDenylistEpoch(ctx); err != nil || strings.TrimSpace(epoch) == "" { + t.Fatalf("Redis epoch must expose run_id for restart detection: epoch=%q err=%v", epoch, err) + } +} + +func TestRefreshRotationGraceReplayRevokesFamilyAndDurablyRetriesDenylist(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + seedCountry(t, repository, "SG") + now := time.UnixMilli(1000) + cache := newMemoryDecisionCache() + metrics := newMemoryRefreshMetrics() + svc := newAuthService(repository, &now, []int64{900016}, []string{"100016"}, + authservice.WithIPDecisionCache(cache), + authservice.WithRefreshMetricRecorder(metrics), + ) + + root, _, err := svc.LoginThirdParty(ctx, "wechat", "openid-refresh-family", thirdPartyRegistration("ios"), authservice.Meta{AppCode: "lalu", RequestID: "req-login"}) + if err != nil { + t.Fatalf("LoginThirdParty failed: %v", err) + } + now = now.Add(time.Second) + first, err := svc.RefreshToken(ctx, root.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RequestID: "trace-1", RefreshRequestID: "refresh-attempt-1"}) + if err != nil { + t.Fatalf("first refresh failed: %v", err) + } + now = now.Add(10 * time.Second) + grace, err := svc.RefreshToken(ctx, root.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RequestID: "trace-2", RefreshRequestID: "refresh-attempt-network-retry"}) + if err != nil || grace.AccessToken != first.AccessToken || grace.RefreshToken != first.RefreshToken || grace.SessionID != first.SessionID { + t.Fatalf("direct predecessor grace must reuse exact token pair: grace=%+v first=%+v err=%v", grace, first, err) + } + now = now.Add(time.Second) + second, err := svc.RefreshToken(ctx, first.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RequestID: "trace-3", RefreshRequestID: "refresh-attempt-2"}) + if err != nil { + t.Fatalf("second generation refresh failed: %v", err) + } + + var rootFamily string + var rootGeneration int64 + var firstFamily string + var firstGeneration int64 + var secondFamily string + var secondGeneration int64 + if err := repository.RawDB().QueryRowContext(ctx, `SELECT token_family_id, generation FROM auth_sessions WHERE session_id = ?`, root.SessionID).Scan(&rootFamily, &rootGeneration); err != nil { + t.Fatalf("query root lineage failed: %v", err) + } + if err := repository.RawDB().QueryRowContext(ctx, `SELECT token_family_id, generation FROM auth_sessions WHERE session_id = ?`, first.SessionID).Scan(&firstFamily, &firstGeneration); err != nil { + t.Fatalf("query first lineage failed: %v", err) + } + if err := repository.RawDB().QueryRowContext(ctx, `SELECT token_family_id, generation FROM auth_sessions WHERE session_id = ?`, second.SessionID).Scan(&secondFamily, &secondGeneration); err != nil { + t.Fatalf("query second lineage failed: %v", err) + } + if rootFamily != root.SessionID || firstFamily != rootFamily || secondFamily != rootFamily || rootGeneration != 0 || firstGeneration != 1 || secondGeneration != 2 { + t.Fatalf("token family lineage mismatch: root=%s/%d first=%s/%d second=%s/%d", rootFamily, rootGeneration, firstFamily, firstGeneration, secondFamily, secondGeneration) + } + + cache.err = errors.New("redis unavailable") + now = now.Add(time.Second) + if _, err := svc.RefreshToken(ctx, root.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RequestID: "trace-reuse", RefreshRequestID: "refresh-attempt-reuse"}); !xerr.IsCode(err, xerr.Unavailable) { + t.Fatalf("second-to-last token must revoke family and surface denylist outage: %v", err) + } + var activeReason string + if err := repository.RawDB().QueryRowContext(ctx, `SELECT revoked_reason FROM auth_sessions WHERE session_id = ?`, second.SessionID).Scan(&activeReason); err != nil { + t.Fatalf("query active generation after reuse failed: %v", err) + } + if activeReason != "REFRESH_TOKEN_REUSE" { + t.Fatalf("active generation must be revoked on reuse, got %q", activeReason) + } + var pendingJobs int + if err := repository.RawDB().QueryRowContext(ctx, `SELECT COUNT(*) FROM auth_session_denylist_jobs WHERE app_code = 'lalu' AND reason = 'REFRESH_TOKEN_REUSE' AND status = 'pending'`).Scan(&pendingJobs); err != nil { + t.Fatalf("query durable denylist jobs failed: %v", err) + } + if pendingJobs != 3 { + t.Fatalf("family revoke must persist one denylist job per sid, got %d", pendingJobs) + } + processed, err := svc.ProcessSessionDenylistBatch(ctx, "denylist-test", 10) + if err == nil || processed != 3 { + t.Fatalf("denylist worker must move failed Redis writes to retryable: processed=%d err=%v", processed, err) + } + var retryableJobs int + if err := repository.RawDB().QueryRowContext(ctx, `SELECT COUNT(*) FROM auth_session_denylist_jobs WHERE app_code = 'lalu' AND reason = 'REFRESH_TOKEN_REUSE' AND status = 'retryable'`).Scan(&retryableJobs); err != nil { + t.Fatalf("query retryable denylist jobs failed: %v", err) + } + if retryableJobs != 3 { + t.Fatalf("failed compensation must leave all jobs retryable, got %d", retryableJobs) + } + cache.err = nil + now = now.Add(3 * time.Second) + processed, err = svc.ProcessSessionDenylistBatch(ctx, "denylist-test", 10) + if err != nil || processed != 3 { + t.Fatalf("denylist retry compensation failed: processed=%d err=%v", processed, err) + } + for _, sessionID := range []string{root.SessionID, first.SessionID, second.SessionID} { + if got := cache.revoked["lalu:"+sessionID]; got != "REFRESH_TOKEN_REUSE" { + t.Fatalf("family sid %s missing replay denylist, got %q", sessionID, got) + } + } + var deliveredJobs int + if err := repository.RawDB().QueryRowContext(ctx, `SELECT COUNT(*) FROM auth_session_denylist_jobs WHERE app_code = 'lalu' AND reason = 'REFRESH_TOKEN_REUSE' AND status = 'delivered'`).Scan(&deliveredJobs); err != nil { + t.Fatalf("query delivered denylist jobs failed: %v", err) + } + if deliveredJobs != 3 { + t.Fatalf("all denylist jobs must be delivered, got %d", deliveredJobs) + } + var outcomeCount int + if err := repository.RawDB().QueryRowContext(ctx, `SELECT COUNT(*) FROM auth_refresh_outcomes WHERE app_code = 'lalu'`).Scan(&outcomeCount); err != nil { + t.Fatalf("query refresh outcomes failed: %v", err) + } + if outcomeCount != 0 { + t.Fatalf("family revoke must delete encrypted token outcomes, got %d", outcomeCount) + } + if metrics.count("lalu", "refresh_success") != 2 || metrics.count("lalu", "grace_hit") != 1 || metrics.count("lalu", "token_reuse") != 1 || metrics.count("lalu", "family_revoked") != 1 { + t.Fatalf("refresh metrics mismatch: %+v", metrics.counts) + } +} + +func TestConcurrentRefreshRetriesReturnOnePersistedTokenPair(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + seedCountry(t, repository, "SG") + now := time.UnixMilli(1000) + cache := newMemoryDecisionCache() + metrics := newMemoryRefreshMetrics() + svc := newAuthService(repository, &now, []int64{900019}, []string{"100019"}, + authservice.WithIPDecisionCache(cache), + authservice.WithRefreshMetricRecorder(metrics), + ) + + root, _, err := svc.LoginThirdParty(ctx, "wechat", "openid-concurrent-refresh", thirdPartyRegistration("ios"), authservice.Meta{AppCode: "lalu", RequestID: "req-login"}) + if err != nil { + t.Fatalf("login failed: %v", err) + } + now = now.Add(time.Second) + + const parallel = 20 + start := make(chan struct{}) + results := make(chan authdomain.Token, parallel) + errorsCh := make(chan error, parallel) + var wg sync.WaitGroup + for i := 0; i < parallel; i++ { + wg.Add(1) + go func() { + defer wg.Done() + <-start + token, refreshErr := svc.RefreshToken(ctx, root.RefreshToken, "dev-ios", authservice.Meta{ + AppCode: "lalu", + RequestID: "trace-concurrent-refresh", + RefreshRequestID: "refresh-request-single-flight", + }) + if refreshErr != nil { + errorsCh <- refreshErr + return + } + results <- token + }() + } + close(start) + wg.Wait() + close(results) + close(errorsCh) + for refreshErr := range errorsCh { + t.Fatalf("concurrent refresh failed: %v", refreshErr) + } + + var canonical authdomain.Token + count := 0 + for token := range results { + if count == 0 { + canonical = token + } else if token.AccessToken != canonical.AccessToken || token.RefreshToken != canonical.RefreshToken || token.SessionID != canonical.SessionID { + t.Fatalf("concurrent retry forked token pair: canonical=%+v got=%+v", canonical, token) + } + count++ + } + if count != parallel { + t.Fatalf("concurrent result count mismatch: got=%d want=%d", count, parallel) + } + + var childCount int + if err := repository.RawDB().QueryRowContext(ctx, `SELECT COUNT(*) FROM auth_sessions WHERE app_code = 'lalu' AND parent_session_id = ?`, root.SessionID).Scan(&childCount); err != nil { + t.Fatalf("query refresh child count failed: %v", err) + } + if childCount != 1 { + t.Fatalf("concurrent refresh must create exactly one child, got %d", childCount) + } + var outcomeCount int + if err := repository.RawDB().QueryRowContext(ctx, `SELECT COUNT(*) FROM auth_refresh_outcomes WHERE app_code = 'lalu' AND parent_session_id = ?`, root.SessionID).Scan(&outcomeCount); err != nil { + t.Fatalf("query refresh outcome count failed: %v", err) + } + if outcomeCount != 1 { + t.Fatalf("concurrent refresh must persist exactly one canonical outcome, got %d", outcomeCount) + } + if metrics.count("lalu", "refresh_success") != 1 || metrics.count("lalu", "grace_hit") != parallel-1 { + t.Fatalf("concurrent refresh metrics mismatch: %+v", metrics.counts) + } +} + +func TestRefreshGraceUsesPersistedWinnerDeadlineAcrossConfigRollout(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + seedCountry(t, repository, "SG") + now := time.UnixMilli(1000) + cache := newMemoryDecisionCache() + winner := newAuthService(repository, &now, []int64{900043}, []string{"100043"}, authservice.WithIPDecisionCache(cache)) + + root, _, err := winner.LoginThirdParty(ctx, "wechat", "openid-refresh-grace-config-rollout", thirdPartyRegistration("ios"), authservice.Meta{AppCode: "lalu"}) + if err != nil { + t.Fatalf("login failed: %v", err) + } + now = now.Add(time.Second) + first, err := winner.RefreshToken(ctx, root.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RefreshRequestID: "winner-30s-grace"}) + if err != nil { + t.Fatalf("winner refresh failed: %v", err) + } + + // retry 实例模拟滚动配置从 30s 降到 10s;首次事务固化的 30s deadline 才是这次 token pair 的唯一窗口事实。 + retry := authservice.New(authservice.Config{ + Issuer: "hyapp-test", + AccessTokenTTLSec: testAccessTokenTTLSec, + RefreshTokenTTLSec: 2592000, + RefreshRotationGraceSec: 10, + SigningAlg: "HS256", + SigningSecret: "test-secret", + }, + authservice.WithAuthRepository(repository), + authservice.WithClock(func() time.Time { return now }), + authservice.WithIPDecisionCache(cache), + ) + now = now.Add(5 * time.Second) + grace, err := retry.RefreshToken(ctx, root.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RefreshRequestID: "retry-on-10s-instance"}) + if err != nil || grace.AccessToken != first.AccessToken || grace.RefreshToken != first.RefreshToken || grace.SessionID != first.SessionID { + t.Fatalf("retry must trust persisted winner deadline and return exact pair: grace=%+v first=%+v err=%v", grace, first, err) + } +} + +func TestLegacyActiveSessionFirstRotationUsesItselfAsFamilyRoot(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + seedCountry(t, repository, "SG") + now := time.UnixMilli(1000) + cache := newMemoryDecisionCache() + svc := newAuthService(repository, &now, []int64{900040}, []string{"100040"}, authservice.WithIPDecisionCache(cache)) + + legacy, _, err := svc.LoginThirdParty(ctx, "wechat", "openid-legacy-refresh-family", thirdPartyRegistration("ios"), authservice.Meta{AppCode: "lalu"}) + if err != nil { + t.Fatalf("login failed: %v", err) + } + // 模拟 018 上线前已存在的 active 行:新增列默认空值,首次新版轮换必须原地升级 lineage,不能另起错误 family。 + if _, err := repository.RawDB().ExecContext(ctx, ` + UPDATE auth_sessions + SET token_family_id = '', generation = 0, parent_session_id = '', rotated_to_session_id = '', rotation_at_ms = 0, rotation_request_id = '' + WHERE app_code = 'lalu' AND session_id = ? + `, legacy.SessionID); err != nil { + t.Fatalf("downgrade session to legacy lineage failed: %v", err) + } + + now = now.Add(time.Second) + child, err := svc.RefreshToken(ctx, legacy.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RefreshRequestID: "legacy-first-refresh"}) + if err != nil { + t.Fatalf("legacy first rotation failed: %v", err) + } + var parentFamily string + var childFamily string + var childGeneration int64 + var childParent string + if err := repository.RawDB().QueryRowContext(ctx, `SELECT token_family_id FROM auth_sessions WHERE session_id = ?`, legacy.SessionID).Scan(&parentFamily); err != nil { + t.Fatalf("query upgraded legacy parent failed: %v", err) + } + if err := repository.RawDB().QueryRowContext(ctx, `SELECT token_family_id, generation, parent_session_id FROM auth_sessions WHERE session_id = ?`, child.SessionID).Scan(&childFamily, &childGeneration, &childParent); err != nil { + t.Fatalf("query legacy child lineage failed: %v", err) + } + if parentFamily != legacy.SessionID || childFamily != legacy.SessionID || childGeneration != 1 || childParent != legacy.SessionID { + t.Fatalf("legacy lineage upgrade mismatch: parent_family=%q child_family=%q generation=%d parent=%q root=%q", parentFamily, childFamily, childGeneration, childParent, legacy.SessionID) + } +} + +func TestLegacyBinaryRotationReplayDoesNotRevokeUnprovenNewSessions(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + seedCountry(t, repository, "SG") + now := time.UnixMilli(1000) + cache := newMemoryDecisionCache() + metrics := newMemoryRefreshMetrics() + svc := newAuthService(repository, &now, []int64{900042}, []string{"100042"}, + authservice.WithIPDecisionCache(cache), + authservice.WithRefreshMetricRecorder(metrics), + ) + + root, _, err := svc.LoginThirdParty(ctx, "wechat", "openid-legacy-binary-rotation", thirdPartyRegistration("ios"), authservice.Meta{AppCode: "lalu"}) + if err != nil { + t.Fatalf("ios login failed: %v", err) + } + android, _, err := svc.LoginThirdParty(ctx, "wechat", "openid-legacy-binary-rotation", thirdPartyRegistration("android"), authservice.Meta{AppCode: "lalu"}) + if err != nil { + t.Fatalf("android login failed: %v", err) + } + + const legacyChildID = "sess_legacy_binary_child" + const legacyRotationAtMs = int64(2000) + // 精确模拟迁移后仍在滚动运行的旧 ReplaceSession:parent 只写 REFRESH_ROTATED,child 的六个 lineage 列全走 DDL 默认值。 + if _, err := repository.RawDB().ExecContext(ctx, ` + UPDATE auth_sessions + SET token_family_id = '', revoked_at_ms = ?, revoked_reason = 'REFRESH_ROTATED', revoked_by = 'refresh_token', + rotated_to_session_id = '', rotation_at_ms = 0, rotation_request_id = '', updated_at_ms = ? + WHERE app_code = 'lalu' AND session_id = ? + `, legacyRotationAtMs, legacyRotationAtMs, root.SessionID); err != nil { + t.Fatalf("simulate legacy parent rotation failed: %v", err) + } + if _, err := repository.RawDB().ExecContext(ctx, ` + INSERT INTO auth_sessions + (app_code, session_id, user_id, refresh_token_hash, token_family_id, generation, parent_session_id, + rotated_to_session_id, rotation_at_ms, rotation_request_id, device_id, expires_at_ms, + last_heartbeat_at_ms, last_heartbeat_request_id, revoked_at_ms, revoked_reason, revoked_request_id, + revoked_by, created_at_ms, updated_at_ms) + SELECT app_code, ?, user_id, 'legacy_binary_child_refresh_hash', '', 0, '', '', 0, '', device_id, expires_at_ms, + 0, '', NULL, '', '', '', ?, ? + FROM auth_sessions WHERE app_code = 'lalu' AND session_id = ? + `, legacyChildID, legacyRotationAtMs, legacyRotationAtMs, root.SessionID); err != nil { + t.Fatalf("simulate legacy child insert failed: %v", err) + } + + now = time.UnixMilli(3000) + if _, err := svc.RefreshToken(ctx, root.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RefreshRequestID: "legacy-parent-replay"}); !xerr.IsCode(err, xerr.SessionRevoked) { + t.Fatalf("legacy parent replay must reject the old token, got %v", err) + } + var childRevokedAt *int64 + var childReason string + if err := repository.RawDB().QueryRowContext(ctx, `SELECT revoked_at_ms, revoked_reason FROM auth_sessions WHERE session_id = ?`, legacyChildID).Scan(&childRevokedAt, &childReason); err != nil { + t.Fatalf("query unproven legacy child failed: %v", err) + } + if childRevokedAt != nil || childReason != "" { + t.Fatalf("unproven successor must remain active: revoked_at=%v reason=%q", childRevokedAt, childReason) + } + for _, sessionID := range []string{root.SessionID, legacyChildID} { + if got, ok := cache.revoked["lalu:"+sessionID]; ok { + t.Fatalf("legacy replay without provable lineage must not create denylist for sid %s, got %q", sessionID, got) + } + } + if metrics.count("lalu", "token_reuse") != 0 || metrics.count("lalu", "family_revoked") != 0 { + t.Fatalf("unproven legacy replay must not emit family-reuse metrics: %+v", metrics.counts) + } + // 显式 logout 也不能从 legacy root 按 user/device 猜 successor;它只撤销已锁定 source。 + if _, err := svc.Logout(ctx, root.SessionID, "", authservice.Meta{AppCode: "lalu", RequestID: "legacy-root-logout"}); err != nil { + t.Fatalf("legacy root logout failed: %v", err) + } + childRevokedAt = nil + childReason = "" + if err := repository.RawDB().QueryRowContext(ctx, `SELECT revoked_at_ms, revoked_reason FROM auth_sessions WHERE session_id = ?`, legacyChildID).Scan(&childRevokedAt, &childReason); err != nil { + t.Fatalf("query unproven child after logout failed: %v", err) + } + if childRevokedAt != nil || childReason != "" { + t.Fatalf("legacy logout must not revoke unproven successor: revoked_at=%v reason=%q", childRevokedAt, childReason) + } + if _, ok := cache.revoked["lalu:"+legacyChildID]; ok { + t.Fatal("legacy logout must not denylist unproven successor") + } + if _, ok := cache.revoked["lalu:"+android.SessionID]; ok { + t.Fatal("legacy replay must not revoke another device") + } + if _, err := svc.RefreshToken(ctx, android.RefreshToken, "dev-android", authservice.Meta{AppCode: "lalu", RefreshRequestID: "android-after-legacy-replay"}); err != nil { + t.Fatalf("other device must remain refreshable after legacy replay: %v", err) + } +} + +func TestCorrectRefreshTokenOnWrongDeviceRevokesItsFamilyAsReuse(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + seedCountry(t, repository, "SG") + now := time.UnixMilli(1000) + cache := newMemoryDecisionCache() + metrics := newMemoryRefreshMetrics() + svc := newAuthService(repository, &now, []int64{900041}, []string{"100041"}, + authservice.WithIPDecisionCache(cache), + authservice.WithRefreshMetricRecorder(metrics), + ) + + root, _, err := svc.LoginThirdParty(ctx, "wechat", "openid-refresh-wrong-device", thirdPartyRegistration("ios"), authservice.Meta{AppCode: "lalu"}) + if err != nil { + t.Fatalf("login failed: %v", err) + } + now = now.Add(time.Second) + if _, err := svc.RefreshToken(ctx, root.RefreshToken, "dev-android", authservice.Meta{AppCode: "lalu", RefreshRequestID: "wrong-device-replay"}); !xerr.IsCode(err, xerr.SessionRevoked) { + t.Fatalf("correct refresh token on another device must be treated as reuse, got %v", err) + } + var revokedReason string + if err := repository.RawDB().QueryRowContext(ctx, `SELECT revoked_reason FROM auth_sessions WHERE session_id = ?`, root.SessionID).Scan(&revokedReason); err != nil { + t.Fatalf("query wrong-device family revoke failed: %v", err) + } + if revokedReason != "REFRESH_TOKEN_REUSE" { + t.Fatalf("wrong-device refresh must revoke token family as reuse, got %q", revokedReason) + } + if got := cache.revoked["lalu:"+root.SessionID]; got != "REFRESH_TOKEN_REUSE" { + t.Fatalf("wrong-device reuse must denylist family access sid, got %q", got) + } + if metrics.count("lalu", "token_reuse") != 1 || metrics.count("lalu", "family_revoked") != 1 { + t.Fatalf("wrong-device reuse metrics mismatch: %+v", metrics.counts) + } +} + +func TestLogoutUsingRotatedParentRevokesOnlyThatDeviceFamily(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + seedCountry(t, repository, "SG") + now := time.UnixMilli(1000) + cache := newMemoryDecisionCache() + svc := newAuthService(repository, &now, []int64{900017}, []string{"100017"}, authservice.WithIPDecisionCache(cache)) + + iosRoot, _, err := svc.LoginThirdParty(ctx, "wechat", "openid-logout-family", thirdPartyRegistration("ios"), authservice.Meta{AppCode: "lalu", RequestID: "req-ios-login"}) + if err != nil { + t.Fatalf("ios login failed: %v", err) + } + androidRegistration := thirdPartyRegistration("android") + androidRoot, _, err := svc.LoginThirdParty(ctx, "wechat", "openid-logout-family", androidRegistration, authservice.Meta{AppCode: "lalu", RequestID: "req-android-login"}) + if err != nil { + t.Fatalf("android login failed: %v", err) + } + now = now.Add(time.Second) + iosChild, err := svc.RefreshToken(ctx, iosRoot.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RefreshRequestID: "ios-refresh"}) + if err != nil { + t.Fatalf("ios refresh failed: %v", err) + } + + revoked, err := svc.Logout(ctx, iosRoot.SessionID, iosRoot.RefreshToken, authservice.Meta{AppCode: "lalu", RequestID: "logout-parent"}) + if err != nil || !revoked { + t.Fatalf("logout by rotated parent failed: revoked=%v err=%v", revoked, err) + } + if _, err := svc.RefreshToken(ctx, iosChild.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RefreshRequestID: "ios-after-logout"}); !xerr.IsCode(err, xerr.SessionRevoked) { + t.Fatalf("rotated child must be revoked by parent logout, got %v", err) + } + for _, sessionID := range []string{iosRoot.SessionID, iosChild.SessionID} { + if got := cache.revoked["lalu:"+sessionID]; got != "USER_LOGOUT" { + t.Fatalf("ios family sid %s missing logout denylist, got %q", sessionID, got) + } + } + if _, ok := cache.revoked["lalu:"+androidRoot.SessionID]; ok { + t.Fatal("logout must not revoke a different device token family") + } + now = now.Add(time.Second) + if _, err := svc.RefreshToken(ctx, androidRoot.RefreshToken, "dev-android", authservice.Meta{AppCode: "lalu", RefreshRequestID: "android-refresh"}); err != nil { + t.Fatalf("different device family must remain refreshable: %v", err) + } +} + +func TestDirectParentRefreshAfterGraceRevokesFamily(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + seedCountry(t, repository, "SG") + now := time.UnixMilli(1000) + cache := newMemoryDecisionCache() + svc := newAuthService(repository, &now, []int64{900018}, []string{"100018"}, authservice.WithIPDecisionCache(cache)) + root, _, err := svc.LoginThirdParty(ctx, "wechat", "openid-refresh-grace-expired", thirdPartyRegistration("ios"), authservice.Meta{AppCode: "lalu"}) + if err != nil { + t.Fatalf("login failed: %v", err) + } + now = now.Add(time.Second) + child, err := svc.RefreshToken(ctx, root.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RefreshRequestID: "first"}) + if err != nil { + t.Fatalf("first refresh failed: %v", err) + } + now = now.Add(31 * time.Second) + if _, err := svc.RefreshToken(ctx, root.RefreshToken, "dev-ios", authservice.Meta{AppCode: "lalu", RefreshRequestID: "late-retry"}); !xerr.IsCode(err, xerr.SessionRevoked) { + t.Fatalf("direct parent after grace must be treated as reuse, got %v", err) + } + var reason string + if err := repository.RawDB().QueryRowContext(ctx, `SELECT revoked_reason FROM auth_sessions WHERE session_id = ?`, child.SessionID).Scan(&reason); err != nil { + t.Fatalf("query child revoke reason failed: %v", err) + } + if reason != "REFRESH_TOKEN_REUSE" { + t.Fatalf("late predecessor retry must revoke active child, got %q", reason) + } } func TestRefreshAndLogoutRequireSessionDenylistCache(t *testing.T) { diff --git a/services/user-service/internal/service/auth/session_denylist_worker.go b/services/user-service/internal/service/auth/session_denylist_worker.go new file mode 100644 index 00000000..07f4e71e --- /dev/null +++ b/services/user-service/internal/service/auth/session_denylist_worker.go @@ -0,0 +1,119 @@ +package auth + +import ( + "context" + "errors" + "time" + + "hyapp/pkg/xerr" +) + +const ( + sessionDenylistWorkerLockTTL = 15 * time.Second + sessionDenylistRetryDelay = 2 * time.Second + sessionDenylistRehydrateInterval = time.Hour +) + +// ProcessSessionDenylistBatch 把 family revoke 同事务写出的 MySQL 事实补偿到 gateway Redis denylist。 +// Redis 暂时不可用时 job 会回到 retryable;进程崩溃后 processing lease 到期也会被其他实例重新认领。 +func (s *Service) ProcessSessionDenylistBatch(ctx context.Context, workerID string, batchSize int) (int, error) { + if s.authRepository == nil || s.ipDecisionCache == nil { + return 0, xerr.New(xerr.Unavailable, "session denylist worker is unavailable") + } + if batchSize <= 0 { + batchSize = 100 + } + now := s.now() + jobs, err := s.authRepository.ClaimSessionDenylistJobs(ctx, workerID, now.UnixMilli(), now.Add(sessionDenylistWorkerLockTTL).UnixMilli(), batchSize) + if err != nil { + return 0, err + } + var batchErr error + for _, job := range jobs { + if err := s.writeRevokedAccessSessionUntil(ctx, job.AppCode, job.SessionID, job.Reason, job.DenyUntilMs); err != nil { + nextRetryAtMs := now.Add(sessionDenylistRetryDelay).UnixMilli() + if nextRetryAtMs > job.DenyUntilMs { + nextRetryAtMs = job.DenyUntilMs + } + markErr := s.authRepository.MarkSessionDenylistJobRetryable(ctx, job.JobID, err.Error(), nextRetryAtMs, now.UnixMilli()) + batchErr = errors.Join(batchErr, err, markErr) + continue + } + nextRehydrateAtMs := now.Add(sessionDenylistRehydrateInterval).UnixMilli() + if nextRehydrateAtMs > job.DenyUntilMs { + nextRehydrateAtMs = job.DenyUntilMs + } + if err := s.authRepository.MarkSessionDenylistJobDelivered(ctx, job.JobID, job.AppCode, job.SessionID, job.Reason, job.DenyUntilMs, now.UnixMilli(), nextRehydrateAtMs); err != nil { + // Redis 已成功;DB 标记失败只会导致幂等重放,不会削弱安全性。 + batchErr = errors.Join(batchErr, err) + } + } + return len(jobs), batchErr +} + +// CleanupExpiredSessionDenylistJobs 只由低频维护 ticker 调用,避免空队列时每秒给 MySQL 增加 DELETE QPS。 +// 多实例可同时执行:DELETE 使用 (deny_until_ms, job_id) 索引和 LIMIT;到期后所有状态都已无有效 JWT 需要保护。 +func (s *Service) CleanupExpiredSessionDenylistJobs(ctx context.Context, batchSize int) (int, error) { + if s.authRepository == nil { + return 0, xerr.New(xerr.Unavailable, "session denylist repository is unavailable") + } + if batchSize <= 0 { + batchSize = 1000 + } + // 清理只信任每个 job 在撤销事务内固化的 deny_until,未来配置下调不能提前删除历史 7d JWT 的保护事实。 + return s.authRepository.DeleteExpiredSessionDenylistJobs(ctx, s.now().UnixMilli(), batchSize) +} + +// CleanupExpiredRefreshOutcomes 把短期 token-pair 密文清理移出 refresh 热路径;严格走 expires_at 索引和 LIMIT。 +func (s *Service) CleanupExpiredRefreshOutcomes(ctx context.Context, batchSize int) (int, error) { + if s.authRepository == nil { + return 0, xerr.New(xerr.Unavailable, "refresh outcome repository is unavailable") + } + if batchSize <= 0 { + batchSize = 1000 + } + return s.authRepository.DeleteExpiredRefreshOutcomes(ctx, s.now().UnixMilli(), batchSize) +} + +// RehydrateAllSessionDenylistJobs 按固定 max job_id 分页直读全部未过期事实并同步写 Redis。 +// 它忽略 status/lease,不依赖旧 pod 是否 claim;固定上界和单调 cursor 让 >1000 jobs 也有限终止。 +func (s *Service) RehydrateAllSessionDenylistJobs(ctx context.Context, batchSize int) (int, error) { + if s.authRepository == nil || s.ipDecisionCache == nil { + return 0, xerr.New(xerr.Unavailable, "session denylist repository is unavailable") + } + if batchSize <= 0 { + batchSize = 1000 + } + throughJobID, err := s.authRepository.MaxSessionDenylistJobID(ctx) + if err != nil { + return 0, err + } + nowMs := s.now().UnixMilli() + var cursor int64 + total := 0 + for cursor < throughJobID { + jobs, nextCursor, err := s.authRepository.ListSessionDenylistJobsForHydration(ctx, nowMs, cursor, throughJobID, batchSize) + if err != nil { + return total, err + } + if len(jobs) == 0 || nextCursor <= cursor { + break + } + for _, job := range jobs { + if err := s.writeRevokedAccessSessionUntil(ctx, job.AppCode, job.SessionID, job.Reason, job.DenyUntilMs); err != nil { + return total, err + } + nextRehydrateAtMs := nowMs + sessionDenylistRehydrateInterval.Milliseconds() + if nextRehydrateAtMs > job.DenyUntilMs { + nextRehydrateAtMs = job.DenyUntilMs + } + // CAS 只在 job 未被并发延长时标 delivered;延长后的 pending 事实仍由普通 worker 写更长 TTL。 + if err := s.authRepository.MarkSessionDenylistJobDelivered(ctx, job.JobID, job.AppCode, job.SessionID, job.Reason, job.DenyUntilMs, nowMs, nextRehydrateAtMs); err != nil { + return total, err + } + total++ + } + cursor = nextCursor + } + return total, nil +} diff --git a/services/user-service/internal/service/auth/token.go b/services/user-service/internal/service/auth/token.go index 13186f60..0296cc73 100644 --- a/services/user-service/internal/service/auth/token.go +++ b/services/user-service/internal/service/auth/token.go @@ -2,11 +2,14 @@ package auth import ( "context" + "crypto/aes" + "crypto/cipher" "crypto/rand" "crypto/sha256" "crypto/subtle" "encoding/base64" "encoding/hex" + "encoding/json" "fmt" "strconv" "strings" @@ -20,7 +23,20 @@ import ( userdomain "hyapp/services/user-service/internal/domain/user" ) -// RefreshToken 轮换 refresh token,旧 token 成功使用后立即失效。 +const ( + defaultRefreshRotationGrace = 30 * time.Second + refreshReplayCipherVersion = "v1" + refreshMetricSuccess = "refresh_success" + refreshMetricGraceHit = "grace_hit" + refreshMetricTokenReuse = "token_reuse" + refreshMetricFamilyRevoked = "family_revoked" + revokeReasonRefreshReuse = "REFRESH_TOKEN_REUSE" + sessionDenylistSafetyMargin = 60 * time.Second + // 仓库历史曾签发 7 天 access JWT;即使配置降到 1 小时,首次撤销也必须覆盖这批尚未到期的历史 token。 + sessionDenylistHistoricalAccessTTLFloor = 7 * 24 * time.Hour +) + +// RefreshToken 轮换 refresh token;直接父代在短暂宽限期内只复用首次提交的 token pair,不能产生分叉。 func (s *Service) RefreshToken(ctx context.Context, refreshToken string, deviceID string, meta Meta) (authdomain.Token, error) { if strings.TrimSpace(refreshToken) == "" || strings.TrimSpace(deviceID) == "" { // refresh token 和 device_id 共同定位并校验会话归属。 @@ -31,58 +47,104 @@ func (s *Service) RefreshToken(ctx context.Context, refreshToken string, deviceI } nowMs := s.now().UnixMilli() - // 持久层只保存 refresh token hash,不能用原文查询。 - session, err := s.authRepository.FindActiveSessionByRefreshHash(ctx, hashRefreshToken(refreshToken), nowMs) + refreshTokenHash := hashRefreshToken(refreshToken) + refreshRequestID, err := normalizeRefreshRequestID(meta.RefreshRequestID, refreshTokenHash) if err != nil { - reason := xerr.SessionRevoked - if xerr.IsCode(err, xerr.SessionExpired) { - reason = xerr.SessionExpired + return authdomain.Token{}, err + } + // 必须读取已轮换行才能区分直接父代 grace 和更早代 replay;数据库仍只用 token hash 查询。 + session, err := s.authRepository.FindSessionByRefreshHash(ctx, refreshTokenHash) + if err != nil { + s.audit(ctx, meta, 0, loginRefresh, "", resultFailed, string(xerr.CodeOf(err))) + return authdomain.Token{}, err + } + grace := s.refreshRotationGrace() + command := authdomain.RefreshRotationCommand{ + AppCode: appcode.Normalize(meta.AppCode), + RefreshTokenHash: refreshTokenHash, + DeviceID: strings.TrimSpace(deviceID), + RefreshRequestID: refreshRequestID, + NowMs: nowMs, + GracePeriodMs: grace.Milliseconds(), + DenyUntilMs: s.sessionDenyUntilMs(nowMs), + } + + // 只有当前仍 active、未过期且设备匹配的 session 才准备新一代;已轮换 token 直接交给 repository 原子判断 grace/replay。 + if session.RevokedAtMs == 0 && session.ExpiresAtMs > nowMs && subtle.ConstantTimeCompare([]byte(session.DeviceID), []byte(strings.TrimSpace(deviceID))) == 1 { + // refresh 时重新读取用户,确保禁用状态和靓号过期恢复生效。 + user, freshErr := s.freshUser(ctx, session.UserID, nowMs, meta.RequestID) + if freshErr != nil { + s.audit(ctx, meta, session.UserID, loginRefresh, "", resultFailed, string(xerr.CodeOf(freshErr))) + return authdomain.Token{}, freshErr } - s.audit(ctx, meta, 0, loginRefresh, "", resultFailed, string(reason)) - return authdomain.Token{}, err + if !user.CanLogin() { + s.audit(ctx, meta, session.UserID, loginRefresh, "", resultFailed, string(xerr.UserDisabled)) + return authdomain.Token{}, xerr.New(xerr.UserDisabled, "user is disabled") + } + + newSession, newRefreshToken, createErr := s.newRotatedSession(session, deviceID) + if createErr != nil { + return authdomain.Token{}, createErr + } + candidateToken, issueErr := s.issueToken(user, newSession.SessionID, newSession.DeviceID, newRefreshToken, newSession.ExpiresAtMs) + if issueErr != nil { + return authdomain.Token{}, issueErr + } + ciphertext, encryptErr := s.encryptRefreshOutcome(candidateToken, session.SessionID, newSession.SessionID, refreshRequestID) + if encryptErr != nil { + return authdomain.Token{}, encryptErr + } + command.NewSession = newSession + command.TokenCiphertext = ciphertext + command.OutcomeExpiresAtMs = nowMs + grace.Milliseconds() + } - if subtle.ConstantTimeCompare([]byte(session.DeviceID), []byte(deviceID)) != 1 { - // refresh token 绑定设备,跨设备使用按 revoked 处理。 - s.audit(ctx, meta, session.UserID, loginRefresh, "", resultFailed, string(xerr.SessionRevoked)) - return authdomain.Token{}, xerr.New(xerr.SessionRevoked, "session revoked") - } - if session.AppCode != appcode.Normalize(meta.AppCode) { - // refresh token 不能跨 App 使用;即使 refresh hash 泄漏也不能从另一个包名续期。 - s.audit(ctx, meta, session.UserID, loginRefresh, "", resultFailed, string(xerr.SessionRevoked)) - return authdomain.Token{}, xerr.New(xerr.SessionRevoked, "session revoked") - } - // refresh 时重新读取用户,确保禁用状态和靓号过期恢复生效。 - user, err := s.freshUser(ctx, session.UserID, nowMs, meta.RequestID) + + rotation, err := s.authRepository.RotateRefreshSession(ctx, command) if err != nil { s.audit(ctx, meta, session.UserID, loginRefresh, "", resultFailed, string(xerr.CodeOf(err))) return authdomain.Token{}, err } - if !user.CanLogin() { - // 禁用用户不能续期会话。 - s.audit(ctx, meta, session.UserID, loginRefresh, "", resultFailed, string(xerr.UserDisabled)) - return authdomain.Token{}, xerr.New(xerr.UserDisabled, "user is disabled") - } - // refresh token 成功使用后必须轮换,旧 session 立即吊销。 - newSession, newRefreshToken, err := s.newSession(session.AppCode, session.UserID, deviceID) - if err != nil { - return authdomain.Token{}, err + switch rotation.Status { + case authdomain.RefreshRotationCreated, authdomain.RefreshRotationGraceHit: + // 无论本实例是否赢得轮换锁,都从事务内保存的密文恢复结果,保证并发和崩溃重试拿到完全相同的 token pair。 + token, decryptErr := s.decryptRefreshOutcome(rotation) + if decryptErr != nil { + s.audit(ctx, meta, session.UserID, loginRefresh, "", resultFailed, string(xerr.Unavailable)) + return authdomain.Token{}, xerr.New(xerr.Unavailable, "refresh outcome is unavailable") + } + // 先由 MySQL 原子提交 parent revoke + child + outcome + durable job,再同步写 Redis。 + // 这样 DB deadlock/失败不会把仍 active 的 sid 单独 deny;Redis 失败则返回 UNAVAILABLE,旧 RT 重试从 outcome 恢复同 pair 并再次补写。 + if err := s.writeRevokedAccessSessionUntil(ctx, rotation.SourceSession.AppCode, rotation.SourceSession.SessionID, revokeReasonRefreshRotated, command.DenyUntilMs); err != nil { + s.audit(ctx, meta, rotation.SourceSession.UserID, loginRefresh, "", resultFailed, string(xerr.Unavailable)) + return authdomain.Token{}, xerr.New(xerr.Unavailable, "rotated session denylist is unavailable") + } + _ = s.authRepository.MarkSessionDenylistJobDelivered(ctx, 0, rotation.SourceSession.AppCode, rotation.SourceSession.SessionID, revokeReasonRefreshRotated, command.DenyUntilMs, nowMs, nowMs+sessionDenylistRehydrateInterval.Milliseconds()) + if rotation.Status == authdomain.RefreshRotationCreated { + s.refreshMetrics.Increment(ctx, refreshMetricSuccess, rotation.SourceSession.AppCode) + // refresh 是登录态存续的主路径;老设备升级新客户端后,设备档案主要在这里补齐。 + s.recordUserDevice(ctx, meta, rotation.SourceSession.UserID, deviceID) + } else { + s.refreshMetrics.Increment(ctx, refreshMetricGraceHit, rotation.SourceSession.AppCode) + } + s.audit(ctx, meta, rotation.SourceSession.UserID, loginRefresh, "", resultSuccess, "") + return token, nil + case authdomain.RefreshRotationReuseDetected: + s.refreshMetrics.Increment(ctx, refreshMetricTokenReuse, rotation.SourceSession.AppCode) + if rotation.FamilyNewlyRevoked { + s.refreshMetrics.Increment(ctx, refreshMetricFamilyRevoked, rotation.SourceSession.AppCode) + } + if err := s.writeRevokedAccessFamilyUntil(ctx, rotation.SourceSession.AppCode, rotation.FamilySessionIDs, revokeReasonRefreshReuse, command.DenyUntilMs); err != nil { + // MySQL 已是 revoked 事实;返回 unavailable 促使调用方重试,后续重试会再次补齐全部 sid denylist。 + s.audit(ctx, meta, rotation.SourceSession.UserID, loginRefresh, "", resultFailed, string(xerr.Unavailable)) + return authdomain.Token{}, err + } + s.audit(ctx, meta, rotation.SourceSession.UserID, loginRefresh, "", resultFailed, string(xerr.SessionRevoked)) + return authdomain.Token{}, xerr.New(xerr.SessionRevoked, "session revoked") + default: + return authdomain.Token{}, xerr.New(xerr.Unavailable, "refresh rotation result is invalid") } - if err := s.writeRevokedAccessSession(ctx, session.AppCode, session.SessionID, revokeReasonRefreshRotated); err != nil { - // 7 天 access token 下,refresh 轮换后旧 JWT 必须立刻进入 gateway denylist。 - // 否则客户端或泄漏方仍可拿旧 sid 调业务接口直到 JWT 自然过期。 - s.audit(ctx, meta, session.UserID, loginRefresh, "", resultFailed, string(xerr.CodeOf(err))) - return authdomain.Token{}, err - } - if err := s.authRepository.ReplaceSession(ctx, session.SessionID, newSession, nowMs); err != nil { - s.audit(ctx, meta, session.UserID, loginRefresh, "", resultFailed, string(xerr.CodeOf(err))) - return authdomain.Token{}, err - } - - s.audit(ctx, meta, session.UserID, loginRefresh, "", resultSuccess, "") - // refresh 是登录态存续的主路径;老设备升级新客户端后,设备档案主要在这里补齐。 - s.recordUserDevice(ctx, meta, session.UserID, deviceID) - return s.issueToken(user, newSession.SessionID, newSession.DeviceID, newRefreshToken, newSession.ExpiresAtMs) } // IssueAccessTokenForSession 基于当前 active session 重签 access token,不轮换 refresh token。 @@ -166,7 +228,7 @@ func (s *Service) AdminIssueUserAccessToken(ctx context.Context, userID int64, m return token, session, nil } -// Logout 失效指定 session 或 refresh token。 +// Logout 失效指定 session 所属 token family;与 refresh 并发时也不能留下可继续登录的 orphan child。 func (s *Service) Logout(ctx context.Context, sessionID string, refreshToken string, meta Meta) (bool, error) { if strings.TrimSpace(sessionID) == "" && strings.TrimSpace(refreshToken) == "" { // 至少需要一种 session 定位方式。 @@ -175,47 +237,25 @@ func (s *Service) Logout(ctx context.Context, sessionID string, refreshToken str if s.authRepository == nil { return false, xerr.New(xerr.Unavailable, "auth repository is not configured") } + if s.ipDecisionCache == nil { + // 没有 Redis 写能力时不进入 DB 撤销;运行中 Redis 瞬断则由事务内 denylist job 持久补偿。 + return false, xerr.New(xerr.Unavailable, "session denylist is not configured") + } nowMs := s.now().UnixMilli() - resolvedSessionID := strings.TrimSpace(sessionID) - resolvedAppCode := appcode.Normalize(meta.AppCode) - if resolvedSessionID == "" && strings.TrimSpace(refreshToken) != "" { - // 仅带 refresh token 的 logout 需要先解析 sid,才能让已签出的 access token 在 gateway 立刻失效。 - session, err := s.authRepository.FindActiveSessionByRefreshHash(ctx, hashRefreshToken(refreshToken), nowMs) - if err == nil { - resolvedSessionID = session.SessionID - resolvedAppCode = session.AppCode - } else if !xerr.IsCode(err, xerr.SessionExpired) && !xerr.IsCode(err, xerr.SessionRevoked) { - s.audit(ctx, meta, 0, "logout", "", resultFailed, string(xerr.CodeOf(err))) - return false, err - } - } - if resolvedSessionID != "" { - if resolvedAppCode == "" { - // 兼容只传 session_id、且请求没有 App 头的旧调用;active session 自身才是 denylist 分区的可信来源。 - session, err := s.authRepository.FindActiveSessionByID(ctx, resolvedSessionID, nowMs) - if err == nil { - resolvedAppCode = session.AppCode - } else if !xerr.IsCode(err, xerr.SessionExpired) && !xerr.IsCode(err, xerr.SessionRevoked) { - s.audit(ctx, meta, 0, "logout", "", resultFailed, string(xerr.CodeOf(err))) - return false, err - } - } - if resolvedAppCode != "" { - if err := s.writeRevokedAccessSession(ctx, resolvedAppCode, resolvedSessionID, revokeReasonUserLogout); err != nil { - // 先写 Redis denylist 再改 MySQL,避免 Redis 不可用时出现“refresh/session 已吊销但旧 JWT 仍可用 7 天”的状态。 - s.audit(ctx, meta, 0, "logout", "", resultFailed, string(xerr.CodeOf(err))) - return false, err - } - } - } - - // refreshToken 可能为空;hashRefreshToken 会保持空值,支持仅用 session_id 登出。 - revoked, err := s.authRepository.RevokeSession(ctx, sessionID, hashRefreshToken(refreshToken), nowMs) + denyUntilMs := s.sessionDenyUntilMs(nowMs) + // repository 读取包含已轮换父代在内的 lineage,并在同事务写每个 sid 的 denylist 补偿 job。 + resolvedAppCode, sessionIDs, revoked, err := s.authRepository.RevokeSessionFamily(ctx, strings.TrimSpace(sessionID), hashRefreshToken(refreshToken), nowMs, denyUntilMs, meta.RequestID) if err != nil { s.audit(ctx, meta, 0, "logout", "", resultFailed, string(xerr.CodeOf(err))) return false, err } + if len(sessionIDs) > 0 { + if err := s.writeRevokedAccessFamilyUntil(ctx, resolvedAppCode, sessionIDs, revokeReasonUserLogout, denyUntilMs); err != nil { + s.audit(ctx, meta, 0, "logout", "", resultFailed, string(xerr.Unavailable)) + return false, err + } + } s.audit(ctx, meta, 0, "logout", "", resultSuccess, "") return revoked, nil @@ -261,7 +301,7 @@ func (s *Service) newSession(appCode string, userID int64, deviceID string) (aut nowMs := s.now().UnixMilli() // SessionID 使用独立前缀,便于日志和排障识别。 sessionID := idgen.New("sess") - return authdomain.Session{ + session := authdomain.Session{ AppCode: appcode.Normalize(appCode), SessionID: sessionID, UserID: userID, @@ -270,7 +310,107 @@ func (s *Service) newSession(appCode string, userID int64, deviceID string) (aut ExpiresAtMs: nowMs + s.cfg.RefreshTokenTTLSec*1000, CreatedAtMs: nowMs, UpdatedAtMs: nowMs, - }, refreshToken, nil + } + // 首个登录 session 自己就是 family root;后续轮换只继承该 ID 并递增 generation。 + session.TokenFamilyID = session.SessionID + return session, refreshToken, nil +} + +func (s *Service) newRotatedSession(parent authdomain.Session, deviceID string) (authdomain.Session, string, error) { + child, refreshToken, err := s.newSession(parent.AppCode, parent.UserID, deviceID) + if err != nil { + return authdomain.Session{}, "", err + } + familyID := strings.TrimSpace(parent.TokenFamilyID) + if familyID == "" { + // 兼容迁移前创建、尚未轮换的 active session:第一次新版轮换时把自身升级为 family root。 + familyID = parent.SessionID + } + child.TokenFamilyID = familyID + child.Generation = parent.Generation + 1 + child.ParentSessionID = parent.SessionID + return child, refreshToken, nil +} + +func (s *Service) refreshRotationGrace() time.Duration { + if s.cfg.RefreshRotationGraceSec <= 0 { + return defaultRefreshRotationGrace + } + return time.Duration(s.cfg.RefreshRotationGraceSec) * time.Second +} + +func normalizeRefreshRequestID(refreshRequestID string, refreshTokenHash string) (string, error) { + refreshRequestID = strings.TrimSpace(refreshRequestID) + if refreshRequestID == "" { + // 旧客户端每次 HTTP request_id 都会变化,不能拿它当幂等键;只从已 hash 的 predecessor token 派生稳定兼容键。 + if len(refreshTokenHash) < 48 { + return "", xerr.New(xerr.InvalidArgument, "refresh token hash is invalid") + } + refreshRequestID = "legacy_" + refreshTokenHash[:48] + } + if len(refreshRequestID) > 96 { + return "", xerr.New(xerr.InvalidArgument, "refresh_request_id is too long") + } + return refreshRequestID, nil +} + +func (s *Service) encryptRefreshOutcome(token authdomain.Token, parentSessionID string, childSessionID string, refreshRequestID string) ([]byte, error) { + plaintext, err := json.Marshal(token) + if err != nil { + return nil, err + } + gcm, err := s.refreshReplayCipher() + if err != nil { + return nil, err + } + nonce := make([]byte, gcm.NonceSize()) + if _, err := rand.Read(nonce); err != nil { + return nil, err + } + // nonce 前置于密文;AAD 绑定父子 lineage 和幂等键,数据库行被搬移后无法解密成可用 token。 + return gcm.Seal(nonce, nonce, plaintext, refreshOutcomeAAD(token.AppCode, parentSessionID, childSessionID, refreshRequestID)), nil +} + +func (s *Service) decryptRefreshOutcome(rotation authdomain.RefreshRotationResult) (authdomain.Token, error) { + gcm, err := s.refreshReplayCipher() + if err != nil { + return authdomain.Token{}, err + } + if len(rotation.TokenCiphertext) <= gcm.NonceSize() { + return authdomain.Token{}, fmt.Errorf("refresh outcome ciphertext is empty") + } + nonce := rotation.TokenCiphertext[:gcm.NonceSize()] + ciphertext := rotation.TokenCiphertext[gcm.NonceSize():] + plaintext, err := gcm.Open(nil, nonce, ciphertext, refreshOutcomeAAD(rotation.SourceSession.AppCode, rotation.SourceSession.SessionID, rotation.ActiveSession.SessionID, rotation.RefreshRequestID)) + if err != nil { + return authdomain.Token{}, err + } + var token authdomain.Token + if err := json.Unmarshal(plaintext, &token); err != nil { + return authdomain.Token{}, err + } + if token.SessionID != rotation.ActiveSession.SessionID || token.AppCode != rotation.SourceSession.AppCode || token.RefreshToken == "" || token.AccessToken == "" { + // 密文即使能通过认证,也必须和事务返回的 child session 一致,避免错误行关联泄露另一个会话结果。 + return authdomain.Token{}, fmt.Errorf("refresh outcome lineage mismatch") + } + return token, nil +} + +func (s *Service) refreshReplayCipher() (cipher.AEAD, error) { + if strings.TrimSpace(s.cfg.SigningSecret) == "" { + return nil, fmt.Errorf("signing secret is empty") + } + // 使用带用途前缀的 SHA-256 派生独立 AES-256 key,避免把 JWT HMAC key 直接作为分组密码 key。 + key := sha256.Sum256([]byte("hyapp-auth-refresh-replay:" + refreshReplayCipherVersion + "\x00" + s.cfg.SigningSecret)) + block, err := aes.NewCipher(key[:]) + if err != nil { + return nil, err + } + return cipher.NewGCM(block) +} + +func refreshOutcomeAAD(appCode string, parentSessionID string, childSessionID string, refreshRequestID string) []byte { + return []byte(strings.Join([]string{refreshReplayCipherVersion, appcode.Normalize(appCode), parentSessionID, childSessionID, refreshRequestID}, "\x00")) } func (s *Service) issueToken(user userdomain.User, sessionID string, deviceID string, refreshToken string, sessionExpiresAtMs int64) (authdomain.Token, error) { @@ -339,6 +479,10 @@ func (s *Service) issueToken(user userdomain.User, sessionID string, deviceID st } func (s *Service) writeRevokedAccessSession(ctx context.Context, appCode string, sessionID string, reason string) error { + return s.writeRevokedAccessSessionUntil(ctx, appCode, sessionID, reason, s.sessionDenyUntilMs(s.now().UnixMilli())) +} + +func (s *Service) writeRevokedAccessSessionUntil(ctx context.Context, appCode string, sessionID string, reason string, denyUntilMs int64) error { if strings.TrimSpace(sessionID) == "" { return nil } @@ -346,13 +490,39 @@ func (s *Service) writeRevokedAccessSession(ctx context.Context, appCode string, // refresh/logout 一旦成功,gateway 必须能立刻拒绝旧 access token;缺少 denylist 不能假装吊销成功。 return xerr.New(xerr.Unavailable, "session denylist is not configured") } - ttl := s.loginRiskPolicy.DenylistTTL + ttl := time.Until(time.UnixMilli(denyUntilMs)) + if s.now != nil { + ttl = time.UnixMilli(denyUntilMs).Sub(s.now()) + } if ttl <= 0 { - ttl = time.Duration(s.cfg.AccessTokenTTLSec+60) * time.Second + // deny_until 已过说明该 sid 的 access JWT 已全部自然失效,无需再写 Redis。 + return nil } return s.ipDecisionCache.SetRevokedSession(ctx, appcode.Normalize(appCode), sessionID, reason, ttl) } +func (s *Service) writeRevokedAccessFamilyUntil(ctx context.Context, appCode string, sessionIDs []string, reason string, denyUntilMs int64) error { + // replay 是罕见安全事件,可以逐 sid 补齐 denylist;不能只写当前 active child,否则 family 内尚未自然过期的旧 JWT 仍能通过 gateway。 + for _, sessionID := range sessionIDs { + if err := s.writeRevokedAccessSessionUntil(ctx, appCode, sessionID, reason, denyUntilMs); err != nil { + return xerr.New(xerr.Unavailable, "session family denylist is unavailable") + } + // family revoke 事务已经写入持久 job;即时 Redis 成功后尽量标 delivered,标记失败会由 worker 幂等重放。 + nowMs := s.now().UnixMilli() + _ = s.authRepository.MarkSessionDenylistJobDelivered(ctx, 0, appCode, sessionID, reason, denyUntilMs, nowMs, nowMs+sessionDenylistRehydrateInterval.Milliseconds()) + } + return nil +} + +func (s *Service) sessionDenyUntilMs(nowMs int64) int64 { + accessTTL := time.Duration(s.cfg.AccessTokenTTLSec) * time.Second + if accessTTL < sessionDenylistHistoricalAccessTTLFloor { + // 这个 floor 只能随历史最大签发 TTL 上调,不能因当前配置下降而下调。 + accessTTL = sessionDenylistHistoricalAccessTTLFloor + } + return nowMs + (accessTTL + sessionDenylistSafetyMargin).Milliseconds() +} + func tokenOnboardingStatus(user userdomain.User) string { // 旧测试数据或手工种子可能没有显式状态;token 按 profile_completed 推导安全默认值。 if user.OnboardingStatus != "" { diff --git a/services/user-service/internal/service/cp/service.go b/services/user-service/internal/service/cp/service.go index 3eb238c9..8d566306 100644 --- a/services/user-service/internal/service/cp/service.go +++ b/services/user-service/internal/service/cp/service.go @@ -16,6 +16,8 @@ const ( maxIntimacyLeaderboardPageSize = int32(100) defaultIntimacyLeaderboardRows = 10000 maxIntimacyLeaderboardRows = 10000 + defaultFormationGiftFeedLimit = int32(20) + maxFormationGiftFeedLimit = int32(100) ) // Repository 描述 CP 关系 service 需要的持久化能力,便于后续单元测试替换 MySQL 实现。 @@ -32,6 +34,12 @@ type Repository interface { ListWeeklyRankEntries(ctx context.Context, relationType string, startMS int64, endMS int64, limit int) ([]cpdomain.WeeklyRankEntry, error) } +// FormationGiftFeedRepository 单独描述成立礼物 feed 的只读查询,避免把展示 feed 混进累计亲密榜接口。 +// 该能力保持为独立扩展接口,使不关心 feed 的 CP service 替身不必实现无关读取。 +type FormationGiftFeedRepository interface { + ListFormationGiftFeed(ctx context.Context, limit int) ([]cpdomain.FormationGiftFeedItem, error) +} + // IntimacyLeaderboardStore 是 CP 亲密榜 Redis zset 读模型边界。 type IntimacyLeaderboardStore interface { ReplaceIntimacyLeaderboard(ctx context.Context, appCode string, entries []cpdomain.IntimacyLeaderboardEntry) error @@ -159,9 +167,31 @@ func (s *Service) ConsumeGiftEvent(ctx context.Context, event cpdomain.GiftEvent if event.GiftValue < 0 { event.GiftValue = 0 } + // coin_spent 是 wallet 结算出的礼物金币价值;缺失或非法的历史事件保留 0,绝不能用 gift_value 的热度口径兜底。 + if event.CoinSpent < 0 { + event.CoinSpent = 0 + } return s.repo.ConsumeGiftEvent(ctx, event, s.nowMs()) } +// ListFormationGiftFeed 返回已接受的 CP 成立礼物事件流;门槛由仓储固定,调用方只能控制有上限的条数。 +func (s *Service) ListFormationGiftFeed(ctx context.Context, limit int32) ([]cpdomain.FormationGiftFeedItem, error) { + if s == nil || s.repo == nil { + return nil, xerr.New(xerr.Unavailable, "cp repository is not configured") + } + feedRepo, ok := s.repo.(FormationGiftFeedRepository) + if !ok { + return nil, xerr.New(xerr.Unavailable, "cp formation gift feed repository is not configured") + } + if limit <= 0 { + limit = defaultFormationGiftFeedLimit + } + if limit > maxFormationGiftFeedLimit { + limit = maxFormationGiftFeedLimit + } + return feedRepo.ListFormationGiftFeed(ctx, int(limit)) +} + // ListWeeklyRankEntries 给 activity-service 的结算链路读取 CP 周榜快照;它不写 Redis,也不发奖。 func (s *Service) ListWeeklyRankEntries(ctx context.Context, relationType string, startMS int64, endMS int64, limit int32) ([]cpdomain.WeeklyRankEntry, int64, error) { if s == nil || s.repo == nil { diff --git a/services/user-service/internal/storage/mysql/auth/session_denylist_jobs.go b/services/user-service/internal/storage/mysql/auth/session_denylist_jobs.go new file mode 100644 index 00000000..3572b3ed --- /dev/null +++ b/services/user-service/internal/storage/mysql/auth/session_denylist_jobs.go @@ -0,0 +1,190 @@ +package auth + +import ( + "context" + "database/sql" + "strings" + + "hyapp/pkg/appcode" + authdomain "hyapp/services/user-service/internal/domain/auth" +) + +func enqueueSessionDenylistJobs(ctx context.Context, tx *sql.Tx, appCode string, sessionIDs []string, reason string, nowMs int64, denyUntilMs int64) error { + if denyUntilMs <= nowMs { + return sql.ErrNoRows + } + for _, sessionID := range sessionIDs { + // unique key 让 repeated replay/logout 复用同一事实。若新撤销把 deny_until 延长,必须重新 pending; + // 否则 DB commit 后进程崩溃会让旧 delivered 状态掩盖尚未写入 Redis 的新 TTL。 + if _, err := tx.ExecContext(ctx, ` + INSERT INTO auth_session_denylist_jobs + (app_code, session_id, reason, status, attempts, next_retry_at_ms, locked_by, locked_until_ms, last_error, deny_until_ms, created_at_ms, updated_at_ms) + VALUES (?, ?, ?, 'pending', 0, ?, '', 0, '', ?, ?, ?) + ON DUPLICATE KEY UPDATE + next_retry_at_ms = IF(VALUES(deny_until_ms) > deny_until_ms OR status <> 'delivered', VALUES(next_retry_at_ms), next_retry_at_ms), + locked_by = IF(VALUES(deny_until_ms) > deny_until_ms OR status <> 'delivered', '', locked_by), + locked_until_ms = IF(VALUES(deny_until_ms) > deny_until_ms OR status <> 'delivered', 0, locked_until_ms), + status = IF(VALUES(deny_until_ms) > deny_until_ms OR status <> 'delivered', 'pending', 'delivered'), + reason = IF(VALUES(deny_until_ms) >= deny_until_ms, VALUES(reason), reason), + deny_until_ms = GREATEST(deny_until_ms, VALUES(deny_until_ms)), + updated_at_ms = VALUES(updated_at_ms) + `, appcode.Normalize(appCode), sessionID, reason, nowMs, denyUntilMs, nowMs, nowMs); err != nil { + return err + } + } + return nil +} + +func (r *Repository) ClaimSessionDenylistJobs(ctx context.Context, workerID string, nowMs int64, lockUntilMs int64, limit int) ([]authdomain.SessionDenylistJob, error) { + if limit <= 0 { + limit = 100 + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return nil, err + } + defer tx.Rollback() + rows, err := tx.QueryContext(ctx, ` + SELECT job_id, app_code, session_id, reason, attempts, deny_until_ms, created_at_ms + FROM auth_session_denylist_jobs + WHERE deny_until_ms > ? AND ((status IN ('pending', 'retryable') AND next_retry_at_ms <= ?) + OR (status = 'processing' AND locked_until_ms <= ?) + ) + ORDER BY next_retry_at_ms, job_id + LIMIT ? + FOR UPDATE SKIP LOCKED + `, nowMs, nowMs, nowMs, limit) + if err != nil { + return nil, err + } + var jobs []authdomain.SessionDenylistJob + for rows.Next() { + var job authdomain.SessionDenylistJob + if err := rows.Scan(&job.JobID, &job.AppCode, &job.SessionID, &job.Reason, &job.Attempts, &job.DenyUntilMs, &job.CreatedAtMs); err != nil { + _ = rows.Close() + return nil, err + } + jobs = append(jobs, job) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + for _, job := range jobs { + if _, err := tx.ExecContext(ctx, ` + UPDATE auth_session_denylist_jobs + SET status = 'processing', attempts = attempts + 1, locked_by = ?, locked_until_ms = ?, updated_at_ms = ? + WHERE job_id = ? + `, strings.TrimSpace(workerID), lockUntilMs, nowMs, job.JobID); err != nil { + return nil, err + } + } + if err := tx.Commit(); err != nil { + return nil, err + } + return jobs, nil +} + +func (r *Repository) MarkSessionDenylistJobDelivered(ctx context.Context, jobID int64, appCode string, sessionID string, reason string, appliedDenyUntilMs int64, nowMs int64, nextRehydrateAtMs int64) error { + if jobID > 0 { + _, err := r.db.ExecContext(ctx, ` + UPDATE auth_session_denylist_jobs + SET status = 'delivered', next_retry_at_ms = ?, locked_by = '', locked_until_ms = 0, last_error = '', updated_at_ms = ? + WHERE job_id = ? AND deny_until_ms <= ? + `, nextRehydrateAtMs, nowMs, jobID, appliedDenyUntilMs) + return err + } + _, err := r.db.ExecContext(ctx, ` + UPDATE auth_session_denylist_jobs + SET status = 'delivered', next_retry_at_ms = ?, locked_by = '', locked_until_ms = 0, last_error = '', updated_at_ms = ? + WHERE app_code = ? AND session_id = ? AND deny_until_ms <= ? + `, nextRehydrateAtMs, nowMs, appcode.Normalize(appCode), sessionID, appliedDenyUntilMs) + return err +} + +func (r *Repository) MarkSessionDenylistJobRetryable(ctx context.Context, jobID int64, errorMessage string, nextRetryAtMs int64, nowMs int64) error { + if len(errorMessage) > 512 { + errorMessage = errorMessage[:512] + } + _, err := r.db.ExecContext(ctx, ` + UPDATE auth_session_denylist_jobs + SET status = 'retryable', next_retry_at_ms = ?, locked_by = '', locked_until_ms = 0, last_error = ?, updated_at_ms = ? + WHERE job_id = ? + `, nextRetryAtMs, errorMessage, nowMs, jobID) + return err +} + +func (r *Repository) MaxSessionDenylistJobID(ctx context.Context) (int64, error) { + var maxJobID int64 + err := r.db.QueryRowContext(ctx, `SELECT COALESCE(MAX(job_id), 0) FROM auth_session_denylist_jobs`).Scan(&maxJobID) + return maxJobID, err +} + +func (r *Repository) ListSessionDenylistJobsForHydration(ctx context.Context, nowMs int64, afterJobID int64, throughJobID int64, limit int) ([]authdomain.SessionDenylistJob, int64, error) { + if limit <= 0 { + limit = 1000 + } + // hydration 是只读 keyset snapshot:不看 status/lease、不 SKIP LOCKED,也不依赖旧 pod 的 worker 状态。 + rows, err := r.db.QueryContext(ctx, ` + SELECT job_id, app_code, session_id, reason, attempts, deny_until_ms, created_at_ms + FROM auth_session_denylist_jobs + WHERE deny_until_ms > ? AND job_id > ? AND job_id <= ? + ORDER BY job_id + LIMIT ? + `, nowMs, afterJobID, throughJobID, limit) + if err != nil { + return nil, afterJobID, err + } + defer rows.Close() + jobs := make([]authdomain.SessionDenylistJob, 0, limit) + for rows.Next() { + var job authdomain.SessionDenylistJob + if err := rows.Scan(&job.JobID, &job.AppCode, &job.SessionID, &job.Reason, &job.Attempts, &job.DenyUntilMs, &job.CreatedAtMs); err != nil { + return nil, afterJobID, err + } + jobs = append(jobs, job) + } + if err := rows.Err(); err != nil { + return nil, afterJobID, err + } + if len(jobs) == 0 { + return jobs, afterJobID, nil + } + return jobs, jobs[len(jobs)-1].JobID, nil +} + +func (r *Repository) DeleteExpiredSessionDenylistJobs(ctx context.Context, nowMs int64, limit int) (int, error) { + if limit <= 0 { + limit = 1000 + } + result, err := r.db.ExecContext(ctx, ` + DELETE FROM auth_session_denylist_jobs + WHERE deny_until_ms <= ? + ORDER BY deny_until_ms, job_id + LIMIT ? + `, nowMs, limit) + if err != nil { + return 0, err + } + affected, err := result.RowsAffected() + return int(affected), err +} + +func (r *Repository) DeleteExpiredRefreshOutcomes(ctx context.Context, nowMs int64, limit int) (int, error) { + if limit <= 0 { + limit = 1000 + } + result, err := r.db.ExecContext(ctx, ` + DELETE FROM auth_refresh_outcomes + WHERE expires_at_ms < ? + ORDER BY expires_at_ms + LIMIT ? + `, nowMs, limit) + if err != nil { + return 0, err + } + affected, err := result.RowsAffected() + return int(affected), err +} diff --git a/services/user-service/internal/storage/mysql/auth/sessions.go b/services/user-service/internal/storage/mysql/auth/sessions.go index 362cbfe5..252937df 100644 --- a/services/user-service/internal/storage/mysql/auth/sessions.go +++ b/services/user-service/internal/storage/mysql/auth/sessions.go @@ -2,19 +2,23 @@ package auth import ( "context" + "crypto/subtle" "database/sql" + "strings" "hyapp/pkg/appcode" "hyapp/pkg/xerr" authdomain "hyapp/services/user-service/internal/domain/auth" ) +const sessionProjection = `app_code, session_id, user_id, refresh_token_hash, token_family_id, generation, parent_session_id, rotated_to_session_id, rotation_at_ms, rotation_request_id, device_id, expires_at_ms, last_heartbeat_at_ms, last_heartbeat_request_id, revoked_at_ms, revoked_reason, revoked_request_id, revoked_by, created_at_ms, updated_at_ms` + func (r *Repository) CreateSession(ctx context.Context, session authdomain.Session) error { // refresh token 只保存 hash,原文不会写入数据库。 _, err := r.db.ExecContext(ctx, ` - INSERT INTO auth_sessions (app_code, session_id, user_id, refresh_token_hash, device_id, expires_at_ms, last_heartbeat_at_ms, last_heartbeat_request_id, revoked_at_ms, revoked_reason, revoked_request_id, revoked_by, created_at_ms, updated_at_ms) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, '', '', '', ?, ?) - `, appcode.Normalize(session.AppCode), session.SessionID, session.UserID, session.RefreshTokenHash, session.DeviceID, session.ExpiresAtMs, session.LastHeartbeatAtMs, session.LastHeartbeatRequestID, session.CreatedAtMs, session.UpdatedAtMs) + INSERT INTO auth_sessions (app_code, session_id, user_id, refresh_token_hash, token_family_id, generation, parent_session_id, rotated_to_session_id, rotation_at_ms, rotation_request_id, device_id, expires_at_ms, last_heartbeat_at_ms, last_heartbeat_request_id, revoked_at_ms, revoked_reason, revoked_request_id, revoked_by, created_at_ms, updated_at_ms) + VALUES (?, ?, ?, ?, ?, ?, ?, '', 0, '', ?, ?, ?, ?, NULL, '', '', '', ?, ?) + `, appcode.Normalize(session.AppCode), session.SessionID, session.UserID, session.RefreshTokenHash, normalizedFamilyID(session), session.Generation, session.ParentSessionID, session.DeviceID, session.ExpiresAtMs, session.LastHeartbeatAtMs, session.LastHeartbeatRequestID, session.CreatedAtMs, session.UpdatedAtMs) if err != nil { // session_id 或 refresh hash 冲突统一映射成 auth 领域冲突。 return mapAuthDuplicateError(err) @@ -23,6 +27,11 @@ func (r *Repository) CreateSession(ctx context.Context, session authdomain.Sessi return nil } +// FindSessionByRefreshHash 返回已轮换/吊销行在内的完整 session;调用方必须继续做状态判定。 +func (r *Repository) FindSessionByRefreshHash(ctx context.Context, refreshTokenHash string) (authdomain.Session, error) { + return r.findSessionByRefreshHash(ctx, refreshTokenHash) +} + // FindActiveSessionByRefreshHash 查找未过期且未吊销的 session。 func (r *Repository) FindActiveSessionByRefreshHash(ctx context.Context, refreshTokenHash string, nowMs int64) (authdomain.Session, error) { @@ -69,15 +78,13 @@ func (r *Repository) FindActiveSessionByID(ctx context.Context, sessionID string func (r *Repository) FindLatestActiveSessionByUser(ctx context.Context, userID int64, nowMs int64) (authdomain.Session, error) { // idx_auth_sessions_user_id(app_code, user_id) 先收敛到单用户,再在少量行上过滤排序即可。 - var session authdomain.Session - var revokedAt sql.Null[int64] - err := r.db.QueryRowContext(ctx, ` - SELECT app_code, session_id, user_id, refresh_token_hash, device_id, expires_at_ms, last_heartbeat_at_ms, last_heartbeat_request_id, revoked_at_ms, revoked_reason, revoked_request_id, revoked_by, created_at_ms, updated_at_ms + session, err := scanSession(r.db.QueryRowContext(ctx, ` + SELECT `+sessionProjection+` FROM auth_sessions WHERE app_code = ? AND user_id = ? AND revoked_at_ms IS NULL AND expires_at_ms > ? ORDER BY created_at_ms DESC, session_id DESC LIMIT 1 - `, appcode.FromContext(ctx), userID, nowMs).Scan(&session.AppCode, &session.SessionID, &session.UserID, &session.RefreshTokenHash, &session.DeviceID, &session.ExpiresAtMs, &session.LastHeartbeatAtMs, &session.LastHeartbeatRequestID, &revokedAt, &session.RevokedReason, &session.RevokedRequestID, &session.RevokedBy, &session.CreatedAtMs, &session.UpdatedAtMs) + `, appcode.FromContext(ctx), userID, nowMs)) if err == sql.ErrNoRows { // “无活跃会话”是后台要明确展示的业务事实,用 NotFound 与其他存储错误区分。 return authdomain.Session{}, xerr.New(xerr.NotFound, "active session not found") @@ -85,53 +92,230 @@ func (r *Repository) FindLatestActiveSessionByUser(ctx context.Context, userID i if err != nil { return authdomain.Session{}, err } - if revokedAt.Valid { - session.RevokedAtMs = revokedAt.V - } - return session, nil } -// ReplaceSession 原子吊销旧 session 并创建新 session。 +// RotateRefreshSession 在一个 MySQL 事务内串行化同一 refresh token 的首次轮换、grace 重试和 replay 撤销。 +func (r *Repository) RotateRefreshSession(ctx context.Context, command authdomain.RefreshRotationCommand) (authdomain.RefreshRotationResult, error) { + appCode := appcode.Normalize(command.AppCode) + if appCode == "" { + appCode = appcode.FromContext(ctx) + } + if command.RefreshTokenHash == "" || command.NowMs <= 0 || command.GracePeriodMs <= 0 || command.DenyUntilMs <= command.NowMs || strings.TrimSpace(command.RefreshRequestID) == "" { + return authdomain.RefreshRotationResult{}, xerr.New(xerr.InvalidArgument, "invalid refresh rotation command") + } -func (r *Repository) ReplaceSession(ctx context.Context, oldSessionID string, newSession authdomain.Session, revokedAtMs int64) error { - // refresh 轮换必须原子吊销旧 session 并插入新 session。 tx, err := r.db.BeginTx(ctx, nil) if err != nil { - return err + return authdomain.RefreshRotationResult{}, err } defer tx.Rollback() - var oldRevokedAt sql.Null[int64] - err = tx.QueryRowContext(ctx, ` - SELECT revoked_at_ms + // 唯一 refresh hash + FOR UPDATE 保证多实例并发只能有一个 winner;幂等密文和 lineage 与轮换同提交。 + source, err := scanSession(tx.QueryRowContext(ctx, ` + SELECT `+sessionProjection+` + FROM auth_sessions + WHERE app_code = ? AND refresh_token_hash = ? + FOR UPDATE + `, appCode, command.RefreshTokenHash)) + if err == sql.ErrNoRows { + return authdomain.RefreshRotationResult{}, xerr.New(xerr.SessionRevoked, "session revoked") + } + if err != nil { + return authdomain.RefreshRotationResult{}, err + } + + if source.RevokedAtMs == 0 && source.ExpiresAtMs <= command.NowMs { + // 自然过期的当前代不是 token reuse,保持 SESSION_EXPIRED 让客户端重新登录。 + return authdomain.RefreshRotationResult{}, xerr.New(xerr.SessionExpired, "session expired") + } + if source.RevokedAtMs > 0 && source.RevokedReason != "REFRESH_ROTATED" && source.RevokedReason != "REFRESH_TOKEN_REUSE" { + // logout、风控和后台封禁都不允许进入 grace,也不能覆盖其原始撤销原因。 + return authdomain.RefreshRotationResult{}, xerr.New(xerr.SessionRevoked, "session revoked") + } + if source.RevokedReason == "REFRESH_ROTATED" && (strings.TrimSpace(source.RotatedToSessionID) == "" || source.RotationAtMs <= 0) { + // 旧 binary 没有写 parent→child lineage/outcome,时间或设备启发式都可能把并发显式登录误认成 child, + // 造成古老 token 永久踢掉未来新会话。无法证明 lineage 时只拒绝旧 token,不扩大任何撤销范围。 + return authdomain.RefreshRotationResult{}, xerr.New(xerr.SessionRevoked, "session revoked") + } + if subtle.ConstantTimeCompare([]byte(source.DeviceID), []byte(strings.TrimSpace(command.DeviceID))) != 1 { + // token 原文在另一设备出现就是重放;family 查询仍同时限定 app/user/device,不能误伤其他设备登录态。 + result, reuseErr := r.revokeRefreshFamilyForReuse(ctx, tx, source, command) + if reuseErr != nil { + return authdomain.RefreshRotationResult{}, reuseErr + } + if err := tx.Commit(); err != nil { + return authdomain.RefreshRotationResult{}, err + } + return result, nil + } + + if source.RevokedAtMs == 0 { + result, rotateErr := r.createRefreshRotation(ctx, tx, source, command) + if rotateErr != nil { + return authdomain.RefreshRotationResult{}, rotateErr + } + if err := tx.Commit(); err != nil { + return authdomain.RefreshRotationResult{}, err + } + return result, nil + } + + if source.RevokedReason == "REFRESH_TOKEN_REUSE" { + // 上次 denylist 写失败时,后续请求仍返回整族 sid,让 service 可以继续补偿 gateway denylist。 + result, reuseErr := r.revokeRefreshFamilyForReuse(ctx, tx, source, command) + if reuseErr != nil { + return authdomain.RefreshRotationResult{}, reuseErr + } + if err := tx.Commit(); err != nil { + return authdomain.RefreshRotationResult{}, err + } + return result, nil + } + + child, childErr := scanSession(tx.QueryRowContext(ctx, ` + SELECT `+sessionProjection+` FROM auth_sessions WHERE app_code = ? AND session_id = ? FOR UPDATE - `, appcode.FromContext(ctx), oldSessionID).Scan(&oldRevokedAt) - if err == sql.ErrNoRows || oldRevokedAt.Valid { - // 旧 session 不存在或已经吊销时,不能再次轮换。 - return xerr.New(xerr.SessionRevoked, "session revoked") + `, appCode, source.RotatedToSessionID)) + if childErr != nil && childErr != sql.ErrNoRows { + return authdomain.RefreshRotationResult{}, childErr } - if err != nil { - return err + var outcomeRequestID string + var outcomeChildID string + var outcomeCiphertext []byte + var outcomeCreatedAtMs int64 + var outcomeExpiresAtMs int64 + outcomeErr := tx.QueryRowContext(ctx, ` + SELECT child_session_id, refresh_request_id, token_ciphertext, created_at_ms, expires_at_ms + FROM auth_refresh_outcomes + WHERE app_code = ? AND parent_session_id = ? + FOR UPDATE + `, appCode, source.SessionID).Scan(&outcomeChildID, &outcomeRequestID, &outcomeCiphertext, &outcomeCreatedAtMs, &outcomeExpiresAtMs) + if outcomeErr != nil && outcomeErr != sql.ErrNoRows { + return authdomain.RefreshRotationResult{}, outcomeErr } - _, err = tx.ExecContext(ctx, ` + graceValid := childErr == nil && outcomeErr == nil && + child.RevokedAtMs == 0 && child.ExpiresAtMs > command.NowMs && + child.ParentSessionID == source.SessionID && child.TokenFamilyID == normalizedFamilyID(source) && child.Generation == source.Generation+1 && + outcomeChildID == child.SessionID && outcomeCreatedAtMs == source.RotationAtMs && + command.NowMs <= outcomeExpiresAtMs + if graceValid { + // 窗口由首次 winner 与 token pair 同事务固化;滚动配置变更时 retry 实例必须信任该 persisted deadline, + // 不能再用自身当前 grace 配置缩短或扩张,否则 30s/10s 混部会把合法重试误判为 reuse。 + if err := tx.Commit(); err != nil { + return authdomain.RefreshRotationResult{}, err + } + return authdomain.RefreshRotationResult{ + Status: authdomain.RefreshRotationGraceHit, + SourceSession: source, + ActiveSession: child, + RefreshRequestID: outcomeRequestID, + TokenCiphertext: append([]byte(nil), outcomeCiphertext...), + }, nil + } + + // child 已再次轮换(第二上一代)、outcome 过窗或 lineage 不完整都属于不可安全恢复的 reuse。 + result, reuseErr := r.revokeRefreshFamilyForReuse(ctx, tx, source, command) + if reuseErr != nil { + return authdomain.RefreshRotationResult{}, reuseErr + } + if err := tx.Commit(); err != nil { + return authdomain.RefreshRotationResult{}, err + } + return result, nil +} + +func (r *Repository) createRefreshRotation(ctx context.Context, tx *sql.Tx, source authdomain.Session, command authdomain.RefreshRotationCommand) (authdomain.RefreshRotationResult, error) { + child := command.NewSession + familyID := normalizedFamilyID(source) + if child.SessionID == "" || child.RefreshTokenHash == "" || len(command.TokenCiphertext) == 0 || len(command.TokenCiphertext) > 4096 || + child.AppCode != source.AppCode || child.UserID != source.UserID || child.DeviceID != source.DeviceID || + child.TokenFamilyID != familyID || child.ParentSessionID != source.SessionID || child.Generation != source.Generation+1 || + command.OutcomeExpiresAtMs != command.NowMs+command.GracePeriodMs { + return authdomain.RefreshRotationResult{}, xerr.New(xerr.InvalidArgument, "invalid refresh rotation lineage") + } + if source.ParentSessionID != "" { + // source 成为新 parent 后,它的 parent 已是第二上一代;事务内删除旧密文,确保每个 family 最多保留 immediate predecessor 的一份结果。 + if _, err := tx.ExecContext(ctx, ` + DELETE FROM auth_refresh_outcomes + WHERE app_code = ? AND parent_session_id = ? + `, source.AppCode, source.ParentSessionID); err != nil { + return authdomain.RefreshRotationResult{}, err + } + } + + _, 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 session_id = ? - `, revokedAtMs, "REFRESH_ROTATED", "", "refresh_token", revokedAtMs, appcode.FromContext(ctx), oldSessionID) + SET token_family_id = ?, rotated_to_session_id = ?, rotation_at_ms = ?, rotation_request_id = ?, + revoked_at_ms = ?, revoked_reason = 'REFRESH_ROTATED', revoked_request_id = ?, revoked_by = 'refresh_token', updated_at_ms = ? + WHERE app_code = ? AND session_id = ? AND revoked_at_ms IS NULL + `, familyID, child.SessionID, command.NowMs, command.RefreshRequestID, command.NowMs, command.RefreshRequestID, command.NowMs, source.AppCode, source.SessionID) if err != nil { - return err + return authdomain.RefreshRotationResult{}, err } - - if err := insertSession(ctx, tx, newSession); err != nil { - // 插入新 session 失败会回滚旧 session 吊销。 - return err + if err := insertSession(ctx, tx, child); err != nil { + return authdomain.RefreshRotationResult{}, err } + _, err = tx.ExecContext(ctx, ` + INSERT INTO auth_refresh_outcomes (app_code, parent_session_id, child_session_id, refresh_request_id, token_ciphertext, created_at_ms, expires_at_ms) + VALUES (?, ?, ?, ?, ?, ?, ?) + `, source.AppCode, source.SessionID, child.SessionID, command.RefreshRequestID, command.TokenCiphertext, command.NowMs, command.OutcomeExpiresAtMs) + if err != nil { + return authdomain.RefreshRotationResult{}, mapAuthDuplicateError(err) + } + // 正常 rotation 的旧 sid 也有尚未过期的 access JWT;与 child/outcome 同事务写 durable job, + // 覆盖 Redis 写成功后进程崩溃、Redis 重启等旧 JWT 重新放行风险。 + if err := enqueueSessionDenylistJobs(ctx, tx, source.AppCode, []string{source.SessionID}, "REFRESH_ROTATED", command.NowMs, command.DenyUntilMs); err != nil { + return authdomain.RefreshRotationResult{}, err + } + source.TokenFamilyID = familyID + source.RotatedToSessionID = child.SessionID + source.RotationAtMs = command.NowMs + source.RotationRequestID = command.RefreshRequestID + source.RevokedAtMs = command.NowMs + source.RevokedReason = "REFRESH_ROTATED" + return authdomain.RefreshRotationResult{ + Status: authdomain.RefreshRotationCreated, + SourceSession: source, + ActiveSession: child, + RefreshRequestID: command.RefreshRequestID, + TokenCiphertext: append([]byte(nil), command.TokenCiphertext...), + }, nil +} - return tx.Commit() +func (r *Repository) revokeRefreshFamilyForReuse(ctx context.Context, tx *sql.Tx, source authdomain.Session, command authdomain.RefreshRotationCommand) (authdomain.RefreshRotationResult, error) { + sessionIDs, err := lockProvenSessionFamily(ctx, tx, source) + if err != nil { + return authdomain.RefreshRotationResult{}, err + } + if len(sessionIDs) == 0 { + // source 已由 refresh hash 锁定,正常 schema 下至少包含自身;空结果视为存储不一致,不能静默成功。 + return authdomain.RefreshRotationResult{}, xerr.New(xerr.Unavailable, "refresh token family is unavailable") + } + result, err := revokeProvenSessionFamily(ctx, tx, source, command.NowMs, "REFRESH_TOKEN_REUSE", command.RefreshRequestID, "refresh_replay") + if err != nil { + return authdomain.RefreshRotationResult{}, err + } + affected, err := result.RowsAffected() + if err != nil { + return authdomain.RefreshRotationResult{}, err + } + // family 已撤销后任何历史 token pair 都不能再被恢复;与撤销同事务清掉全部相关密文。 + if err := deleteProvenSessionFamilyOutcomes(ctx, tx, source); err != nil { + return authdomain.RefreshRotationResult{}, err + } + if err := enqueueSessionDenylistJobs(ctx, tx, source.AppCode, sessionIDs, "REFRESH_TOKEN_REUSE", command.NowMs, command.DenyUntilMs); err != nil { + return authdomain.RefreshRotationResult{}, err + } + return authdomain.RefreshRotationResult{ + Status: authdomain.RefreshRotationReuseDetected, + SourceSession: source, + FamilySessionIDs: sessionIDs, + FamilyNewlyRevoked: affected > 0, + }, nil } // RevokeSession 按 session_id 或 refresh token hash 吊销 session。 @@ -149,6 +333,130 @@ func (r *Repository) RevokeSession(ctx context.Context, sessionID string, refres return r.revokeSessionByID(ctx, sessionID, revokedAtMs, "USER_LOGOUT", "", "user_logout") } +// RevokeSessionFamily 让显式 logout 与并发 refresh 收敛到同一个 family;不同设备拥有不同 family,不会被连带退出。 +func (r *Repository) RevokeSessionFamily(ctx context.Context, sessionID string, refreshTokenHash string, revokedAtMs int64, denyUntilMs int64, requestID string) (string, []string, bool, error) { + if revokedAtMs <= 0 || denyUntilMs <= revokedAtMs { + return "", nil, false, xerr.New(xerr.InvalidArgument, "invalid session family denylist deadline") + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return "", nil, false, err + } + defer tx.Rollback() + + var source authdomain.Session + if strings.TrimSpace(sessionID) != "" { + source, err = scanSession(tx.QueryRowContext(ctx, ` + SELECT `+sessionProjection+` FROM auth_sessions WHERE app_code = ? AND session_id = ? FOR UPDATE + `, appcode.FromContext(ctx), strings.TrimSpace(sessionID))) + } else { + source, err = scanSession(tx.QueryRowContext(ctx, ` + SELECT `+sessionProjection+` FROM auth_sessions WHERE app_code = ? AND refresh_token_hash = ? FOR UPDATE + `, appcode.FromContext(ctx), refreshTokenHash)) + } + if err == sql.ErrNoRows { + return "", nil, false, tx.Commit() + } + if err != nil { + return "", nil, false, err + } + + sessionIDs, err := lockProvenSessionFamily(ctx, tx, source) + if err != nil { + return "", nil, false, err + } + result, err := revokeProvenSessionFamily(ctx, tx, source, revokedAtMs, "USER_LOGOUT", requestID, "user_logout") + if err != nil { + return "", nil, false, err + } + affected, err := result.RowsAffected() + if err != nil { + return "", nil, false, err + } + if err := deleteProvenSessionFamilyOutcomes(ctx, tx, source); err != nil { + return "", nil, false, err + } + if err := enqueueSessionDenylistJobs(ctx, tx, source.AppCode, sessionIDs, "USER_LOGOUT", revokedAtMs, denyUntilMs); err != nil { + return "", nil, false, err + } + if err := tx.Commit(); err != nil { + return "", nil, false, err + } + return source.AppCode, sessionIDs, affected > 0, nil +} + +func lockProvenSessionFamily(ctx context.Context, tx *sql.Tx, source authdomain.Session) ([]string, error) { + familyID := strings.TrimSpace(source.TokenFamilyID) + if familyID == "" { + // 迁移前 session 没有可证明 lineage;source 已由调用方 FOR UPDATE 锁定,只处理自身, + // 绝不能按 user/device/time 猜测 successor,否则古老 token 可撤销未来显式登录。 + return []string{source.SessionID}, nil + } + // 禁止写成 token_family_id OR session_id:大账号会让优化器退回 user_id 索引并扫描/锁等待数万行。 + // 启动已强校验 family 索引,因此显式 FORCE INDEX,避免统计信息过旧时又选到高基数 user_id 索引; + // user/device 仅做数据污染防线。 + rows, err := tx.QueryContext(ctx, ` + SELECT session_id + FROM auth_sessions FORCE INDEX (idx_auth_sessions_token_family) + WHERE app_code = ? AND token_family_id = ? AND user_id = ? AND device_id = ? + ORDER BY generation, created_at_ms, session_id + FOR UPDATE + `, source.AppCode, familyID, source.UserID, source.DeviceID) + if err != nil { + return nil, err + } + defer rows.Close() + var sessionIDs []string + for rows.Next() { + var sessionID string + if err := rows.Scan(&sessionID); err != nil { + return nil, err + } + sessionIDs = append(sessionIDs, sessionID) + } + if err := rows.Err(); err != nil { + return nil, err + } + return sessionIDs, nil +} + +func revokeProvenSessionFamily(ctx context.Context, tx *sql.Tx, source authdomain.Session, revokedAtMs int64, reason string, requestID string, revokedBy string) (sql.Result, error) { + familyID := strings.TrimSpace(source.TokenFamilyID) + if familyID == "" { + // legacy 无 lineage 时仅更新已锁定 source;session_id 主键路径为单行更新。 + return tx.ExecContext(ctx, ` + UPDATE auth_sessions + SET revoked_at_ms = ?, revoked_reason = ?, revoked_request_id = ?, revoked_by = ?, updated_at_ms = ? + WHERE app_code = ? AND session_id = ? AND revoked_at_ms IS NULL + `, revokedAtMs, reason, requestID, revokedBy, revokedAtMs, source.AppCode, source.SessionID) + } + return tx.ExecContext(ctx, ` + UPDATE auth_sessions FORCE INDEX (idx_auth_sessions_token_family) + SET revoked_at_ms = ?, revoked_reason = ?, revoked_request_id = ?, revoked_by = ?, updated_at_ms = ? + WHERE app_code = ? AND token_family_id = ? AND user_id = ? AND device_id = ? AND revoked_at_ms IS NULL + `, revokedAtMs, reason, requestID, revokedBy, revokedAtMs, source.AppCode, familyID, source.UserID, source.DeviceID) +} + +func deleteProvenSessionFamilyOutcomes(ctx context.Context, tx *sql.Tx, source authdomain.Session) error { + familyID := strings.TrimSpace(source.TokenFamilyID) + if familyID == "" { + // 无 lineage 时最多删除 source 自己作为 predecessor 的结果,不通过任何启发式扩大范围。 + _, err := tx.ExecContext(ctx, ` + DELETE FROM auth_refresh_outcomes + WHERE app_code = ? AND parent_session_id = ? + `, source.AppCode, source.SessionID) + return err + } + _, err := tx.ExecContext(ctx, ` + DELETE outcome + FROM auth_sessions session FORCE INDEX (idx_auth_sessions_token_family) + STRAIGHT_JOIN auth_refresh_outcomes outcome + ON session.app_code = outcome.app_code AND session.session_id = outcome.parent_session_id + WHERE session.app_code = ? AND session.token_family_id = ? AND session.user_id = ? AND session.device_id = ? + `, source.AppCode, familyID, source.UserID, source.DeviceID) + return err +} + func (r *Repository) RevokeSessionWithReason(ctx context.Context, sessionID string, revokedAtMs int64, reason string, requestID string, revokedBy string) (bool, error) { return r.revokeSessionByID(ctx, sessionID, revokedAtMs, reason, requestID, revokedBy) } @@ -274,13 +582,11 @@ func (r *Repository) revokeSessionByID(ctx context.Context, sessionID string, re func (r *Repository) findSessionByRefreshHash(ctx context.Context, refreshTokenHash string) (authdomain.Session, error) { // refresh token hash 是唯一索引,最多命中一条 session。 - var session authdomain.Session - var revokedAt sql.Null[int64] - err := r.db.QueryRowContext(ctx, ` - SELECT app_code, session_id, user_id, refresh_token_hash, device_id, expires_at_ms, last_heartbeat_at_ms, last_heartbeat_request_id, revoked_at_ms, revoked_reason, revoked_request_id, revoked_by, created_at_ms, updated_at_ms + session, err := scanSession(r.db.QueryRowContext(ctx, ` + SELECT `+sessionProjection+` FROM auth_sessions WHERE app_code = ? AND refresh_token_hash = ? - `, appcode.FromContext(ctx), refreshTokenHash).Scan(&session.AppCode, &session.SessionID, &session.UserID, &session.RefreshTokenHash, &session.DeviceID, &session.ExpiresAtMs, &session.LastHeartbeatAtMs, &session.LastHeartbeatRequestID, &revokedAt, &session.RevokedReason, &session.RevokedRequestID, &session.RevokedBy, &session.CreatedAtMs, &session.UpdatedAtMs) + `, appcode.FromContext(ctx), refreshTokenHash)) if err == sql.ErrNoRows { // 找不到 hash 按 revoked 返回,避免暴露 token 是否存在。 return authdomain.Session{}, xerr.New(xerr.SessionRevoked, "session revoked") @@ -288,23 +594,16 @@ func (r *Repository) findSessionByRefreshHash(ctx context.Context, refreshTokenH if err != nil { return authdomain.Session{}, err } - if revokedAt.Valid { - // sql.Null[int64] 转换成领域零值语义。 - session.RevokedAtMs = revokedAt.V - } - return session, nil } func (r *Repository) findSessionByID(ctx context.Context, sessionID string) (authdomain.Session, error) { // session_id 来自已校验 access token 的 sid claim,仍必须回查服务端 session 状态。 - var session authdomain.Session - var revokedAt sql.Null[int64] - err := r.db.QueryRowContext(ctx, ` - SELECT app_code, session_id, user_id, refresh_token_hash, device_id, expires_at_ms, last_heartbeat_at_ms, last_heartbeat_request_id, revoked_at_ms, revoked_reason, revoked_request_id, revoked_by, created_at_ms, updated_at_ms + session, err := scanSession(r.db.QueryRowContext(ctx, ` + SELECT `+sessionProjection+` FROM auth_sessions WHERE app_code = ? AND session_id = ? - `, appcode.FromContext(ctx), sessionID).Scan(&session.AppCode, &session.SessionID, &session.UserID, &session.RefreshTokenHash, &session.DeviceID, &session.ExpiresAtMs, &session.LastHeartbeatAtMs, &session.LastHeartbeatRequestID, &revokedAt, &session.RevokedReason, &session.RevokedRequestID, &session.RevokedBy, &session.CreatedAtMs, &session.UpdatedAtMs) + `, appcode.FromContext(ctx), sessionID)) if err == sql.ErrNoRows { // 不暴露 session_id 是否存在,统一按 revoked 处理。 return authdomain.Session{}, xerr.New(xerr.SessionRevoked, "session revoked") @@ -312,22 +611,63 @@ func (r *Repository) findSessionByID(ctx context.Context, sessionID string) (aut if err != nil { return authdomain.Session{}, err } - if revokedAt.Valid { - session.RevokedAtMs = revokedAt.V - } - return session, nil } func insertSession(ctx context.Context, tx *sql.Tx, session authdomain.Session) error { // insertSession 只在已有事务中使用,保证与 session 替换或三方注册同提交。 _, err := tx.ExecContext(ctx, ` - INSERT INTO auth_sessions (app_code, session_id, user_id, refresh_token_hash, device_id, expires_at_ms, last_heartbeat_at_ms, last_heartbeat_request_id, revoked_at_ms, revoked_reason, revoked_request_id, revoked_by, created_at_ms, updated_at_ms) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, '', '', '', ?, ?) - `, appcode.Normalize(session.AppCode), session.SessionID, session.UserID, session.RefreshTokenHash, session.DeviceID, session.ExpiresAtMs, session.LastHeartbeatAtMs, session.LastHeartbeatRequestID, session.CreatedAtMs, session.UpdatedAtMs) + INSERT INTO auth_sessions (app_code, session_id, user_id, refresh_token_hash, token_family_id, generation, parent_session_id, rotated_to_session_id, rotation_at_ms, rotation_request_id, device_id, expires_at_ms, last_heartbeat_at_ms, last_heartbeat_request_id, revoked_at_ms, revoked_reason, revoked_request_id, revoked_by, created_at_ms, updated_at_ms) + VALUES (?, ?, ?, ?, ?, ?, ?, '', 0, '', ?, ?, ?, ?, NULL, '', '', '', ?, ?) + `, appcode.Normalize(session.AppCode), session.SessionID, session.UserID, session.RefreshTokenHash, normalizedFamilyID(session), session.Generation, session.ParentSessionID, session.DeviceID, session.ExpiresAtMs, session.LastHeartbeatAtMs, session.LastHeartbeatRequestID, session.CreatedAtMs, session.UpdatedAtMs) if err != nil { return mapAuthDuplicateError(err) } return nil } + +type sessionScanner interface { + Scan(dest ...any) error +} + +func scanSession(scanner sessionScanner) (authdomain.Session, error) { + var session authdomain.Session + var revokedAt sql.Null[int64] + err := scanner.Scan( + &session.AppCode, + &session.SessionID, + &session.UserID, + &session.RefreshTokenHash, + &session.TokenFamilyID, + &session.Generation, + &session.ParentSessionID, + &session.RotatedToSessionID, + &session.RotationAtMs, + &session.RotationRequestID, + &session.DeviceID, + &session.ExpiresAtMs, + &session.LastHeartbeatAtMs, + &session.LastHeartbeatRequestID, + &revokedAt, + &session.RevokedReason, + &session.RevokedRequestID, + &session.RevokedBy, + &session.CreatedAtMs, + &session.UpdatedAtMs, + ) + if err != nil { + return authdomain.Session{}, err + } + if revokedAt.Valid { + session.RevokedAtMs = revokedAt.V + } + return session, nil +} + +func normalizedFamilyID(session authdomain.Session) string { + if familyID := strings.TrimSpace(session.TokenFamilyID); familyID != "" { + return familyID + } + return session.SessionID +} diff --git a/services/user-service/internal/storage/mysql/cp/repository.go b/services/user-service/internal/storage/mysql/cp/repository.go index b0f34508..5bc02179 100644 --- a/services/user-service/internal/storage/mysql/cp/repository.go +++ b/services/user-service/internal/storage/mysql/cp/repository.go @@ -15,6 +15,8 @@ import ( cpdomain "hyapp/services/user-service/internal/domain/cp" ) +const formationGiftCoinThreshold = int64(5000) + // Repository 是 CP 关系在 user-service MySQL 上的 owner 存储。 type Repository struct { db *sql.DB @@ -319,6 +321,72 @@ func (r *Repository) ListActiveIntimacyLeaderboardEntries(ctx context.Context, l return entries, rows.Err() } +// ListFormationGiftFeed 读取“组 CP 时礼物金币价值严格超过 5000”的已接受成立事件,和累计亲密榜保持完全独立。 +func (r *Repository) ListFormationGiftFeed(ctx context.Context, limit int) ([]cpdomain.FormationGiftFeedItem, error) { + if r == nil || r.db == nil { + return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + if limit <= 0 { + limit = 20 + } + if limit > 100 { + limit = 100 + } + appCode := appcode.FromContext(ctx) + // accepted 申请从 formation_feed_eligible=1 的等值索引范围按决定时间倒序扫描;历史行资格默认 0, + // 无命中时不会退化为扫描全部 accepted CP,查询也不做 COUNT 或 OFFSET。解除关系不会抹掉已发生的成立事件。 + rows, err := r.db.QueryContext(ctx, ` + SELECT + source.application_id, source.gift_coin_value, + requester.user_id, COALESCE(requester.current_display_user_id, ''), COALESCE(requester.username, ''), COALESCE(requester.avatar, ''), + target.user_id, COALESCE(target.current_display_user_id, ''), COALESCE(target.username, ''), COALESCE(target.avatar, ''), + source.decided_at_ms + FROM user_cp_applications source + JOIN users requester + ON requester.app_code = source.app_code AND requester.user_id = source.requester_user_id + JOIN users target + ON target.app_code = source.app_code AND target.user_id = source.target_user_id + WHERE source.app_code = ? + AND source.status = ? + AND source.relation_type = ? + AND source.formation_feed_eligible = 1 + AND source.gift_coin_value > ? + ORDER BY source.decided_at_ms DESC, source.application_id DESC + LIMIT ?`, + appCode, + cpdomain.ApplicationStatusAccepted, + cpdomain.RelationTypeCP, + formationGiftCoinThreshold, + limit, + ) + if err != nil { + return nil, err + } + defer rows.Close() + + items := make([]cpdomain.FormationGiftFeedItem, 0, limit) + for rows.Next() { + var item cpdomain.FormationGiftFeedItem + if err := rows.Scan( + &item.FormationID, + &item.GiftCoinValue, + &item.Requester.UserID, + &item.Requester.DisplayUserID, + &item.Requester.Username, + &item.Requester.Avatar, + &item.Target.UserID, + &item.Target.DisplayUserID, + &item.Target.Username, + &item.Target.Avatar, + &item.FormedAtMS, + ); err != nil { + return nil, err + } + items = append(items, item) + } + return items, rows.Err() +} + // ListWeeklyRankEntries 按消费事实聚合一个 UTC 周期内的 CP 关系新增亲密值。 // score 只等于窗口内 relationship_intimacy_added gift_value 之和;关系表 intimacy_value 只服务普通亲密榜和等级累计态,不参与活动周榜排名。 func (r *Repository) ListWeeklyRankEntries(ctx context.Context, relationType string, startMS int64, endMS int64, limit int) ([]cpdomain.WeeklyRankEntry, error) { @@ -698,7 +766,7 @@ func applicationSelectSQL(suffix string) string { a.application_id, a.relation_type, a.status, a.room_id, a.room_region_id, a.gift_id, a.gift_name, a.gift_icon_url, a.gift_animation_url, - a.gift_count, a.gift_value, a.billing_receipt_id, + a.gift_count, a.gift_value, a.gift_coin_value, a.billing_receipt_id, a.source_room_event_id, a.source_command_id, a.created_at_ms, a.updated_at_ms, a.expires_at_ms, a.decided_at_ms, requester.user_id, COALESCE(requester.current_display_user_id, ''), COALESCE(requester.username, ''), COALESCE(requester.avatar, ''), @@ -727,7 +795,7 @@ func scanApplication(scanner interface{ Scan(dest ...any) error }) (cpdomain.App &app.ApplicationID, &app.RelationType, &app.Status, &app.RoomID, &app.RoomRegionID, &app.Gift.GiftID, &app.Gift.GiftName, &app.Gift.GiftIconURL, &app.Gift.GiftAnimationURL, - &app.Gift.GiftCount, &app.Gift.GiftValue, &app.Gift.BillingReceiptID, + &app.Gift.GiftCount, &app.Gift.GiftValue, &app.Gift.CoinSpent, &app.Gift.BillingReceiptID, &app.SourceEventID, &app.SourceCommandID, &app.CreatedAtMS, &app.UpdatedAtMS, &app.ExpiresAtMS, &app.DecidedAtMS, &app.Requester.UserID, &app.Requester.DisplayUserID, &app.Requester.Username, &app.Requester.Avatar, @@ -1145,11 +1213,11 @@ func upsertApplicationFromGiftTx(ctx context.Context, tx *sql.Tx, appCode string if _, err := tx.ExecContext(ctx, ` UPDATE user_cp_applications SET room_id = ?, room_region_id = ?, gift_id = ?, gift_name = ?, gift_icon_url = ?, - gift_animation_url = ?, gift_count = ?, gift_value = ?, billing_receipt_id = ?, + gift_animation_url = ?, gift_count = ?, gift_value = ?, gift_coin_value = ?, formation_feed_eligible = ?, billing_receipt_id = ?, source_room_event_id = ?, source_command_id = ?, expires_at_ms = ?, updated_at_ms = ? WHERE app_code = ? AND application_id = ?`, event.RoomID, event.VisibleRegionID, event.GiftID, event.GiftName, event.GiftIconURL, - event.GiftAnimationURL, event.GiftCount, event.GiftValue, event.BillingReceiptID, + event.GiftAnimationURL, event.GiftCount, event.GiftValue, event.CoinSpent, formationGiftFeedEligibility(event.CoinSpent), event.BillingReceiptID, event.EventID, event.CommandID, expiresAtMS, nowMs, appCode, application.ApplicationID, ); err != nil { return cpdomain.Application{}, err @@ -1169,12 +1237,12 @@ func upsertApplicationFromGiftTx(ctx context.Context, tx *sql.Tx, appCode string INSERT INTO user_cp_applications ( app_code, application_id, requester_user_id, target_user_id, relation_type, status, room_id, room_region_id, gift_id, gift_name, gift_icon_url, gift_animation_url, - gift_count, gift_value, billing_receipt_id, source_room_event_id, source_command_id, + gift_count, gift_value, gift_coin_value, formation_feed_eligible, billing_receipt_id, source_room_event_id, source_command_id, created_at_ms, updated_at_ms, expires_at_ms, decided_at_ms - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)`, + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)`, appCode, applicationID, event.SenderUserID, event.TargetUserID, relationType, cpdomain.ApplicationStatusPending, event.RoomID, event.VisibleRegionID, event.GiftID, event.GiftName, event.GiftIconURL, event.GiftAnimationURL, - event.GiftCount, event.GiftValue, event.BillingReceiptID, event.EventID, event.CommandID, + event.GiftCount, event.GiftValue, event.CoinSpent, formationGiftFeedEligibility(event.CoinSpent), event.BillingReceiptID, event.EventID, event.CommandID, nowMs, nowMs, expiresAtMS, ); err != nil { return cpdomain.Application{}, err @@ -1288,10 +1356,19 @@ func giftSnapshotFromEvent(event cpdomain.GiftEvent) cpdomain.GiftSnapshot { GiftAnimationURL: strings.TrimSpace(event.GiftAnimationURL), GiftCount: event.GiftCount, GiftValue: event.GiftValue, + CoinSpent: event.CoinSpent, BillingReceiptID: strings.TrimSpace(event.BillingReceiptID), } } +func formationGiftFeedEligibility(coinSpent int64) int8 { + // 资格值和查询中的严格门槛共用同一常量;pending 礼物快照被覆盖时该值也随最新 wallet 结算价值重算,不累计旧礼物。 + if coinSpent > formationGiftCoinThreshold { + return 1 + } + return 0 +} + func clampPageSize(pageSize int32) int32 { if pageSize <= 0 { return 20 diff --git a/services/user-service/internal/storage/mysql/db.go b/services/user-service/internal/storage/mysql/db.go index 5f2550fc..46be30b9 100644 --- a/services/user-service/internal/storage/mysql/db.go +++ b/services/user-service/internal/storage/mysql/db.go @@ -4,6 +4,7 @@ package mysql import ( "context" "database/sql" + "fmt" "strings" "time" @@ -58,6 +59,81 @@ func (r *Repository) Migrate(ctx context.Context) error { if err := r.ensureColumn(ctx, "login_audit", "build_number", "build_number VARCHAR(64) NOT NULL DEFAULT '' COMMENT '本次认证客户端构建号' AFTER app_version"); err != nil { return err } + // auth_sessions 是热表;只允许 INSTANT 常量默认列在启动迁移中执行,绝不在进程启动时隐式 COPY 大表或构建 family 索引。 + instantSessionColumns := []struct { + name string + ddl string + }{ + {name: "token_family_id", ddl: "token_family_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '令牌族根 session ID'"}, + {name: "generation", ddl: "generation BIGINT NOT NULL DEFAULT 0 COMMENT '令牌族内单调代际,首代为 0'"}, + {name: "parent_session_id", ddl: "parent_session_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '直接父代 session ID'"}, + {name: "rotated_to_session_id", ddl: "rotated_to_session_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '轮换产生的直接子代 session ID'"}, + {name: "rotation_at_ms", ddl: "rotation_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '轮换时间,UTC epoch ms'"}, + {name: "rotation_request_id", ddl: "rotation_request_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '首次轮换 refresh 幂等键'"}, + } + for _, column := range instantSessionColumns { + if err := r.ensureInstantColumn(ctx, "auth_sessions", column.name, column.ddl); err != nil { + return err + } + } + // family 索引会扫描登录热表,只能由离线 018 在低峰构建;缺失/同名错列时启动直接失败,不能静默全表查询。 + if err := r.requireIndexDefinition(ctx, "auth_sessions", "idx_auth_sessions_token_family", []string{"app_code", "token_family_id", "generation"}, false); err != nil { + return err + } + // 独立小表创建不扫描 auth_sessions;family 索引仍只允许由离线 018 migration 在低峰用 INPLACE/LOCK=NONE 创建。 + if _, err := r.db.ExecContext(ctx, ` + CREATE TABLE IF NOT EXISTS auth_refresh_outcomes ( + app_code VARCHAR(32) NOT NULL, + parent_session_id VARCHAR(96) NOT NULL, + child_session_id VARCHAR(96) NOT NULL, + refresh_request_id VARCHAR(96) NOT NULL, + token_ciphertext VARBINARY(4096) NOT NULL, + created_at_ms BIGINT NOT NULL, + expires_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, parent_session_id), + KEY idx_auth_refresh_outcomes_request (app_code, refresh_request_id), + KEY idx_auth_refresh_outcomes_expires (expires_at_ms) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci + `); err != nil { + return err + } + if _, err := r.db.ExecContext(ctx, ` + CREATE TABLE IF NOT EXISTS auth_session_denylist_jobs ( + job_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + app_code VARCHAR(32) NOT NULL, + session_id VARCHAR(96) NOT NULL, + reason VARCHAR(64) NOT NULL, + status VARCHAR(16) NOT NULL DEFAULT 'pending', + attempts INT NOT NULL DEFAULT 0, + next_retry_at_ms BIGINT NOT NULL DEFAULT 0, + locked_by VARCHAR(96) NOT NULL DEFAULT '', + locked_until_ms BIGINT NOT NULL DEFAULT 0, + last_error VARCHAR(512) NOT NULL DEFAULT '', + deny_until_ms BIGINT NOT NULL DEFAULT 0, + created_at_ms BIGINT NOT NULL, + updated_at_ms BIGINT NOT NULL, + UNIQUE KEY uk_auth_session_denylist_job (app_code, session_id), + KEY idx_auth_session_denylist_pending (status, next_retry_at_ms, job_id), + KEY idx_auth_session_denylist_cleanup (deny_until_ms, job_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci + `); err != nil { + return err + } + if err := r.ensureInstantColumn(ctx, "auth_session_denylist_jobs", "deny_until_ms", "deny_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT '历史 access JWT 最晚拒绝时刻(含安全余量),UTC epoch ms'"); err != nil { + return err + } + // 从旧三列 unique 收敛到每 sid 一行前必须先离线去重;启动时不能先 DROP 后因重复 ADD 失败而留下无唯一约束表。 + if err := r.requireIndexDefinition(ctx, "auth_session_denylist_jobs", "uk_auth_session_denylist_job", []string{"app_code", "session_id"}, true); err != nil { + return err + } + if err := r.ensureIndexDefinition(ctx, + "auth_session_denylist_jobs", + "idx_auth_session_denylist_cleanup", + []string{"deny_until_ms", "job_id"}, + "ALTER TABLE auth_session_denylist_jobs ADD INDEX idx_auth_session_denylist_cleanup (deny_until_ms, job_id)", + ); err != nil { + return err + } // Dashboard 必须先按用户分区,再按 created_at_ms/id 取最近成功登录。校验完整列序而不只检查索引名, // 防止历史环境中同名但列定义不完整的索引让查询退化成全表排序。 return r.ensureIndexDefinition(ctx, @@ -68,6 +144,62 @@ func (r *Repository) Migrate(ctx context.Context) error { ) } +func (r *Repository) requireIndexDefinition(ctx context.Context, tableName string, indexName string, columns []string, unique bool) error { + rows, err := r.db.QueryContext(ctx, ` + SELECT COLUMN_NAME, NON_UNIQUE + FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND INDEX_NAME = ? + ORDER BY SEQ_IN_INDEX + `, tableName, indexName) + if err != nil { + return err + } + defer rows.Close() + existing := make([]string, 0, len(columns)) + nonUnique := -1 + for rows.Next() { + var column string + var rowNonUnique int + if err := rows.Scan(&column, &rowNonUnique); err != nil { + return err + } + if nonUnique == -1 { + nonUnique = rowNonUnique + } else if nonUnique != rowNonUnique { + return fmt.Errorf("required index %s.%s has inconsistent NON_UNIQUE metadata", tableName, indexName) + } + existing = append(existing, column) + } + if err := rows.Err(); err != nil { + return err + } + wantNonUnique := 1 + if unique { + wantNonUnique = 0 + } + if !equalStringSlices(existing, columns) || nonUnique != wantNonUnique { + return fmt.Errorf("required index %s.%s has columns %v and NON_UNIQUE=%d, want columns %v and NON_UNIQUE=%d; apply migration 018 before startup", tableName, indexName, existing, nonUnique, columns, wantNonUnique) + } + return nil +} + +func (r *Repository) ensureInstantColumn(ctx context.Context, tableName string, columnName string, columnDDL string) error { + var count int + if err := r.db.QueryRowContext(ctx, + `SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?`, + tableName, columnName, + ).Scan(&count); err != nil { + return err + } + if count > 0 { + return nil + } + // 固定 DDL 若不支持 INSTANT 会直接失败,让操作者改走低峰 Online DDL,而不是启动时静默全表重建。 + // MySQL 8.4 的 INSTANT 算法不接受显式 LOCK 子句;只指定算法仍保证不退化成 COPY/INPLACE。 + _, err := r.db.ExecContext(ctx, `ALTER TABLE `+tableName+` ADD COLUMN `+columnDDL+`, ALGORITHM=INSTANT`) + return err +} + func (r *Repository) ensureColumn(ctx context.Context, tableName string, columnName string, columnDDL string) error { var count int if err := r.db.QueryRowContext(ctx, diff --git a/services/user-service/internal/storage/mysql/db_test.go b/services/user-service/internal/storage/mysql/db_test.go index b2b5402c..3d4fe059 100644 --- a/services/user-service/internal/storage/mysql/db_test.go +++ b/services/user-service/internal/storage/mysql/db_test.go @@ -27,7 +27,37 @@ func TestMigrateAddsLoginAuditClientVersionColumnsAndIndex(t *testing.T) { WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0)) mock.ExpectExec(regexp.QuoteMeta("ALTER TABLE login_audit ADD COLUMN build_number VARCHAR(64) NOT NULL DEFAULT '' COMMENT '本次认证客户端构建号' AFTER app_version")). WillReturnResult(sqlmock.NewResult(0, 0)) - mock.ExpectQuery(`(?s)SELECT COLUMN_NAME.*FROM information_schema\.STATISTICS.*TABLE_SCHEMA = DATABASE\(\).*TABLE_NAME = \?.*INDEX_NAME = \?.*ORDER BY SEQ_IN_INDEX`). + for _, column := range []string{"token_family_id", "generation", "parent_session_id", "rotated_to_session_id", "rotation_at_ms", "rotation_request_id"} { + mock.ExpectQuery(columnProbe). + WithArgs("auth_sessions", column). + WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1)) + } + requiredIndexProbe := `(?s)SELECT COLUMN_NAME, NON_UNIQUE.*FROM information_schema\.STATISTICS.*TABLE_SCHEMA = DATABASE\(\).*TABLE_NAME = \?.*INDEX_NAME = \?.*ORDER BY SEQ_IN_INDEX` + mock.ExpectQuery(requiredIndexProbe). + WithArgs("auth_sessions", "idx_auth_sessions_token_family"). + WillReturnRows(sqlmock.NewRows([]string{"COLUMN_NAME", "NON_UNIQUE"}). + AddRow("app_code", 1). + AddRow("token_family_id", 1). + AddRow("generation", 1)) + mock.ExpectExec(`(?s)CREATE TABLE IF NOT EXISTS auth_refresh_outcomes`). + WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectExec(`(?s)CREATE TABLE IF NOT EXISTS auth_session_denylist_jobs`). + WillReturnResult(sqlmock.NewResult(0, 0)) + mock.ExpectQuery(columnProbe). + WithArgs("auth_session_denylist_jobs", "deny_until_ms"). + WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1)) + mock.ExpectQuery(requiredIndexProbe). + WithArgs("auth_session_denylist_jobs", "uk_auth_session_denylist_job"). + WillReturnRows(sqlmock.NewRows([]string{"COLUMN_NAME", "NON_UNIQUE"}). + AddRow("app_code", 0). + AddRow("session_id", 0)) + indexProbe := `(?s)SELECT COLUMN_NAME.*FROM information_schema\.STATISTICS.*TABLE_SCHEMA = DATABASE\(\).*TABLE_NAME = \?.*INDEX_NAME = \?.*ORDER BY SEQ_IN_INDEX` + mock.ExpectQuery(indexProbe). + WithArgs("auth_session_denylist_jobs", "idx_auth_session_denylist_cleanup"). + WillReturnRows(sqlmock.NewRows([]string{"COLUMN_NAME"}). + AddRow("deny_until_ms"). + AddRow("job_id")) + mock.ExpectQuery(indexProbe). WithArgs("login_audit", "idx_login_audit_latest_success"). WillReturnRows(sqlmock.NewRows([]string{"COLUMN_NAME"})) mock.ExpectExec(regexp.QuoteMeta("ALTER TABLE login_audit ADD INDEX idx_login_audit_latest_success (app_code, user_id, result, blocked, login_type, created_at_ms, id)")). diff --git a/services/user-service/internal/testutil/mysqltest/mysqltest.go b/services/user-service/internal/testutil/mysqltest/mysqltest.go index 209446e1..0a37d150 100644 --- a/services/user-service/internal/testutil/mysqltest/mysqltest.go +++ b/services/user-service/internal/testutil/mysqltest/mysqltest.go @@ -358,6 +358,11 @@ func (r *Repository) FindActiveSessionByRefreshHash(ctx context.Context, refresh return r.Repository.AuthRepository().FindActiveSessionByRefreshHash(ctx, refreshTokenHash, nowMs) } +// FindSessionByRefreshHash 让 refresh rotation 测试读取已轮换 lineage。 +func (r *Repository) FindSessionByRefreshHash(ctx context.Context, refreshTokenHash string) (authdomain.Session, error) { + return r.Repository.AuthRepository().FindSessionByRefreshHash(ctx, refreshTokenHash) +} + // FindLatestActiveSessionByUser 让测试 wrapper 继续满足认证接口。 func (r *Repository) FindLatestActiveSessionByUser(ctx context.Context, userID int64, nowMs int64) (authdomain.Session, error) { return r.Repository.AuthRepository().FindLatestActiveSessionByUser(ctx, userID, nowMs) @@ -373,9 +378,9 @@ func (r *Repository) FindActiveSessionByID(ctx context.Context, sessionID string return r.Repository.AuthRepository().FindActiveSessionByID(ctx, sessionID, nowMs) } -// ReplaceSession 让测试 wrapper 继续满足认证接口。 -func (r *Repository) ReplaceSession(ctx context.Context, oldSessionID string, newSession authdomain.Session, revokedAtMs int64) error { - return r.Repository.AuthRepository().ReplaceSession(ctx, oldSessionID, newSession, revokedAtMs) +// RotateRefreshSession 让测试 wrapper 继续使用生产 MySQL 原子轮换实现。 +func (r *Repository) RotateRefreshSession(ctx context.Context, command authdomain.RefreshRotationCommand) (authdomain.RefreshRotationResult, error) { + return r.Repository.AuthRepository().RotateRefreshSession(ctx, command) } // RevokeSession 让测试 wrapper 继续满足认证接口。 @@ -383,6 +388,11 @@ func (r *Repository) RevokeSession(ctx context.Context, sessionID string, refres return r.Repository.AuthRepository().RevokeSession(ctx, sessionID, refreshTokenHash, revokedAtMs) } +// RevokeSessionFamily 让 logout/refresh 竞态测试覆盖真实 token family 事务。 +func (r *Repository) RevokeSessionFamily(ctx context.Context, sessionID string, refreshTokenHash string, revokedAtMs int64, denyUntilMs int64, requestID string) (string, []string, bool, error) { + return r.Repository.AuthRepository().RevokeSessionFamily(ctx, sessionID, refreshTokenHash, revokedAtMs, denyUntilMs, requestID) +} + // RevokeSessionWithReason 让测试 wrapper 继续满足认证接口。 func (r *Repository) RevokeSessionWithReason(ctx context.Context, sessionID string, revokedAtMs int64, reason string, requestID string, revokedBy string) (bool, error) { return r.Repository.AuthRepository().RevokeSessionWithReason(ctx, sessionID, revokedAtMs, reason, requestID, revokedBy) @@ -393,6 +403,34 @@ func (r *Repository) RevokeUserDeviceSessionsForRisk(ctx context.Context, source return r.Repository.AuthRepository().RevokeUserDeviceSessionsForRisk(ctx, sourceSessionID, userID, revokedAtMs, reason, requestID, revokedBy) } +func (r *Repository) ClaimSessionDenylistJobs(ctx context.Context, workerID string, nowMs int64, lockUntilMs int64, limit int) ([]authdomain.SessionDenylistJob, error) { + return r.Repository.AuthRepository().ClaimSessionDenylistJobs(ctx, workerID, nowMs, lockUntilMs, limit) +} + +func (r *Repository) MarkSessionDenylistJobDelivered(ctx context.Context, jobID int64, appCode string, sessionID string, reason string, appliedDenyUntilMs int64, nowMs int64, nextRehydrateAtMs int64) error { + return r.Repository.AuthRepository().MarkSessionDenylistJobDelivered(ctx, jobID, appCode, sessionID, reason, appliedDenyUntilMs, nowMs, nextRehydrateAtMs) +} + +func (r *Repository) MarkSessionDenylistJobRetryable(ctx context.Context, jobID int64, errorMessage string, nextRetryAtMs int64, nowMs int64) error { + return r.Repository.AuthRepository().MarkSessionDenylistJobRetryable(ctx, jobID, errorMessage, nextRetryAtMs, nowMs) +} + +func (r *Repository) MaxSessionDenylistJobID(ctx context.Context) (int64, error) { + return r.Repository.AuthRepository().MaxSessionDenylistJobID(ctx) +} + +func (r *Repository) ListSessionDenylistJobsForHydration(ctx context.Context, nowMs int64, afterJobID int64, throughJobID int64, limit int) ([]authdomain.SessionDenylistJob, int64, error) { + return r.Repository.AuthRepository().ListSessionDenylistJobsForHydration(ctx, nowMs, afterJobID, throughJobID, limit) +} + +func (r *Repository) DeleteExpiredSessionDenylistJobs(ctx context.Context, nowMs int64, limit int) (int, error) { + return r.Repository.AuthRepository().DeleteExpiredSessionDenylistJobs(ctx, nowMs, limit) +} + +func (r *Repository) DeleteExpiredRefreshOutcomes(ctx context.Context, nowMs int64, limit int) (int, error) { + return r.Repository.AuthRepository().DeleteExpiredRefreshOutcomes(ctx, nowMs, limit) +} + // UpdateSessionHeartbeat 让测试 wrapper 继续满足认证接口。 func (r *Repository) UpdateSessionHeartbeat(ctx context.Context, sessionID string, userID int64, heartbeatAtMs int64, requestID string) (authdomain.Session, error) { return r.Repository.AuthRepository().UpdateSessionHeartbeat(ctx, sessionID, userID, heartbeatAtMs, requestID) diff --git a/services/user-service/internal/transport/grpc/cp.go b/services/user-service/internal/transport/grpc/cp.go index 44cbc183..91ddf63c 100644 --- a/services/user-service/internal/transport/grpc/cp.go +++ b/services/user-service/internal/transport/grpc/cp.go @@ -105,6 +105,26 @@ func (s *Server) ListCPIntimacyLeaderboard(ctx context.Context, req *userv1.List return resp, nil } +// ListCPFormationGiftFeed 返回组 CP 成立时 wallet 结算金币价值严格超过固定门槛的历史成立事件。 +func (s *Server) ListCPFormationGiftFeed(ctx context.Context, req *userv1.ListCPFormationGiftFeedRequest) (*userv1.ListCPFormationGiftFeedResponse, error) { + ctx = contextWithApp(ctx, req.GetMeta()) + if s.cpSvc == nil { + return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "cp service is not configured")) + } + // limit 只控制返回条数;金币门槛、active/accepted 和 relation_type=cp 均由 owner 仓储固定,调用方不能篡改。 + items, err := s.cpSvc.ListFormationGiftFeed(ctx, req.GetLimit()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + resp := &userv1.ListCPFormationGiftFeedResponse{ + Items: make([]*userv1.CPFormationGiftFeedItem, 0, len(items)), + } + for _, item := range items { + resp.Items = append(resp.Items, toProtoCPFormationGiftFeedItem(item)) + } + return resp, nil +} + // PrepareBreakCPRelationship 创建解除关系占位;gateway 随后按返回费用调用 wallet-service 扣金币。 func (s *Server) PrepareBreakCPRelationship(ctx context.Context, req *userv1.PrepareBreakCPRelationshipRequest) (*userv1.PrepareBreakCPRelationshipResponse, error) { ctx = contextWithApp(ctx, req.GetMeta()) @@ -176,6 +196,7 @@ func (s *Server) ConsumeRoomGiftCPEvent(ctx context.Context, req *userv1.Consume GiftID: event.GetGiftId(), GiftCount: event.GetGiftCount(), GiftValue: event.GetGiftValue(), + CoinSpent: event.GetCoinSpent(), BillingReceiptID: event.GetBillingReceiptId(), VisibleRegionID: event.GetVisibleRegionId(), CommandID: event.GetCommandId(), @@ -259,6 +280,19 @@ func toProtoCPRelationship(relationship cpdomain.Relationship) *userv1.CPRelatio } } +func toProtoCPFormationGiftFeedItem(item cpdomain.FormationGiftFeedItem) *userv1.CPFormationGiftFeedItem { + if item.FormationID == "" { + return nil + } + return &userv1.CPFormationGiftFeedItem{ + FormationId: item.FormationID, + GiftCoinValue: item.GiftCoinValue, + Requester: toProtoCPUserProfile(item.Requester), + Target: toProtoCPUserProfile(item.Target), + FormedAtMs: item.FormedAtMS, + } +} + func toProtoCPUserProfile(profile cpdomain.UserProfile) *userv1.CPUserProfile { if profile.UserID <= 0 { return nil @@ -345,6 +379,7 @@ func toProtoCPGiftSnapshot(gift cpdomain.GiftSnapshot) *userv1.CPGiftSnapshot { GiftAnimationUrl: gift.GiftAnimationURL, GiftCount: gift.GiftCount, GiftValue: gift.GiftValue, + CoinSpent: gift.CoinSpent, BillingReceiptId: gift.BillingReceiptID, } } diff --git a/services/user-service/internal/transport/grpc/server.go b/services/user-service/internal/transport/grpc/server.go index 6e1e37f2..22fa14c4 100644 --- a/services/user-service/internal/transport/grpc/server.go +++ b/services/user-service/internal/transport/grpc/server.go @@ -248,7 +248,9 @@ func (s *Server) QuickCreateAccount(ctx context.Context, req *userv1.QuickCreate func (s *Server) RefreshToken(ctx context.Context, req *userv1.RefreshTokenRequest) (*userv1.RefreshTokenResponse, error) { ctx = contextWithApp(ctx, req.GetMeta()) // refresh token 轮换后响应里会返回新的 refresh token,旧 token 立即失效。 - token, err := s.authSvc.RefreshToken(ctx, req.GetRefreshToken(), req.GetMeta().GetDeviceId(), authMeta(req.GetMeta())) + meta := authMeta(req.GetMeta()) + meta.RefreshRequestID = req.GetRefreshRequestId() + token, err := s.authSvc.RefreshToken(ctx, req.GetRefreshToken(), req.GetMeta().GetDeviceId(), meta) if err != nil { return nil, xerr.ToGRPCError(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 3e4a3215..06caa9f6 100644 --- a/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql +++ b/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql @@ -41,6 +41,16 @@ CREATE TABLE IF NOT EXISTS wallet_transactions ( KEY idx_wallet_tx_external_ref (app_code, external_ref) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包交易主表'; +-- 提现终局锁是按申请增长的小表,不在 10GB 级 wallet_transactions 上增建唯一生成列索引。 +-- 首次 INSERT/ON DUPLICATE KEY 在主键上串行化 settle/release,避免两个“未找到终局”的 gap lock 同时通过后双向执行。 +CREATE TABLE IF NOT EXISTS wallet_withdrawal_terminal_locks ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码', + withdrawal_application_id VARCHAR(64) 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, withdrawal_application_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='提现申请钱包终局串行锁'; + -- App 用户送礼榜历史应急查询会按 app_code/biz_type/status/created_at_ms 过滤; -- 老索引缺 status 时会在 10GB 级 wallet_transactions 上读取大量失败/非成功交易再做 JSON 聚合。 SET @ddl := IF( @@ -1153,6 +1163,7 @@ CREATE TABLE IF NOT EXISTS resource_shop_items ( resource_id BIGINT NOT NULL COMMENT '售卖资源 ID', status VARCHAR(32) NOT NULL COMMENT '业务状态', duration_days INT NOT NULL COMMENT '售卖天数,只允许 1/3/7', + coin_price BIGINT NOT NULL DEFAULT 0 COMMENT '该售卖天数的独立金币价格;未自定义时复制资源列表价格', effective_from_ms BIGINT NOT NULL DEFAULT 0 COMMENT '生效开始时间,UTC epoch ms,0 表示立即生效', effective_to_ms BIGINT NOT NULL DEFAULT 0 COMMENT '生效结束时间,UTC epoch ms,0 表示长期有效', sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重,数值越小越靠前', @@ -1160,7 +1171,7 @@ CREATE TABLE IF NOT EXISTS resource_shop_items ( 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', - UNIQUE KEY uk_resource_shop_items_resource (app_code, resource_id), + UNIQUE KEY uk_resource_shop_items_resource_duration (app_code, resource_id, duration_days), KEY idx_resource_shop_items_status_sort (app_code, status, sort_order), KEY idx_resource_shop_items_effective (app_code, status, effective_from_ms, effective_to_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='道具商店售卖资源表'; @@ -1685,6 +1696,9 @@ CREATE TABLE IF NOT EXISTS user_vip_settings ( user_id BIGINT NOT NULL COMMENT '用户 ID', room_entry_notice_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否开启进房通知', online_global_notice_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否开启上线全服通知', + hide_profile_data_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否开启隐藏个人数据', + anonymous_profile_visit_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否开启匿名访问主页', + leaderboard_invisible_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否开启榜单隐身', created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', PRIMARY KEY (app_code, user_id) diff --git a/services/wallet-service/deploy/mysql/migrations/002_resource_shop_price_tiers.sql b/services/wallet-service/deploy/mysql/migrations/002_resource_shop_price_tiers.sql new file mode 100644 index 00000000..ec7738b0 --- /dev/null +++ b/services/wallet-service/deploy/mysql/migrations/002_resource_shop_price_tiers.sql @@ -0,0 +1,48 @@ +-- 道具商店从“每个资源一个动态价格”迁移为“每个资源可有 1/3/7 天独立定价规格”。 +-- 先增加带默认值的列,保证滚动发布期间旧代码仍可写入;随后把历史行回填为上线前实际展示/扣费价, +-- 因而迁移不会把既有 3/7 天商品突然降为资源列表原价。配置表数据量很小,但执行前仍应检查长事务, +-- 避免 ALTER TABLE 等待 metadata lock。 +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +USE hyapp_wallet; + +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'resource_shop_items' AND COLUMN_NAME = 'coin_price') = 0, + 'ALTER TABLE resource_shop_items ADD COLUMN coin_price BIGINT NOT NULL DEFAULT 0 COMMENT ''该售卖天数的独立金币价格;未自定义时复制资源列表价格'' AFTER duration_days', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- 旧实现按 resources.coin_price * duration_days 实时计价。乘法上界保护只处理异常脏数据;正常 1/3/7 +-- 天配置会完整保留迁移前价格,之后资源目录调价不再隐式影响已上架规格。 +UPDATE resource_shop_items AS si +JOIN resources AS r ON r.app_code = si.app_code AND r.resource_id = si.resource_id +SET si.coin_price = CASE + WHEN si.duration_days > 0 AND r.coin_price <= 9223372036854775807 DIV si.duration_days + THEN r.coin_price * si.duration_days + ELSE r.coin_price +END +WHERE si.coin_price = 0; + +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'resource_shop_items' AND INDEX_NAME = 'uk_resource_shop_items_resource_duration') = 0, + 'ALTER TABLE resource_shop_items ADD UNIQUE INDEX uk_resource_shop_items_resource_duration (app_code, resource_id, duration_days)', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'resource_shop_items' AND INDEX_NAME = 'uk_resource_shop_items_resource') > 0, + 'ALTER TABLE resource_shop_items DROP INDEX uk_resource_shop_items_resource', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; diff --git a/services/wallet-service/internal/domain/ledger/vip.go b/services/wallet-service/internal/domain/ledger/vip.go index d173982b..db141c23 100644 --- a/services/wallet-service/internal/domain/ledger/vip.go +++ b/services/wallet-service/internal/domain/ledger/vip.go @@ -128,6 +128,36 @@ type VipBenefit struct { MetadataJSON string CreatedAtMS int64 UpdatedAtMS int64 + Presentation *VipBenefitPresentation +} + +// VipBenefitPresentation 是 App 可直接渲染的权益表现契约。它从 metadata_json.presentation +// 投影而来,避免 Flutter 按 benefit_code 维护一份隐形 JSON 解析规则。 +type VipBenefitPresentation struct { + Description string `json:"description"` + PreviewItems []VipBenefitPreviewItem `json:"preview_items"` + NumericReward *VipBenefitNumericReward `json:"numeric_reward,omitempty"` +} + +// VipBenefitPreviewItem 描述一个静态或动态预览。CompositionType 明确头像合成方式, +// 头像框与声波纹无需再由客户端根据权益编码猜测布局。 +type VipBenefitPreviewItem struct { + PreviewID string `json:"preview_id"` + Title string `json:"title"` + MediaType string `json:"media_type"` + AssetURL string `json:"asset_url"` + PreviewURL string `json:"preview_url"` + AnimationURL string `json:"animation_url"` + CompositionType string `json:"composition_type"` + SortOrder int32 `json:"sort_order"` +} + +// VipBenefitNumericReward 只负责数值展示;真实发放和结算仍由对应 owner service 执行。 +type VipBenefitNumericReward struct { + Label string `json:"label"` + Value int64 `json:"value"` + Unit string `json:"unit"` + Period string `json:"period"` } // VipRewardItem 是 VIP 资源组权益的轻量展示投影。 @@ -201,28 +231,39 @@ type VipTrialCard struct { // VipUserSettings 是用户可关闭的 VIP 展示偏好。默认值必须由 wallet owner 统一构造, // 不能让 room/gateway 因为数据库尚未物化记录而各自猜不同默认值。 type VipUserSettings struct { - AppCode string - UserID int64 - RoomEntryNoticeEnabled bool - OnlineGlobalNoticeEnabled bool - UpdatedAtMS int64 + AppCode string + UserID int64 + RoomEntryNoticeEnabled bool + OnlineGlobalNoticeEnabled bool + HideProfileDataEnabled bool + AnonymousProfileVisitEnabled bool + LeaderboardInvisibleEnabled bool + UpdatedAtMS int64 } -// DefaultVipUserSettings 返回尚未物化时的产品默认:两项通知均开启,UpdatedAtMS=0。 +// DefaultVipUserSettings 返回尚未物化时的产品默认:五项能力均开启,UpdatedAtMS=0。 func DefaultVipUserSettings(appCode string, userID int64) VipUserSettings { return VipUserSettings{ AppCode: appCode, UserID: userID, RoomEntryNoticeEnabled: true, OnlineGlobalNoticeEnabled: true, + HideProfileDataEnabled: true, AnonymousProfileVisitEnabled: true, + LeaderboardInvisibleEnabled: true, } } -// AllowsBenefitSetting 只处理用户可关闭的两项权益;其它权益不受偏好表影响。 +// AllowsBenefitSetting 只处理用户可关闭的五项权益;其它权益不受偏好表影响。 func (settings VipUserSettings) AllowsBenefitSetting(benefitCode string) bool { switch strings.ToLower(strings.TrimSpace(benefitCode)) { case VipBenefitCodeRoomEntryNotice: return settings.RoomEntryNoticeEnabled case VipBenefitCodeOnlineGlobalNotice: return settings.OnlineGlobalNoticeEnabled + case VipBenefitCodeHideProfileData: + return settings.HideProfileDataEnabled + case VipBenefitCodeAnonymousProfileVisit: + return settings.AnonymousProfileVisitEnabled + case VipBenefitCodeLeaderboardInvisible: + return settings.LeaderboardInvisibleEnabled default: return true } @@ -256,6 +297,7 @@ type PurchaseVipReceipt struct { Vip UserVip CoinSpent int64 CoinBalanceAfter int64 + CoinBalance AssetBalance RewardItems []VipRewardItem State VipState } @@ -345,10 +387,13 @@ type AdminVipProgramConfigCommand struct { // UpdateVipUserSettingsCommand 使用指针表达 partial update;nil 字段必须保留数据库原值。 type UpdateVipUserSettingsCommand struct { - AppCode string - UserID int64 - RoomEntryNoticeEnabled *bool - OnlineGlobalNoticeEnabled *bool + AppCode string + UserID int64 + RoomEntryNoticeEnabled *bool + OnlineGlobalNoticeEnabled *bool + HideProfileDataEnabled *bool + AnonymousProfileVisitEnabled *bool + LeaderboardInvisibleEnabled *bool } // VipDailyCoinRebateRun 是单 App、单 UTC 日唯一的配置快照与分页游标。 diff --git a/services/wallet-service/internal/domain/ledger/vip_presentation.go b/services/wallet-service/internal/domain/ledger/vip_presentation.go new file mode 100644 index 00000000..a0a57de8 --- /dev/null +++ b/services/wallet-service/internal/domain/ledger/vip_presentation.go @@ -0,0 +1,145 @@ +package ledger + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + "unicode/utf8" +) + +const ( + vipPresentationDescriptionMaxRunes = 1000 + vipPresentationPreviewMaxCount = 20 + vipPresentationTextMaxRunes = 128 + vipPresentationURLMaxRunes = 2048 +) + +// ParseVipBenefitPresentation 只解析 metadata_json.presentation 这一段稳定展示契约。 +// metadata_json 的其它业务字段(例如 coin_amount、message)由对应 owner 保留处理。 +func ParseVipBenefitPresentation(metadataJSON string) (*VipBenefitPresentation, error) { + metadataJSON = strings.TrimSpace(metadataJSON) + if metadataJSON == "" { + return nil, nil + } + var metadata struct { + Presentation *VipBenefitPresentation `json:"presentation"` + } + if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil { + return nil, err + } + if metadata.Presentation == nil { + return nil, nil + } + if err := ValidateVipBenefitPresentation(*metadata.Presentation); err != nil { + return nil, err + } + return metadata.Presentation, nil +} + +// MergeVipBenefitPresentation 将后台结构化输入归一到现有 JSON 列,避免为纯展示字段增加双写事实。 +// presentation 为空对象表示显式清除;nil 表示沿用 metadata_json 中已有值。 +func MergeVipBenefitPresentation(metadataJSON string, presentation *VipBenefitPresentation) (string, error) { + metadataJSON = strings.TrimSpace(metadataJSON) + if presentation == nil { + if metadataJSON == "" { + return "", nil + } + if !json.Valid([]byte(metadataJSON)) { + return "", errors.New("metadata_json is invalid") + } + return metadataJSON, nil + } + if err := ValidateVipBenefitPresentation(*presentation); err != nil { + return "", err + } + + metadata := make(map[string]json.RawMessage) + if metadataJSON != "" { + if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil || metadata == nil { + return "", errors.New("metadata_json must be an object") + } + } + if vipBenefitPresentationIsZero(*presentation) { + delete(metadata, "presentation") + } else { + encoded, err := json.Marshal(presentation) + if err != nil { + return "", err + } + metadata["presentation"] = encoded + } + if len(metadata) == 0 { + return "", nil + } + encoded, err := json.Marshal(metadata) + return string(encoded), err +} + +// ValidateVipBenefitPresentation 锁定 Flutter 可直接渲染的边界,防止后台把任意 JSON +// 重新变成客户端按 benefit_code 猜类型的隐式协议。 +func ValidateVipBenefitPresentation(presentation VipBenefitPresentation) error { + presentation.Description = strings.TrimSpace(presentation.Description) + if utf8.RuneCountInString(presentation.Description) > vipPresentationDescriptionMaxRunes { + return errors.New("presentation description is too long") + } + if len(presentation.PreviewItems) > vipPresentationPreviewMaxCount { + return errors.New("presentation has too many preview items") + } + seen := make(map[string]struct{}, len(presentation.PreviewItems)) + for index, item := range presentation.PreviewItems { + item.PreviewID = strings.TrimSpace(item.PreviewID) + item.Title = strings.TrimSpace(item.Title) + item.MediaType = strings.ToLower(strings.TrimSpace(item.MediaType)) + item.CompositionType = strings.ToLower(strings.TrimSpace(item.CompositionType)) + if item.PreviewID == "" || utf8.RuneCountInString(item.PreviewID) > vipPresentationTextMaxRunes { + return fmt.Errorf("preview_items[%d].preview_id is invalid", index) + } + if _, exists := seen[item.PreviewID]; exists { + return fmt.Errorf("preview_items[%d].preview_id is duplicated", index) + } + seen[item.PreviewID] = struct{}{} + if utf8.RuneCountInString(item.Title) > vipPresentationTextMaxRunes { + return fmt.Errorf("preview_items[%d].title is too long", index) + } + if item.MediaType != "image" && item.MediaType != "animation" { + return fmt.Errorf("preview_items[%d].media_type is invalid", index) + } + switch item.CompositionType { + case "none", "user_avatar_center", "user_avatar_waveform": + default: + return fmt.Errorf("preview_items[%d].composition_type is invalid", index) + } + if exceedsRuneLimit(item.AssetURL, vipPresentationURLMaxRunes) || exceedsRuneLimit(item.PreviewURL, vipPresentationURLMaxRunes) || exceedsRuneLimit(item.AnimationURL, vipPresentationURLMaxRunes) { + return fmt.Errorf("preview_items[%d] url is too long", index) + } + if item.MediaType == "animation" && strings.TrimSpace(item.AnimationURL) == "" { + return fmt.Errorf("preview_items[%d].animation_url is required", index) + } + if item.MediaType == "image" && strings.TrimSpace(item.PreviewURL) == "" && strings.TrimSpace(item.AssetURL) == "" { + return fmt.Errorf("preview_items[%d] image url is required", index) + } + } + if reward := presentation.NumericReward; reward != nil { + reward.Label = strings.TrimSpace(reward.Label) + reward.Unit = strings.TrimSpace(reward.Unit) + reward.Period = strings.ToLower(strings.TrimSpace(reward.Period)) + if reward.Value <= 0 || reward.Label == "" || reward.Unit == "" || utf8.RuneCountInString(reward.Label) > vipPresentationTextMaxRunes || utf8.RuneCountInString(reward.Unit) > vipPresentationTextMaxRunes { + return errors.New("numeric_reward is invalid") + } + switch reward.Period { + case "once", "daily", "monthly": + default: + return errors.New("numeric_reward.period is invalid") + } + } + return nil +} + +func vipBenefitPresentationIsZero(presentation VipBenefitPresentation) bool { + return strings.TrimSpace(presentation.Description) == "" && len(presentation.PreviewItems) == 0 && presentation.NumericReward == nil +} + +func exceedsRuneLimit(value string, limit int) bool { + return utf8.RuneCountInString(strings.TrimSpace(value)) > limit +} diff --git a/services/wallet-service/internal/domain/ledger/vip_presentation_test.go b/services/wallet-service/internal/domain/ledger/vip_presentation_test.go new file mode 100644 index 00000000..26c2d697 --- /dev/null +++ b/services/wallet-service/internal/domain/ledger/vip_presentation_test.go @@ -0,0 +1,46 @@ +package ledger + +import "testing" + +func TestVipBenefitPresentationRoundTripPreservesOtherMetadata(t *testing.T) { + presentation := &VipBenefitPresentation{ + Description: "头像框会自动合成当前用户头像", + PreviewItems: []VipBenefitPreviewItem{{ + PreviewID: "frame-main", MediaType: "animation", AnimationURL: "https://cdn.example/frame.svga", + PreviewURL: "https://cdn.example/frame.png", CompositionType: "user_avatar_center", SortOrder: 10, + }}, + NumericReward: &VipBenefitNumericReward{Label: "每日返现", Value: 100, Unit: "金币", Period: "daily"}, + } + metadata, err := MergeVipBenefitPresentation(`{"coin_amount":100}`, presentation) + if err != nil { + t.Fatalf("merge presentation failed: %v", err) + } + parsed, err := ParseVipBenefitPresentation(metadata) + if err != nil || parsed == nil { + t.Fatalf("parse presentation failed: parsed=%+v err=%v", parsed, err) + } + if parsed.Description != presentation.Description || len(parsed.PreviewItems) != 1 || parsed.PreviewItems[0].CompositionType != "user_avatar_center" || parsed.NumericReward == nil || parsed.NumericReward.Value != 100 { + t.Fatalf("presentation round trip mismatch: %+v", parsed) + } + if metadata == "" || !containsJSONFragment(metadata, `"coin_amount":100`) { + t.Fatalf("merge must preserve owner metadata: %s", metadata) + } +} + +func TestVipBenefitPresentationRejectsImplicitClientRules(t *testing.T) { + invalid := VipBenefitPresentation{PreviewItems: []VipBenefitPreviewItem{{ + PreviewID: "wave", MediaType: "animation", CompositionType: "guess_from_benefit_code", + }}} + if err := ValidateVipBenefitPresentation(invalid); err == nil { + t.Fatal("unknown composition type must be rejected") + } +} + +func containsJSONFragment(value string, fragment string) bool { + for index := 0; index+len(fragment) <= len(value); index++ { + if value[index:index+len(fragment)] == fragment { + return true + } + } + return false +} diff --git a/services/wallet-service/internal/domain/resource/entitlement.go b/services/wallet-service/internal/domain/resource/entitlement.go index 8fb02e9d..9fa50aae 100644 --- a/services/wallet-service/internal/domain/resource/entitlement.go +++ b/services/wallet-service/internal/domain/resource/entitlement.go @@ -30,6 +30,15 @@ type ListUserResourcesQuery struct { ActiveOnly bool } +type RevokeUserResourceCommand struct { + RequestID string + AppCode string + UserID int64 + EntitlementID string + Reason string + OperatorUserID int64 +} + type EquipUserResourceCommand struct { // RequestID 在通用背包命中 VIP 体验卡时作为专用状态机的 outbox 幂等事件键; // 普通装扮仍不把 request_id 当业务幂等键。 diff --git a/services/wallet-service/internal/domain/resource/shop.go b/services/wallet-service/internal/domain/resource/shop.go index 3fea677f..29005801 100644 --- a/services/wallet-service/internal/domain/resource/shop.go +++ b/services/wallet-service/internal/domain/resource/shop.go @@ -43,10 +43,12 @@ type ResourceShopPurchaseOrder struct { } type ResourceShopItemInput struct { - ShopItemID int64 - ResourceID int64 - Status string - DurationDays int32 + ShopItemID int64 + ResourceID int64 + Status string + DurationDays int32 + // CoinPrice 新建为 0 时使用资源列表价,更新已有规格为 0 时保留当前售价;落库后各规格价格互相独立。 + CoinPrice int64 EffectiveFromMS int64 EffectiveToMS int64 SortOrder int32 diff --git a/services/wallet-service/internal/service/wallet/ports/repository.go b/services/wallet-service/internal/service/wallet/ports/repository.go index 36dda1af..01384f68 100644 --- a/services/wallet-service/internal/service/wallet/ports/repository.go +++ b/services/wallet-service/internal/service/wallet/ports/repository.go @@ -215,6 +215,7 @@ type ResourceGrantStore interface { // ResourceEquipmentStore 管理用户资源权益和穿戴状态。 type ResourceEquipmentStore interface { ListUserResources(ctx context.Context, query resourcedomain.ListUserResourcesQuery) ([]resourcedomain.UserResourceEntitlement, error) + RevokeUserResource(ctx context.Context, command resourcedomain.RevokeUserResourceCommand) (resourcedomain.UserResourceEntitlement, error) EquipUserResource(ctx context.Context, command resourcedomain.EquipUserResourceCommand) (resourcedomain.UserResourceEntitlement, error) UnequipUserResource(ctx context.Context, command resourcedomain.UnequipUserResourceCommand) (resourcedomain.UnequipUserResourceResult, error) BatchGetUserEquippedResources(ctx context.Context, query resourcedomain.BatchGetUserEquippedResourcesQuery) ([]resourcedomain.UserEquippedResources, error) diff --git a/services/wallet-service/internal/service/wallet/resource.go b/services/wallet-service/internal/service/wallet/resource.go index 808dd568..3f0f4c1a 100644 --- a/services/wallet-service/internal/service/wallet/resource.go +++ b/services/wallet-service/internal/service/wallet/resource.go @@ -280,6 +280,15 @@ func (s *Service) ListUserResources(ctx context.Context, query resourcedomain.Li return s.repository.ListUserResources(ctx, query) } +func (s *Service) RevokeUserResource(ctx context.Context, command resourcedomain.RevokeUserResourceCommand) (resourcedomain.UserResourceEntitlement, error) { + if s.repository == nil { + return resourcedomain.UserResourceEntitlement{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + command.AppCode = appcode.Normalize(command.AppCode) + ctx = appcode.WithContext(ctx, command.AppCode) + return s.repository.RevokeUserResource(ctx, command) +} + func (s *Service) EquipUserResource(ctx context.Context, command resourcedomain.EquipUserResourceCommand) (resourcedomain.UserResourceEntitlement, error) { if s.repository == nil { return resourcedomain.UserResourceEntitlement{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") diff --git a/services/wallet-service/internal/service/wallet/service_test.go b/services/wallet-service/internal/service/wallet/service_test.go index 3eece8b3..dacd6a47 100644 --- a/services/wallet-service/internal/service/wallet/service_test.go +++ b/services/wallet-service/internal/service/wallet/service_test.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "strings" + "sync" "testing" "time" @@ -2353,6 +2354,156 @@ func TestPointWithdrawalFreezeSettleReleaseIsHuwaaOnly(t *testing.T) { requireWalletBalanceForApp(t, svc, "huwaa", 22002, ledger.AssetPoint, 2_000_000, 0) } +func TestSalaryWithdrawalTerminalReusesLegacyCommandAcrossReviewerRetryAndRejectsOppositeDecision(t *testing.T) { + repository := mysqltest.NewRepository(t) + repository.SetAssetBalanceForApp("lalu", 22003, ledger.AssetHostSalaryUSD, 10_000) + svc := walletservice.New(repository) + + if _, err := svc.FreezeSalaryWithdrawal(context.Background(), ledger.SalaryWithdrawalCommand{ + AppCode: "lalu", CommandID: "salary-withdrawal:legacy-freeze", UserID: 22003, + SalaryAssetType: ledger.AssetHostSalaryUSD, SalaryUSDMinor: 5_000, WithdrawalRef: "legacy-freeze", + }); err != nil { + t.Fatalf("freeze salary withdrawal failed: %v", err) + } + legacy, err := svc.SettleSalaryWithdrawal(context.Background(), ledger.SalaryWithdrawalCommand{ + AppCode: "lalu", CommandID: "salary-withdrawal:901:approved", UserID: 22003, + SalaryAssetType: ledger.AssetHostSalaryUSD, SalaryUSDMinor: 5_000, + OperatorUserID: 7, Reason: "legacy finance remark", WithdrawalApplicationID: "901", + }) + if err != nil { + t.Fatalf("legacy finance settlement failed: %v", err) + } + + // admin 事务若在 wallet 成功后失败,新版会换用 stage command,并可能由另一审核人修改备注后重试。 + // wallet 必须按 application id 找回旧回执,不再扣减 frozen,也不因审计 metadata 改变产生 hash 冲突。 + retry, err := svc.SettleSalaryWithdrawal(context.Background(), ledger.SalaryWithdrawalCommand{ + AppCode: "lalu", CommandID: "salary-withdrawal:901:finance", UserID: 22003, + SalaryAssetType: ledger.AssetHostSalaryUSD, SalaryUSDMinor: 5_000, + OperatorUserID: 9, Reason: "new reviewer changed remark", WithdrawalApplicationID: "901", + }) + if err != nil { + t.Fatalf("stage command retry must reuse legacy terminal: %v", err) + } + if retry.TransactionID != legacy.TransactionID { + t.Fatalf("retry transaction = %s, want legacy %s", retry.TransactionID, legacy.TransactionID) + } + if got := repository.CountRows("wallet_transactions", "app_code = ? AND external_ref = ? AND biz_type IN (?, ?)", "lalu", "901", "salary_withdrawal_settle", "salary_withdrawal_release"); got != 1 { + t.Fatalf("withdrawal application must own one terminal transaction, got %d", got) + } + requireWalletBalanceForApp(t, svc, "lalu", 22003, ledger.AssetHostSalaryUSD, 5_000, 0) + + _, err = svc.ReleaseSalaryWithdrawal(context.Background(), ledger.SalaryWithdrawalCommand{ + AppCode: "lalu", CommandID: "salary-withdrawal:901:finance", UserID: 22003, + SalaryAssetType: ledger.AssetHostSalaryUSD, SalaryUSDMinor: 5_000, + OperatorUserID: 10, Reason: "opposite decision", WithdrawalApplicationID: "901", + }) + if !xerr.IsCode(err, xerr.IdempotencyConflict) { + t.Fatalf("opposite terminal decision must conflict, got %v", err) + } + if got := repository.CountRows("wallet_transactions", "app_code = ? AND external_ref = ? AND biz_type IN (?, ?)", "lalu", "901", "salary_withdrawal_settle", "salary_withdrawal_release"); got != 1 { + t.Fatalf("opposite decision must not create a second terminal transaction, got %d", got) + } +} + +func TestPointWithdrawalTerminalReusesLegacyCommandWithNormalizedPolicySnapshot(t *testing.T) { + repository := mysqltest.NewRepository(t) + repository.SetAssetBalanceForApp("huwaa", 22005, ledger.AssetPoint, 2_000_000) + svc := walletservice.New(repository) + + if _, err := svc.FreezePointWithdrawal(context.Background(), ledger.PointWithdrawalCommand{ + AppCode: "huwaa", CommandID: "point-withdrawal:legacy-freeze", UserID: 22005, + AssetType: ledger.AssetPoint, GrossPointAmount: 1_000_000, + FeePointAmount: 50_000, NetPointAmount: 950_000, PointsPerUSD: 100_000, FeeBPS: 500, + WithdrawalRef: "point-legacy-freeze", + }); err != nil { + t.Fatalf("freeze point withdrawal failed: %v", err) + } + legacy, err := svc.SettlePointWithdrawal(context.Background(), ledger.PointWithdrawalCommand{ + AppCode: "huwaa", CommandID: "salary-withdrawal:903:approved", UserID: 22005, + AssetType: ledger.AssetPoint, GrossPointAmount: 1_000_000, + FeePointAmount: 50_000, NetPointAmount: 950_000, PointsPerUSD: 100_000, FeeBPS: 500, + OperatorUserID: 7, Reason: "legacy point finance remark", WithdrawalApplicationID: "903", + }) + if err != nil { + t.Fatalf("legacy point withdrawal settlement failed: %v", err) + } + + // 新版重试可由另一审核人发起且省略可由政策快照确定的 fee/net;service 归一化后必须命中旧终局 metadata。 + retry, err := svc.SettlePointWithdrawal(context.Background(), ledger.PointWithdrawalCommand{ + AppCode: "huwaa", CommandID: "salary-withdrawal:903:finance", UserID: 22005, + AssetType: ledger.AssetPoint, GrossPointAmount: 1_000_000, PointsPerUSD: 100_000, FeeBPS: 500, + OperatorUserID: 9, Reason: "new point reviewer remark", WithdrawalApplicationID: "903", + }) + if err != nil { + t.Fatalf("stage point command retry must reuse legacy terminal: %v", err) + } + if retry.TransactionID != legacy.TransactionID || retry.FeePointAmount != 50_000 || retry.NetPointAmount != 950_000 || retry.PointsPerUSD != 100_000 || retry.FeeBPS != 500 { + t.Fatalf("point terminal retry snapshot mismatch: legacy=%+v retry=%+v", legacy, retry) + } + if got := repository.CountRows("wallet_transactions", "app_code = ? AND external_ref = ? AND biz_type IN (?, ?)", "huwaa", "903", "salary_withdrawal_settle", "salary_withdrawal_release"); got != 1 { + t.Fatalf("point withdrawal application must own one terminal transaction, got %d", got) + } + requireWalletBalanceForApp(t, svc, "huwaa", 22005, ledger.AssetPoint, 1_000_000, 0) +} + +func TestSalaryWithdrawalTerminalSerializesConcurrentOppositeDecisions(t *testing.T) { + repository := mysqltest.NewRepository(t) + repository.SetAssetBalanceForApp("lalu", 22004, ledger.AssetHostSalaryUSD, 10_000) + svc := walletservice.New(repository) + if _, err := svc.FreezeSalaryWithdrawal(context.Background(), ledger.SalaryWithdrawalCommand{ + AppCode: "lalu", CommandID: "salary-withdrawal:concurrent-freeze", UserID: 22004, + SalaryAssetType: ledger.AssetHostSalaryUSD, SalaryUSDMinor: 5_000, WithdrawalRef: "concurrent-freeze", + }); err != nil { + t.Fatalf("freeze salary withdrawal failed: %v", err) + } + + start := make(chan struct{}) + errs := make(chan error, 2) + var workers sync.WaitGroup + workers.Add(2) + go func() { + defer workers.Done() + <-start + _, err := svc.SettleSalaryWithdrawal(context.Background(), ledger.SalaryWithdrawalCommand{ + AppCode: "lalu", CommandID: "salary-withdrawal:902:approved", UserID: 22004, + SalaryAssetType: ledger.AssetHostSalaryUSD, SalaryUSDMinor: 5_000, + OperatorUserID: 7, Reason: "approve", WithdrawalApplicationID: "902", + }) + errs <- err + }() + go func() { + defer workers.Done() + <-start + _, err := svc.ReleaseSalaryWithdrawal(context.Background(), ledger.SalaryWithdrawalCommand{ + AppCode: "lalu", CommandID: "salary-withdrawal:902:finance", UserID: 22004, + SalaryAssetType: ledger.AssetHostSalaryUSD, SalaryUSDMinor: 5_000, + OperatorUserID: 8, Reason: "reject", WithdrawalApplicationID: "902", + }) + errs <- err + }() + close(start) + workers.Wait() + close(errs) + + succeeded, conflicted := 0, 0 + for err := range errs { + switch { + case err == nil: + succeeded++ + case xerr.IsCode(err, xerr.IdempotencyConflict): + conflicted++ + default: + t.Fatalf("unexpected concurrent terminal error: %v", err) + } + } + if succeeded != 1 || conflicted != 1 { + t.Fatalf("concurrent terminal results: succeeded=%d conflicted=%d", succeeded, conflicted) + } + if got := repository.CountRows("wallet_transactions", "app_code = ? AND external_ref = ? AND biz_type IN (?, ?)", "lalu", "902", "salary_withdrawal_settle", "salary_withdrawal_release"); got != 1 { + t.Fatalf("concurrent opposite decisions created %d terminal rows", got) + } +} + // TestTransferPointToCoinSellerUsesServerWhitelist 验证 H5 不能自报比例,wallet 会按 App、国家和 active 配置原子扣 POINT/加币商库存。 func TestTransferPointToCoinSellerUsesServerWhitelist(t *testing.T) { repository := mysqltest.NewRepository(t) @@ -5547,6 +5698,132 @@ func TestRevokeResourceGroupGrantReversesWalletCreditAndEntitlement(t *testing.T } } +// TestRevokeUserResourceKeepsResourceGroupSiblings proves the admin detail action removes only the +// selected entitlement. Reusing grant-level revoke here would also remove every sibling in the group. +func TestRevokeUserResourceKeepsResourceGroupSiblings(t *testing.T) { + repository := mysqltest.NewRepository(t) + svc := walletservice.New(repository) + ctx := context.Background() + + hostBadge, err := svc.CreateResource(ctx, resourcedomain.ResourceCommand{ + ResourceCode: "host_badge_precise_revoke", + ResourceType: resourcedomain.TypeBadge, + Name: "Host Badge", + Status: resourcedomain.StatusActive, + Grantable: true, + GrantStrategy: resourcedomain.GrantStrategySetActiveFlag, + UsageScopes: []string{"profile"}, + OperatorUserID: 90001, + }) + if err != nil { + t.Fatalf("create host badge failed: %v", err) + } + avatarFrame, err := svc.CreateResource(ctx, resourcedomain.ResourceCommand{ + ResourceCode: "host_frame_precise_revoke", + ResourceType: resourcedomain.TypeAvatarFrame, + Name: "Host Frame", + Status: resourcedomain.StatusActive, + Grantable: true, + GrantStrategy: resourcedomain.GrantStrategySetActiveFlag, + UsageScopes: []string{"profile"}, + OperatorUserID: 90001, + }) + if err != nil { + t.Fatalf("create host frame failed: %v", err) + } + group, err := svc.CreateResourceGroup(ctx, resourcedomain.ResourceGroupCommand{ + GroupCode: "host_assets_precise_revoke", + Name: "Host Assets", + Status: resourcedomain.StatusActive, + Items: []resourcedomain.ResourceGroupItemInput{ + {ResourceID: hostBadge.ResourceID, Quantity: 1, SortOrder: 1}, + {ResourceID: avatarFrame.ResourceID, Quantity: 1, SortOrder: 2}, + }, + OperatorUserID: 90001, + }) + if err != nil { + t.Fatalf("create host resource group failed: %v", err) + } + grant, err := svc.GrantResourceGroup(ctx, resourcedomain.GrantResourceGroupCommand{ + CommandID: "cmd-grant-host-assets-precise-revoke", + TargetUserID: 42106, + GroupID: group.GroupID, + Reason: "test precise user resource revoke", + OperatorUserID: 90001, + GrantSource: resourcedomain.GrantSourceAdmin, + }) + if err != nil { + t.Fatalf("grant host resource group failed: %v", err) + } + + var badgeEntitlementID, frameEntitlementID string + for _, item := range grant.Items { + switch item.ResourceID { + case hostBadge.ResourceID: + badgeEntitlementID = item.EntitlementID + case avatarFrame.ResourceID: + frameEntitlementID = item.EntitlementID + } + } + if badgeEntitlementID == "" || frameEntitlementID == "" { + t.Fatalf("grant entitlements are incomplete: %+v", grant.Items) + } + for resourceID, entitlementID := range map[int64]string{ + hostBadge.ResourceID: badgeEntitlementID, + avatarFrame.ResourceID: frameEntitlementID, + } { + if _, err := svc.EquipUserResource(ctx, resourcedomain.EquipUserResourceCommand{ + UserID: 42106, ResourceID: resourceID, EntitlementID: entitlementID, + }); err != nil { + t.Fatalf("equip resource %d failed: %v", resourceID, err) + } + } + + revoked, err := svc.RevokeUserResource(ctx, resourcedomain.RevokeUserResourceCommand{ + RequestID: "request-revoke-host-badge", + UserID: 42106, + EntitlementID: badgeEntitlementID, + Reason: "remove host badge", + OperatorUserID: 90002, + }) + if err != nil { + t.Fatalf("RevokeUserResource failed: %v", err) + } + if revoked.Status != resourcedomain.GrantStatusRevoked || revoked.RemainingQuantity != 0 || revoked.Equipped { + t.Fatalf("revoked entitlement state mismatch: %+v", revoked) + } + active, err := svc.ListUserResources(ctx, resourcedomain.ListUserResourcesQuery{UserID: 42106, ActiveOnly: true}) + if err != nil { + t.Fatalf("list active resources failed: %v", err) + } + if len(active) != 1 || active[0].EntitlementID != frameEntitlementID { + t.Fatalf("resource-group sibling must remain active: %+v", active) + } + if got := repository.CountRows("resource_grants", "grant_id = ? AND status = ?", grant.GrantID, resourcedomain.GrantStatusDone); got != 1 { + t.Fatalf("precise revoke must not revoke the source group grant, got %d", got) + } + if got := repository.CountRows("user_resource_equipment", "user_id = ? AND entitlement_id = ?", int64(42106), badgeEntitlementID); got != 0 { + t.Fatalf("revoked badge equipment row must be removed, got %d", got) + } + if got := repository.CountRows("user_resource_equipment", "user_id = ? AND entitlement_id = ?", int64(42106), frameEntitlementID); got != 1 { + t.Fatalf("sibling frame equipment row must remain, got %d", got) + } + + outboxCount := repository.CountRows("wallet_outbox", "event_type = ? AND user_id = ?", "UserResourceChanged", int64(42106)) + if _, err := svc.RevokeUserResource(ctx, resourcedomain.RevokeUserResourceCommand{ + RequestID: "request-revoke-host-badge-retry", + UserID: 42106, + EntitlementID: badgeEntitlementID, + Reason: "remove host badge retry", + OperatorUserID: 90003, + }); err != nil { + t.Fatalf("idempotent RevokeUserResource retry failed: %v", err) + } + if got := repository.CountRows("wallet_outbox", "event_type = ? AND user_id = ?", "UserResourceChanged", int64(42106)); got != outboxCount { + t.Fatalf("idempotent retry must not duplicate outbox facts: got %d want %d", got, outboxCount) + } +} + // TestRevokeResourceGroupGrantClampsWalletDebitWhenBalanceInsufficient 验证撤回金币时余额不足也不能扣成负数。 func TestRevokeResourceGroupGrantClampsWalletDebitWhenBalanceInsufficient(t *testing.T) { repository := mysqltest.NewRepository(t) @@ -5911,27 +6188,58 @@ func TestPurchaseResourceShopItemDebitsCoinAndGrantsEntitlement(t *testing.T) { t.Fatalf("create shop resource failed: %v", err) } shopItems, err := svc.UpsertResourceShopItems(ctx, resourcedomain.ResourceShopItemsCommand{ - Items: []resourcedomain.ResourceShopItemInput{{ - ResourceID: resource.ResourceID, - Status: resourcedomain.StatusActive, - DurationDays: resourcedomain.ShopDurationThreeDays, - SortOrder: 1, - }}, + Items: []resourcedomain.ResourceShopItemInput{ + { + ResourceID: resource.ResourceID, + Status: resourcedomain.StatusActive, + DurationDays: resourcedomain.ShopDurationOneDay, + SortOrder: 1, + }, + { + ResourceID: resource.ResourceID, + Status: resourcedomain.StatusActive, + DurationDays: resourcedomain.ShopDurationThreeDays, + CoinPrice: 250, + SortOrder: 2, + }, + { + ResourceID: resource.ResourceID, + Status: resourcedomain.StatusActive, + DurationDays: resourcedomain.ShopDurationSevenDays, + CoinPrice: 600, + SortOrder: 3, + }, + }, OperatorUserID: 90001, }) if err != nil { t.Fatalf("upsert shop item failed: %v", err) } + if len(shopItems) != 3 { + t.Fatalf("one resource should keep three sale durations, got %+v", shopItems) + } + var purchaseItem resourcedomain.ResourceShopItem + for _, item := range shopItems { + if item.DurationDays == resourcedomain.ShopDurationOneDay && item.CoinPrice != resource.CoinPrice { + t.Fatalf("omitted sale price should copy resource price: %+v", item) + } + if item.DurationDays == resourcedomain.ShopDurationThreeDays { + purchaseItem = item + } + } + if purchaseItem.ShopItemID == 0 || purchaseItem.CoinPrice != 250 { + t.Fatalf("custom three-day sale price mismatch: %+v", purchaseItem) + } receipt, err := svc.PurchaseResourceShopItem(ctx, resourcedomain.ResourceShopPurchaseCommand{ CommandID: "cmd-shop-badge", UserID: 53001, - ShopItemID: shopItems[0].ShopItemID, + ShopItemID: purchaseItem.ShopItemID, }) if err != nil { t.Fatalf("PurchaseResourceShopItem failed: %v", err) } - if receipt.OrderID == "" || receipt.TransactionID == "" || receipt.GrantID == "" || receipt.CoinSpent != 300 || receipt.Balance.AvailableAmount != 700 { + if receipt.OrderID == "" || receipt.TransactionID == "" || receipt.GrantID == "" || receipt.CoinSpent != 250 || receipt.Balance.AvailableAmount != 750 { t.Fatalf("resource shop purchase receipt mismatch: %+v", receipt) } if receipt.Resource.EntitlementID == "" || receipt.Resource.ResourceID != resource.ResourceID || receipt.Resource.ExpiresAtMS <= time.Now().UnixMilli() { @@ -5940,16 +6248,72 @@ func TestPurchaseResourceShopItemDebitsCoinAndGrantsEntitlement(t *testing.T) { if !receipt.Resource.Equipped { t.Fatalf("resource shop badge purchase should auto equip receipt resource: %+v", receipt.Resource) } + if _, err := svc.UpsertResourceShopItems(ctx, resourcedomain.ResourceShopItemsCommand{ + Items: []resourcedomain.ResourceShopItemInput{{ + ShopItemID: purchaseItem.ShopItemID, + ResourceID: resource.ResourceID, + Status: resourcedomain.StatusActive, + DurationDays: resourcedomain.ShopDurationThreeDays, + CoinPrice: 275, + SortOrder: 2, + }}, + OperatorUserID: 90001, + }); err != nil { + t.Fatalf("update shop item price failed: %v", err) + } + preservedItems, err := svc.UpsertResourceShopItems(ctx, resourcedomain.ResourceShopItemsCommand{ + Items: []resourcedomain.ResourceShopItemInput{{ + ShopItemID: purchaseItem.ShopItemID, + ResourceID: resource.ResourceID, + Status: resourcedomain.StatusActive, + DurationDays: resourcedomain.ShopDurationThreeDays, + SortOrder: 4, + }}, + OperatorUserID: 90002, + }) + if err != nil { + t.Fatalf("update shop item without price failed: %v", err) + } + var preservedPrice int64 + for _, item := range preservedItems { + if item.ShopItemID == purchaseItem.ShopItemID { + preservedPrice = item.CoinPrice + } + } + if preservedPrice != 275 { + t.Fatalf("omitted price on an existing item must preserve the custom price, got %d", preservedPrice) + } + naturalKeyItems, err := svc.UpsertResourceShopItems(ctx, resourcedomain.ResourceShopItemsCommand{ + Items: []resourcedomain.ResourceShopItemInput{{ + ResourceID: resource.ResourceID, + Status: resourcedomain.StatusActive, + DurationDays: resourcedomain.ShopDurationThreeDays, + SortOrder: 5, + }}, + OperatorUserID: 90003, + }) + if err != nil { + t.Fatalf("update shop item by natural key without price failed: %v", err) + } + preservedPrice = 0 + for _, item := range naturalKeyItems { + if item.ShopItemID == purchaseItem.ShopItemID { + preservedPrice = item.CoinPrice + } + } + if preservedPrice != 275 { + t.Fatalf("natural-key update without price must preserve the custom price, got %d", preservedPrice) + } again, err := svc.PurchaseResourceShopItem(ctx, resourcedomain.ResourceShopPurchaseCommand{ CommandID: "cmd-shop-badge", UserID: 53001, - ShopItemID: shopItems[0].ShopItemID, + ShopItemID: purchaseItem.ShopItemID, }) if err != nil { t.Fatalf("PurchaseResourceShopItem retry failed: %v", err) } - if again.OrderID != receipt.OrderID || again.TransactionID != receipt.TransactionID || again.Balance.AvailableAmount != receipt.Balance.AvailableAmount { + if again.OrderID != receipt.OrderID || again.TransactionID != receipt.TransactionID || again.Balance.AvailableAmount != receipt.Balance.AvailableAmount || again.ShopItem.CoinPrice != receipt.CoinSpent { t.Fatalf("resource shop idempotency mismatch: first=%+v again=%+v", receipt, again) } if got := repository.CountRows("resource_shop_purchase_orders", "user_id = ?", int64(53001)); got != 1 { @@ -5958,7 +6322,7 @@ func TestPurchaseResourceShopItemDebitsCoinAndGrantsEntitlement(t *testing.T) { if got := repository.CountRows("wallet_transactions", "command_id = ? AND biz_type = ?", "cmd-shop-badge", "resource_shop_purchase"); got != 1 { t.Fatalf("resource shop purchase should write one wallet transaction, got %d", got) } - if got := repository.CountRows("wallet_entries", "transaction_id = ? AND available_delta = ?", receipt.TransactionID, int64(-300)); got != 1 { + if got := repository.CountRows("wallet_entries", "transaction_id = ? AND available_delta = ?", receipt.TransactionID, int64(-250)); got != 1 { t.Fatalf("resource shop purchase should write one debit entry, got %d", got) } if got := repository.CountRows("resource_grants", "grant_id = ?", receipt.GrantID); got != 1 { @@ -6656,6 +7020,9 @@ func TestPurchaseVipDebitsCoinAndGrantsReward(t *testing.T) { if receipt.OrderID == "" || receipt.TransactionID == "" || receipt.CoinSpent != 1000 || receipt.CoinBalanceAfter != 19000 { t.Fatalf("vip receipt mismatch: %+v", receipt) } + if receipt.CoinBalance.AssetType != ledger.AssetCoin || receipt.CoinBalance.AvailableAmount != 19000 || receipt.CoinBalance.FrozenAmount != 0 || receipt.CoinBalance.Version <= 0 { + t.Fatalf("vip purchase must return versioned coin balance: %+v", receipt.CoinBalance) + } if !receipt.Vip.Active || receipt.Vip.Level != 1 || receipt.Vip.ExpiresAtMS <= receipt.Vip.StartedAtMS { t.Fatalf("vip membership mismatch: %+v", receipt.Vip) } @@ -6680,7 +7047,7 @@ func TestPurchaseVipDebitsCoinAndGrantsReward(t *testing.T) { if err != nil { t.Fatalf("PurchaseVip retry failed: %v", err) } - if again.OrderID != receipt.OrderID || again.CoinBalanceAfter != receipt.CoinBalanceAfter { + if again.OrderID != receipt.OrderID || again.CoinBalanceAfter != receipt.CoinBalanceAfter || again.CoinBalance.Version != receipt.CoinBalance.Version { t.Fatalf("vip idempotency mismatch: first=%+v again=%+v", receipt, again) } if _, err := svc.PurchaseVip(context.Background(), ledger.PurchaseVipCommand{ @@ -6709,6 +7076,14 @@ func TestPurchaseVipDebitsCoinAndGrantsReward(t *testing.T) { if !xerr.IsCode(err, xerr.VIPDowngradeNotAllowed) { t.Fatalf("expected VIP_DOWNGRADE_NOT_ALLOWED, got %v", err) } + _, err = svc.PurchaseVip(context.Background(), ledger.PurchaseVipCommand{ + CommandID: "cmd-vip-insufficient", + UserID: 51002, + Level: 1, + }) + if !xerr.IsCode(err, xerr.VIPInsufficientCoin) { + t.Fatalf("expected VIP_INSUFFICIENT_COIN, got %v", err) + } } func TestPurchaseVipRenewalAlignsRewardEntitlementExpiry(t *testing.T) { diff --git a/services/wallet-service/internal/service/wallet/vip.go b/services/wallet-service/internal/service/wallet/vip.go index 751fe8d4..2e290bfc 100644 --- a/services/wallet-service/internal/service/wallet/vip.go +++ b/services/wallet-service/internal/service/wallet/vip.go @@ -230,10 +230,12 @@ func (s *Service) UpdateAdminVipProgramConfig(ctx context.Context, command ledge return s.repository.UpdateAdminVipProgramConfig(ctx, command) } -// UpdateVipUserSettings 保存用户可关闭的 VIP 通知偏好。用户当前没有 VIP 也允许保存, +// UpdateVipUserSettings 保存用户可关闭的 VIP 展示与隐私偏好。用户当前没有 VIP 也允许保存, // 但偏好不会授予权益;实际执行仍由 CheckVipBenefit 同时校验 effective benefit。 func (s *Service) UpdateVipUserSettings(ctx context.Context, command ledger.UpdateVipUserSettingsCommand) (ledger.VipUserSettings, error) { - if command.UserID <= 0 || (command.RoomEntryNoticeEnabled == nil && command.OnlineGlobalNoticeEnabled == nil) { + if command.UserID <= 0 || (command.RoomEntryNoticeEnabled == nil && command.OnlineGlobalNoticeEnabled == nil && + command.HideProfileDataEnabled == nil && command.AnonymousProfileVisitEnabled == nil && + command.LeaderboardInvisibleEnabled == nil) { return ledger.VipUserSettings{}, xerr.New(xerr.InvalidArgument, "vip user settings update is incomplete") } if s.repository == nil { diff --git a/services/wallet-service/internal/service/wallet/vip_configurable_integration_test.go b/services/wallet-service/internal/service/wallet/vip_configurable_integration_test.go index 016f9d05..72f7ab9e 100644 --- a/services/wallet-service/internal/service/wallet/vip_configurable_integration_test.go +++ b/services/wallet-service/internal/service/wallet/vip_configurable_integration_test.go @@ -144,7 +144,7 @@ func TestFamiVIPReplaceAndTrialCardSwitch(t *testing.T) { if _, err := service.EquipUserResource(ctx, resourcedomain.EquipUserResourceCommand{ AppCode: "fami", RequestID: "generic-equip-disabled", UserID: userID, ResourceID: card3.TrialCard.ResourceID, EntitlementID: card3.TrialCard.EntitlementID, - }); !xerr.IsCode(err, xerr.Conflict) { + }); !xerr.IsCode(err, xerr.VIPProgramInactive) { t.Fatalf("generic backpack equip must preserve trial_card_enabled validation, got %v", err) } if got := repository.CountRows("user_resource_equipment", "app_code = ? AND user_id = ? AND resource_type = ?", "fami", userID, resourcedomain.TypeVIPTrialCard); got != 0 { @@ -270,6 +270,19 @@ func TestFamiVIPReplaceAndTrialCardSwitch(t *testing.T) { if err != nil || !paidRebate.Allowed { t.Fatalf("paid VIP6 must retain configured rebate benefit: allowed=%v err=%v result=%+v", paidRebate.Allowed, err, paidRebate) } + + // 体验卡错误必须稳定区分“实例不存在”和“绝对时间已过期”,Flutter 不解析 message 猜分支。 + if _, _, err := service.EquipVipTrialCard(ctx, ledger.EquipVipTrialCardCommand{ + AppCode: "fami", RequestID: "equip-missing-trial", UserID: userID, EntitlementID: "missing-entitlement", + }); !xerr.IsCode(err, xerr.VIPTrialCardNotFound) { + t.Fatalf("missing trial card must return VIP_TRIAL_CARD_NOT_FOUND, got %v", err) + } + repository.ExpireEntitlement(card6.TrialCard.EntitlementID, time.Now().Add(-time.Minute).UnixMilli()) + if _, _, err := service.EquipVipTrialCard(ctx, ledger.EquipVipTrialCardCommand{ + AppCode: "fami", RequestID: "equip-expired-trial", UserID: userID, EntitlementID: card6.TrialCard.EntitlementID, + }); !xerr.IsCode(err, xerr.VIPTrialCardExpired) { + t.Fatalf("expired trial card must return VIP_TRIAL_CARD_EXPIRED, got %v", err) + } } // TestVipPurchaseConcurrentReplayWithExactBalance 验证幂等守卫发生在账户/会员锁之前: @@ -309,6 +322,9 @@ func TestVipPurchaseConcurrentReplayWithExactBalance(t *testing.T) { if first.receipt.CoinBalanceAfter != 0 || second.receipt.CoinBalanceAfter != 0 { t.Fatalf("idempotent purchase must debit exact balance once: first=%d second=%d", first.receipt.CoinBalanceAfter, second.receipt.CoinBalanceAfter) } + if first.receipt.CoinBalance.Version <= 0 || first.receipt.CoinBalance.Version != second.receipt.CoinBalance.Version { + t.Fatalf("idempotent purchase must preserve original balance version: first=%+v second=%+v", first.receipt.CoinBalance, second.receipt.CoinBalance) + } if got := repository.CountRows("vip_purchase_orders", "app_code = ? AND command_id = ?", "lalu", commandID); got != 1 { t.Fatalf("concurrent replay persisted %d VIP orders, want 1", got) } @@ -399,7 +415,7 @@ func TestVipProgramCanCreateAndResizeAppLevels(t *testing.T) { } repository.SetBalanceForApp("future_app", 880002, 1_000) _, err = service.PurchaseVip(ctx, ledger.PurchaseVipCommand{AppCode: "future_app", CommandID: "buy-hidden-level", UserID: 880002, Level: 3}) - if !xerr.IsCode(err, xerr.VIPLevelNotFound) { + if !xerr.IsCode(err, xerr.VIPPackageNotPurchasable) { t.Fatalf("level above current level_count must be unreachable, got %v", err) } } diff --git a/services/wallet-service/internal/service/wallet/vip_user_settings_integration_test.go b/services/wallet-service/internal/service/wallet/vip_user_settings_integration_test.go index 96168131..62fb6c06 100644 --- a/services/wallet-service/internal/service/wallet/vip_user_settings_integration_test.go +++ b/services/wallet-service/internal/service/wallet/vip_user_settings_integration_test.go @@ -24,7 +24,9 @@ func TestVipUserSettingsDefaultPartialUpdateAndAppScope(t *testing.T) { if err != nil { t.Fatalf("get default VIP settings failed: %v", err) } - if !defaultState.UserSettings.RoomEntryNoticeEnabled || !defaultState.UserSettings.OnlineGlobalNoticeEnabled || defaultState.UserSettings.UpdatedAtMS != 0 { + if !defaultState.UserSettings.RoomEntryNoticeEnabled || !defaultState.UserSettings.OnlineGlobalNoticeEnabled || + !defaultState.UserSettings.HideProfileDataEnabled || !defaultState.UserSettings.AnonymousProfileVisitEnabled || + !defaultState.UserSettings.LeaderboardInvisibleEnabled || defaultState.UserSettings.UpdatedAtMS != 0 { t.Fatalf("missing settings row must project default enabled: %+v", defaultState.UserSettings) } if got := repository.CountRows("user_vip_settings", "app_code = ? AND user_id = ?", "fami", paidUserID); got != 0 { @@ -38,6 +40,13 @@ func TestVipUserSettingsDefaultPartialUpdateAndAppScope(t *testing.T) { if err != nil || settings.RoomEntryNoticeEnabled || !settings.OnlineGlobalNoticeEnabled || settings.UpdatedAtMS <= 0 { t.Fatalf("first partial settings update mismatch: settings=%+v err=%v", settings, err) } + hideProfileOff := false + settings, err = service.UpdateVipUserSettings(famiCtx, ledger.UpdateVipUserSettingsCommand{ + AppCode: "fami", UserID: paidUserID, HideProfileDataEnabled: &hideProfileOff, + }) + if err != nil || settings.HideProfileDataEnabled || !settings.AnonymousProfileVisitEnabled || !settings.LeaderboardInvisibleEnabled { + t.Fatalf("privacy partial update must preserve other switches: settings=%+v err=%v", settings, err) + } onlineOff := false settings, err = service.UpdateVipUserSettings(famiCtx, ledger.UpdateVipUserSettingsCommand{ AppCode: "fami", UserID: paidUserID, OnlineGlobalNoticeEnabled: &onlineOff, @@ -46,7 +55,9 @@ func TestVipUserSettingsDefaultPartialUpdateAndAppScope(t *testing.T) { t.Fatalf("second partial update must preserve room switch: settings=%+v err=%v", settings, err) } laluState, err := service.GetVipState(laluCtx, paidUserID) - if err != nil || !laluState.UserSettings.RoomEntryNoticeEnabled || !laluState.UserSettings.OnlineGlobalNoticeEnabled || laluState.UserSettings.UpdatedAtMS != 0 { + if err != nil || !laluState.UserSettings.RoomEntryNoticeEnabled || !laluState.UserSettings.OnlineGlobalNoticeEnabled || + !laluState.UserSettings.HideProfileDataEnabled || !laluState.UserSettings.AnonymousProfileVisitEnabled || + !laluState.UserSettings.LeaderboardInvisibleEnabled || laluState.UserSettings.UpdatedAtMS != 0 { t.Fatalf("same user settings must remain App scoped: state=%+v err=%v", laluState.UserSettings, err) } @@ -98,6 +109,10 @@ func TestVipUserSettingsDefaultPartialUpdateAndAppScope(t *testing.T) { t.Fatalf("paid VIP user setting gate mismatch for %s: result=%+v err=%v", code, result, checkErr) } } + hideProfileCheck, err := service.CheckVipBenefit(famiCtx, paidUserID, ledger.VipBenefitCodeHideProfileData) + if err != nil || hideProfileCheck.Allowed || hideProfileCheck.DenialReason != "user_setting_disabled" { + t.Fatalf("hide profile setting gate mismatch: result=%+v err=%v", hideProfileCheck, err) + } roomOn := true settings, err = service.UpdateVipUserSettings(famiCtx, ledger.UpdateVipUserSettingsCommand{ AppCode: "fami", UserID: paidUserID, RoomEntryNoticeEnabled: &roomOn, diff --git a/services/wallet-service/internal/storage/mysql/resource_entitlement_repository.go b/services/wallet-service/internal/storage/mysql/resource_entitlement_repository.go index 85d5c16b..ab460f1c 100644 --- a/services/wallet-service/internal/storage/mysql/resource_entitlement_repository.go +++ b/services/wallet-service/internal/storage/mysql/resource_entitlement_repository.go @@ -8,6 +8,7 @@ import ( "fmt" "hyapp/pkg/appcode" "hyapp/pkg/xerr" + "hyapp/services/wallet-service/internal/domain/ledger" resourcedomain "hyapp/services/wallet-service/internal/domain/resource" "math" "strings" @@ -63,6 +64,109 @@ func (r *Repository) ListUserResources(ctx context.Context, query resourcedomain return items, rows.Err() } +// RevokeUserResource forcibly invalidates exactly one entitlement. It deliberately does not mutate +// the source grant because a resource-group grant can contain sibling assets that must stay active. +func (r *Repository) RevokeUserResource(ctx context.Context, command resourcedomain.RevokeUserResourceCommand) (resourcedomain.UserResourceEntitlement, error) { + if r == nil || r.db == nil { + return resourcedomain.UserResourceEntitlement{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + ctx = contextWithCommandApp(ctx, command.AppCode) + command.AppCode = appcode.FromContext(ctx) + command.RequestID = strings.TrimSpace(command.RequestID) + command.EntitlementID = strings.TrimSpace(command.EntitlementID) + command.Reason = strings.TrimSpace(command.Reason) + if command.UserID <= 0 || command.EntitlementID == "" || command.Reason == "" || command.OperatorUserID <= 0 { + return resourcedomain.UserResourceEntitlement{}, xerr.New(xerr.InvalidArgument, "user resource revoke command is incomplete") + } + + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return resourcedomain.UserResourceEntitlement{}, err + } + defer func() { _ = tx.Rollback() }() + + entitlement, err := r.getUserResourceEntitlementForUpdateTx(ctx, tx, command.EntitlementID) + if err != nil { + return resourcedomain.UserResourceEntitlement{}, err + } + if entitlement.UserID != command.UserID { + // Do not reveal that another user's entitlement exists when a mismatched user path is supplied. + return resourcedomain.UserResourceEntitlement{}, xerr.New(xerr.NotFound, "user resource entitlement not found") + } + + nowMs := time.Now().UnixMilli() + changed := entitlement.Status == resourcedomain.StatusActive || entitlement.RemainingQuantity > 0 + if changed { + result, err := tx.ExecContext(ctx, ` + UPDATE user_resource_entitlements + SET status = ?, remaining_quantity = 0, updated_at_ms = ? + WHERE app_code = ? AND entitlement_id = ? AND user_id = ?`, + resourcedomain.GrantStatusRevoked, nowMs, command.AppCode, command.EntitlementID, command.UserID, + ) + if err != nil { + return resourcedomain.UserResourceEntitlement{}, err + } + affected, err := result.RowsAffected() + if err != nil { + return resourcedomain.UserResourceEntitlement{}, err + } + if affected != 1 { + return resourcedomain.UserResourceEntitlement{}, xerr.New(xerr.LedgerConflict, "user resource revoke state conflict") + } + } + + // Removing equipment is part of the same transaction as entitlement invalidation, so clients can + // never observe a revoked badge/frame still selected as the user's current appearance. + if _, err := tx.ExecContext(ctx, ` + DELETE FROM user_resource_equipment + WHERE app_code = ? AND user_id = ? AND entitlement_id = ?`, + command.AppCode, command.UserID, command.EntitlementID, + ); err != nil { + return resourcedomain.UserResourceEntitlement{}, err + } + if _, err := tx.ExecContext(ctx, ` + UPDATE user_vip_trial_cards + SET status = ?, updated_at_ms = ? + WHERE app_code = ? AND user_id = ? AND entitlement_id = ? AND status = ?`, + ledger.VipTrialCardStatusRevoked, nowMs, command.AppCode, command.UserID, + command.EntitlementID, ledger.VipTrialCardStatusActive, + ); err != nil { + return resourcedomain.UserResourceEntitlement{}, err + } + + if changed { + eventCommandID := "revoke-user-resource:" + stableHash(fmt.Sprintf("%s|%d|%s", command.AppCode, command.UserID, command.EntitlementID)) + if err := r.insertWalletOutbox(ctx, tx, []walletOutboxEvent{ + resourceOutboxEvent("UserResourceChanged", eventCommandID, command.UserID, entitlement.ResourceID, map[string]any{ + "action": "revoke", + "app_code": command.AppCode, + "user_id": command.UserID, + "resource_id": entitlement.ResourceID, + "resource_type": entitlement.Resource.ResourceType, + "entitlement_id": command.EntitlementID, + "source_grant_id": entitlement.SourceGrantID, + "status": resourcedomain.GrantStatusRevoked, + "remaining_quantity": 0, + "revoked_by_user_id": command.OperatorUserID, + "revoke_reason": command.Reason, + "updated_at_ms": nowMs, + "event_command": eventCommandID, + }, nowMs), + }); err != nil { + return resourcedomain.UserResourceEntitlement{}, err + } + } + + revoked, err := r.getUserResourceEntitlementTx(ctx, tx, command.EntitlementID) + if err != nil { + return resourcedomain.UserResourceEntitlement{}, err + } + if err := tx.Commit(); err != nil { + return resourcedomain.UserResourceEntitlement{}, err + } + return revoked, nil +} + func (r *Repository) EquipUserResource(ctx context.Context, command resourcedomain.EquipUserResourceCommand) (resourcedomain.UserResourceEntitlement, error) { if r == nil || r.db == nil { return resourcedomain.UserResourceEntitlement{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") @@ -268,7 +372,7 @@ func (r *Repository) BatchGetUserEquippedResources(ctx context.Context, query re return result, nil } -func (r *Repository) applyEntitlement(ctx context.Context, tx *sql.Tx, userID int64, resource resourcedomain.Resource, quantity int64, durationMS int64, grantID string, nowMs int64, snapshot resourceEntitlementSnapshot) (string, error) { +func (r *Repository) applyEntitlement(ctx context.Context, tx *sql.Tx, userID int64, resource resourcedomain.Resource, quantity int64, durationMS int64, grantID string, nowMs int64, strategyOverride string, snapshot resourceEntitlementSnapshot) (string, error) { if snapshot.SourceSnapshotID != "" { if !validSHA256(snapshot.ResourceSnapshotHash) || strings.TrimSpace(snapshot.ResourceSnapshotJSON) == "" { return "", xerr.New(xerr.Internal, "pinned entitlement resource snapshot is incomplete") @@ -294,7 +398,13 @@ func (r *Repository) applyEntitlement(ctx context.Context, tx *sql.Tx, userID in } expiresAt = nowMs + durationMS } - strategy := resourcedomain.NormalizeGrantStrategy(resource.GrantStrategy) + strategy := resourcedomain.NormalizeGrantStrategy(strategyOverride) + if strategy == "" { + strategy = resourcedomain.NormalizeGrantStrategy(resource.GrantStrategy) + } else if !resourcedomain.ValidGrantStrategy(strategy) { + // 覆盖策略只允许由 owner service 的专用业务入口传入;无效值属于服务端编排错误,不能静默回退目录配置。 + return "", xerr.New(xerr.Internal, "entitlement strategy override is invalid") + } if strategy == resourcedomain.GrantStrategyExtendExpiry || strategy == resourcedomain.GrantStrategyIncreaseQuantity || strategy == resourcedomain.GrantStrategySetActiveFlag { existing, exists, err := r.queryActiveEntitlementForUpdate(ctx, tx, userID, resource.ResourceID, snapshot.ResourceSnapshotHash, snapshot.GiftSnapshotHash, nowMs) if err != nil { @@ -306,6 +416,10 @@ func (r *Repository) applyEntitlement(ctx context.Context, tx *sql.Tx, userID in newExpiresAt := existing.ExpiresAtMS switch strategy { case resourcedomain.GrantStrategyExtendExpiry: + if strategyOverride != "" && durationMS > 0 && existing.ExpiresAtMS == 0 { + // 商城不能向永久权益继续出售有限天数:合并后无法区分永久与付费时长的撤销贡献,直接拒绝并回滚扣费。 + return "", xerr.New(xerr.Conflict, "resource is already permanently owned") + } newRemaining += quantity newQuantity += quantity if durationMS > 0 { @@ -314,7 +428,7 @@ func (r *Repository) applyEntitlement(ctx context.Context, tx *sql.Tx, userID in return "", xerr.New(xerr.InvalidArgument, "duration overflow") } newExpiresAt = base + durationMS - } else { + } else if durationMS == 0 { newExpiresAt = 0 } case resourcedomain.GrantStrategyIncreaseQuantity: diff --git a/services/wallet-service/internal/storage/mysql/resource_grant_repository.go b/services/wallet-service/internal/storage/mysql/resource_grant_repository.go index 81f998b5..1a2ce542 100644 --- a/services/wallet-service/internal/storage/mysql/resource_grant_repository.go +++ b/services/wallet-service/internal/storage/mysql/resource_grant_repository.go @@ -240,7 +240,7 @@ func (r *Repository) GrantPinnedResourceGroup(ctx context.Context, command resou return resourcedomain.ResourceGrant{}, err } if _, err := r.applyGrantItemWithEntitlementSnapshot(ctx, tx, grantID, command.CommandID, command.TargetUserID, - item.Resource, item.Quantity, item.DurationMS, nowMS, resourceEntitlementSnapshot{ + item.Resource, item.Quantity, item.DurationMS, nowMS, "", resourceEntitlementSnapshot{ SourceSnapshotID: snapshot.SnapshotID, ResourceSnapshotHash: resourceSnapshotHash, ResourceSnapshotJSON: string(resourceSnapshotJSON), GiftSnapshotHash: giftSnapshotHash, GiftSnapshotJSON: giftSnapshotJSON, @@ -430,7 +430,13 @@ func (r *Repository) GetResourceGrant(ctx context.Context, grantID string) (reso } func (r *Repository) applyGrantItem(ctx context.Context, tx *sql.Tx, grantID string, commandID string, targetUserID int64, resource resourcedomain.Resource, quantity int64, durationMS int64, nowMs int64) (resourcedomain.ResourceGrantItem, error) { - return r.applyGrantItemWithEntitlementSnapshot(ctx, tx, grantID, commandID, targetUserID, resource, quantity, durationMS, nowMs, resourceEntitlementSnapshot{}) + return r.applyGrantItemWithEntitlementSnapshot(ctx, tx, grantID, commandID, targetUserID, resource, quantity, durationMS, nowMs, "", resourceEntitlementSnapshot{}) +} + +// applyGrantItemWithEntitlementStrategy 只覆盖本次发放如何合并用户权益,不改资源目录或 grant item +// 的资源快照。商城售卖的是明确时长,因此需要固定为续期语义,同时保留资源在其他发放场景中的原策略。 +func (r *Repository) applyGrantItemWithEntitlementStrategy(ctx context.Context, tx *sql.Tx, grantID string, commandID string, targetUserID int64, resource resourcedomain.Resource, quantity int64, durationMS int64, nowMs int64, entitlementStrategy string) (resourcedomain.ResourceGrantItem, error) { + return r.applyGrantItemWithEntitlementSnapshot(ctx, tx, grantID, commandID, targetUserID, resource, quantity, durationMS, nowMs, entitlementStrategy, resourceEntitlementSnapshot{}) } type resourceEntitlementSnapshot struct { @@ -441,7 +447,7 @@ type resourceEntitlementSnapshot struct { GiftSnapshotJSON string } -func (r *Repository) applyGrantItemWithEntitlementSnapshot(ctx context.Context, tx *sql.Tx, grantID string, commandID string, targetUserID int64, resource resourcedomain.Resource, quantity int64, durationMS int64, nowMs int64, entitlementSnapshot resourceEntitlementSnapshot) (resourcedomain.ResourceGrantItem, error) { +func (r *Repository) applyGrantItemWithEntitlementSnapshot(ctx context.Context, tx *sql.Tx, grantID string, commandID string, targetUserID int64, resource resourcedomain.Resource, quantity int64, durationMS int64, nowMs int64, entitlementStrategy string, entitlementSnapshot resourceEntitlementSnapshot) (resourcedomain.ResourceGrantItem, error) { if quantity <= 0 { return resourcedomain.ResourceGrantItem{}, xerr.New(xerr.InvalidArgument, "quantity must be positive") } @@ -509,7 +515,7 @@ func (r *Repository) applyGrantItemWithEntitlementSnapshot(ctx context.Context, item.ResultType = resourcedomain.ResultWalletCredit item.WalletTransactionID = transactionID } else { - entitlementID, err := r.applyEntitlement(ctx, tx, targetUserID, resource, quantity, durationMS, grantID, nowMs, entitlementSnapshot) + entitlementID, err := r.applyEntitlement(ctx, tx, targetUserID, resource, quantity, durationMS, grantID, nowMs, entitlementStrategy, entitlementSnapshot) if err != nil { return resourcedomain.ResourceGrantItem{}, err } diff --git a/services/wallet-service/internal/storage/mysql/resource_shop_repository.go b/services/wallet-service/internal/storage/mysql/resource_shop_repository.go index 46d8ac12..cfb9c540 100644 --- a/services/wallet-service/internal/storage/mysql/resource_shop_repository.go +++ b/services/wallet-service/internal/storage/mysql/resource_shop_repository.go @@ -3,17 +3,20 @@ package mysql import ( "context" "database/sql" + "encoding/json" "errors" "fmt" "hyapp/pkg/appcode" "hyapp/pkg/xerr" "hyapp/services/wallet-service/internal/domain/ledger" resourcedomain "hyapp/services/wallet-service/internal/domain/resource" + "sort" "strings" "time" ) -// ListResourceShopItems 返回 App 道具商店和后台配置共用的售卖视图;价格始终由资源一日价乘以售卖天数派生。 +// ListResourceShopItems 返回 App 道具商店和后台配置共用的售卖规格;价格优先取规格自己的持久值。 +// 滚动发布期间旧实例仍可能写出 0,这类行必须沿用旧版“资源价 × 天数”,不能误套新建规格的默认价。 func (r *Repository) ListResourceShopItems(ctx context.Context, query resourcedomain.ListResourceShopItemsQuery) ([]resourcedomain.ResourceShopItem, int64, error) { if r == nil || r.db == nil { return nil, 0, xerr.New(xerr.Unavailable, "mysql repository is not configured") @@ -90,7 +93,8 @@ func (r *Repository) ListResourceShopPurchaseOrders(ctx context.Context, query r return items, total, rows.Err() } -// UpsertResourceShopItems 批量添加或重配售卖资源;同一个资源在商店只保留一个当前售卖配置。 +// UpsertResourceShopItems 批量添加或重配售卖规格;同一资源可同时配置 1/3/7 天, +// 但相同资源和相同天数只能保留一个规格,购买端继续用独立 shop_item_id 选择具体档位。 func (r *Repository) UpsertResourceShopItems(ctx context.Context, command resourcedomain.ResourceShopItemsCommand) ([]resourcedomain.ResourceShopItem, error) { if r == nil || r.db == nil { return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") @@ -108,13 +112,29 @@ func (r *Repository) UpsertResourceShopItems(ctx context.Context, command resour defer func() { _ = tx.Rollback() }() nowMs := time.Now().UnixMilli() - resourceIDs := make([]int64, 0, len(command.Items)) - seen := make(map[int64]struct{}, len(command.Items)) - for _, item := range command.Items { - if _, exists := seen[item.ResourceID]; exists { - return nil, xerr.New(xerr.InvalidArgument, "resource shop contains duplicate resource") + items := append([]resourcedomain.ResourceShopItemInput(nil), command.Items...) + // 所有写事务统一按 resource_id 再按规格身份加锁。购买同样先锁资源再锁商品,避免改价与购买形成反向等待。 + sort.SliceStable(items, func(left, right int) bool { + if items[left].ResourceID != items[right].ResourceID { + return items[left].ResourceID < items[right].ResourceID } - seen[item.ResourceID] = struct{}{} + if items[left].ShopItemID != items[right].ShopItemID { + return items[left].ShopItemID < items[right].ShopItemID + } + return items[left].DurationDays < items[right].DurationDays + }) + resourceIDs := make([]int64, 0, len(items)) + type resourceShopTierKey struct { + resourceID int64 + durationDays int32 + } + seen := make(map[resourceShopTierKey]struct{}, len(items)) + for _, item := range items { + tierKey := resourceShopTierKey{resourceID: item.ResourceID, durationDays: item.DurationDays} + if _, exists := seen[tierKey]; exists { + return nil, xerr.New(xerr.InvalidArgument, "resource shop contains duplicate resource duration") + } + seen[tierKey] = struct{}{} resource, err := r.getResourceForUpdate(ctx, tx, item.ResourceID) if err != nil { return nil, err @@ -122,22 +142,69 @@ func (r *Repository) UpsertResourceShopItems(ctx context.Context, command resour if err := validateResourceShopResource(resource); err != nil { return nil, err } + if item.ShopItemID > 0 { + current, err := r.getResourceShopItemTx(ctx, tx, item.ShopItemID, true) + if err != nil { + return nil, err + } + // shop_item_id 是既有规格的稳定身份,只允许在同一资源内调整天数和价格,防止误把另一资源的条目搬过来。 + if current.ResourceID != item.ResourceID { + return nil, xerr.New(xerr.InvalidArgument, "resource shop item does not match resource") + } + // 旧管理端不会发送新增的 coin_price;更新已有规格时 0 必须保留当前售价,不能把自定义价重置为资源价。 + coinPrice := item.CoinPrice + if coinPrice == 0 { + coinPrice = current.CoinPrice + } + if _, err := tx.ExecContext(ctx, ` + UPDATE resource_shop_items + SET status = ?, duration_days = ?, coin_price = ?, effective_from_ms = ?, effective_to_ms = ?, + sort_order = ?, updated_by_user_id = ?, updated_at_ms = ? + WHERE app_code = ? AND shop_item_id = ?`, + item.Status, item.DurationDays, coinPrice, item.EffectiveFromMS, item.EffectiveToMS, + item.SortOrder, command.OperatorUserID, nowMs, command.AppCode, item.ShopItemID, + ); err != nil { + if isMySQLDuplicateError(err) { + return nil, xerr.New(xerr.Conflict, "resource shop duration already exists") + } + return nil, err + } + resourceIDs = append(resourceIDs, item.ResourceID) + continue + } + // 新规格未传价格时复制资源列表价一次;落库后规格价格独立,不随资源目录调价变化。 + coinPrice := item.CoinPrice + if coinPrice == 0 { + current, exists, err := r.getResourceShopItemByTierTx(ctx, tx, item.ResourceID, item.DurationDays, true) + if err != nil { + return nil, err + } + if exists { + // 兼容未发送 shop_item_id 的旧调用:自然键已存在时 0 表示未提供价格,必须保留当前售价。 + coinPrice = current.CoinPrice + } else { + coinPrice = resource.CoinPrice + } + } if _, err := tx.ExecContext(ctx, ` INSERT INTO resource_shop_items ( - app_code, resource_id, status, duration_days, effective_from_ms, effective_to_ms, sort_order, + app_code, resource_id, status, duration_days, coin_price, effective_from_ms, effective_to_ms, sort_order, created_by_user_id, updated_by_user_id, created_at_ms, updated_at_ms - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE status = VALUES(status), - duration_days = VALUES(duration_days), + coin_price = VALUES(coin_price), effective_from_ms = VALUES(effective_from_ms), effective_to_ms = VALUES(effective_to_ms), sort_order = VALUES(sort_order), updated_by_user_id = VALUES(updated_by_user_id), updated_at_ms = VALUES(updated_at_ms)`, - command.AppCode, item.ResourceID, item.Status, item.DurationDays, item.EffectiveFromMS, item.EffectiveToMS, item.SortOrder, + command.AppCode, item.ResourceID, item.Status, item.DurationDays, coinPrice, item.EffectiveFromMS, item.EffectiveToMS, item.SortOrder, command.OperatorUserID, command.OperatorUserID, nowMs, nowMs, ); err != nil { + if isMySQLDuplicateError(err) { + return nil, xerr.New(xerr.Conflict, "resource shop duration already exists") + } return nil, err } resourceIDs = append(resourceIDs, item.ResourceID) @@ -167,7 +234,7 @@ func (r *Repository) SetResourceShopItemStatus(ctx context.Context, command reso } defer func() { _ = tx.Rollback() }() - item, err := r.getResourceShopItemTx(ctx, tx, command.ShopItemID, true) + item, err := r.lockResourceShopItemTx(ctx, tx, command.ShopItemID) if err != nil { return resourcedomain.ResourceShopItem{}, err } @@ -213,7 +280,9 @@ func (r *Repository) PurchaseResourceShopItem(ctx context.Context, command resou defer func() { _ = tx.Rollback() }() requestHash := resourceShopPurchaseRequestHash(command) - if txRow, exists, err := r.lookupTransaction(ctx, tx, command.CommandID, requestHash, bizTypeResourceShopPurchase); err != nil || exists { + // 首次查询不能对不存在的 command_id 加 gap lock:两笔不同订单随后会按资源行串行, + // 若各自先持有交易唯一键间隙,先拿到资源锁的事务在 INSERT 时可能与等待资源锁的事务形成死锁。 + if txRow, exists, err := r.lookupTransactionConsistent(ctx, tx, command.CommandID, requestHash, bizTypeResourceShopPurchase, xerr.LedgerConflict); err != nil || exists { if err != nil { return resourcedomain.ResourceShopPurchaseReceipt{}, err } @@ -221,7 +290,7 @@ func (r *Repository) PurchaseResourceShopItem(ctx context.Context, command resou } nowMs := time.Now().UnixMilli() - item, err := r.getResourceShopItemTx(ctx, tx, command.ShopItemID, true) + item, err := r.lockResourceShopItemTx(ctx, tx, command.ShopItemID) if err != nil { return resourcedomain.ResourceShopPurchaseReceipt{}, err } @@ -254,9 +323,16 @@ func (r *Repository) PurchaseResourceShopItem(ctx context.Context, command resou "price_type": item.PriceType, "coin_spent": item.CoinPrice, "balance_after": coinBalanceAfter, + "balance_version": account.Version + 1, "resource_grant_id": grantID, } if err := r.insertTransaction(ctx, tx, transactionID, command.CommandID, bizTypeResourceShopPurchase, requestHash, orderID, metadata, nowMs); err != nil { + if isMySQLDuplicateError(err) { + // 同 command_id 的并发首发都可能在一致性读阶段看不到未提交行;唯一键决定胜者, + // 败者必须回滚所有预备锁并重读胜者回执,不能重复扣费或把 duplicate 暴露成 500。 + _ = tx.Rollback() + return r.replayResourceShopPurchase(ctx, command, requestHash) + } return resourcedomain.ResourceShopPurchaseReceipt{}, err } if err := r.applyAccountDelta(ctx, tx, account, -item.CoinPrice, 0, nowMs); err != nil { @@ -277,7 +353,10 @@ func (r *Repository) PurchaseResourceShopItem(ctx context.Context, command resou if err := r.insertResourceGrant(ctx, tx, grantID, command.CommandID, command.UserID, resourcedomain.GrantSourceResourceShop, resourcedomain.GrantSubjectResource, fmt.Sprintf("%d", item.ResourceID), requestHash, "", "resource shop purchase", command.UserID, nowMs); err != nil { return resourcedomain.ResourceShopPurchaseReceipt{}, err } - grantItem, err := r.applyGrantItem(ctx, tx, grantID, command.CommandID, command.UserID, item.Resource, 1, durationMS, nowMs) + // 商城商品卖的是 duration_days 对应的使用时长,重复购买必须从当前到期时间继续累加, + // 不能受资源目录在活动、礼物等其他发放场景使用的 increase_quantity/new_entitlement 策略影响。 + // 同一资源的购买事务已由 lockResourceShopItemTx 锁住资源行,权益层再以 FOR UPDATE 合并,避免并发续期丢失时长。 + grantItem, err := r.applyGrantItemWithEntitlementStrategy(ctx, tx, grantID, command.CommandID, command.UserID, item.Resource, 1, durationMS, nowMs, resourcedomain.GrantStrategyExtendExpiry) if err != nil { return resourcedomain.ResourceShopPurchaseReceipt{}, err } @@ -299,6 +378,22 @@ func (r *Repository) PurchaseResourceShopItem(ctx context.Context, command resou if err != nil { return resourcedomain.ResourceShopPurchaseReceipt{}, err } + // 订单回执必须固化本次购买完成时的权益窗口;后续续期仍复用同一 entitlement, + // 若重放时直接读当前行,旧 command_id 会错误返回后续订单已经延长的到期时间和数量。 + metadata["entitlement_snapshot_version"] = 1 + metadata["entitlement_id"] = resource.EntitlementID + metadata["entitlement_status"] = resource.Status + metadata["entitlement_quantity"] = resource.Quantity + metadata["entitlement_remaining_quantity"] = resource.RemainingQuantity + metadata["entitlement_effective_at_ms"] = resource.EffectiveAtMS + metadata["entitlement_expires_at_ms"] = resource.ExpiresAtMS + metadata["entitlement_source_grant_id"] = resource.SourceGrantID + metadata["entitlement_created_at_ms"] = resource.CreatedAtMS + metadata["entitlement_updated_at_ms"] = resource.UpdatedAtMS + metadata["entitlement_equipped"] = resource.Equipped + if err := r.updateTransactionMetadata(ctx, tx, transactionID, metadata, nowMs); err != nil { + return resourcedomain.ResourceShopPurchaseReceipt{}, err + } if err := r.insertWalletOutbox(ctx, tx, []walletOutboxEvent{ balanceChangedEvent(transactionID, command.CommandID, command.UserID, ledger.AssetCoin, -item.CoinPrice, 0, coinBalanceAfter, account.FrozenAmount, account.Version+1, metadata, nowMs, bizTypeResourceShopPurchase), resourceOutboxEvent("ResourceGranted", command.CommandID, command.UserID, item.ResourceID, map[string]any{"grant_id": grantID, "resource": item.Resource, "source": resourcedomain.GrantSourceResourceShop}, nowMs), @@ -337,6 +432,24 @@ func (r *Repository) PurchaseResourceShopItem(ctx context.Context, command resou }, nil } +// replayResourceShopPurchase 在原事务回滚后读取已提交订单,供同 command_id 的并发请求稳定返回同一回执。 +func (r *Repository) replayResourceShopPurchase(ctx context.Context, command resourcedomain.ResourceShopPurchaseCommand, requestHash string) (resourcedomain.ResourceShopPurchaseReceipt, error) { + tx, err := r.db.BeginTx(ctx, &sql.TxOptions{ReadOnly: true, Isolation: sql.LevelRepeatableRead}) + if err != nil { + return resourcedomain.ResourceShopPurchaseReceipt{}, err + } + defer func() { _ = tx.Rollback() }() + + txRow, exists, err := r.lookupTransactionConsistent(ctx, tx, command.CommandID, requestHash, bizTypeResourceShopPurchase, xerr.LedgerConflict) + if err != nil { + return resourcedomain.ResourceShopPurchaseReceipt{}, err + } + if !exists { + return resourcedomain.ResourceShopPurchaseReceipt{}, xerr.New(xerr.Unavailable, "resource shop purchase idempotent receipt is not visible") + } + return r.resourceShopPurchaseReceiptForTransaction(ctx, tx, txRow.TransactionID, command.UserID) +} + func (r *Repository) getResourceShopItem(ctx context.Context, shopItemID int64) (resourcedomain.ResourceShopItem, error) { return r.getResourceShopItemWithQuerier(ctx, r.db, shopItemID, false) } @@ -345,6 +458,39 @@ func (r *Repository) getResourceShopItemTx(ctx context.Context, tx *sql.Tx, shop return r.getResourceShopItemWithQuerier(ctx, tx, shopItemID, lock) } +// lockResourceShopItemTx 先无锁定位不可变的 resource_id,再统一按“资源 -> 商品”顺序取写锁。 +// 改价、启停和购买都走这里,避免某条链路先锁商品、另一条链路先锁资源而形成循环等待。 +func (r *Repository) lockResourceShopItemTx(ctx context.Context, tx *sql.Tx, shopItemID int64) (resourcedomain.ResourceShopItem, error) { + candidate, err := r.getResourceShopItemTx(ctx, tx, shopItemID, false) + if err != nil { + return resourcedomain.ResourceShopItem{}, err + } + if _, err := r.getResourceForUpdate(ctx, tx, candidate.ResourceID); err != nil { + return resourcedomain.ResourceShopItem{}, err + } + item, err := r.getResourceShopItemTx(ctx, tx, shopItemID, true) + if err != nil { + return resourcedomain.ResourceShopItem{}, err + } + // resource_id 按业务约束不可变;若被旁路修改,不能在未锁定的新资源行上继续启停、改价或扣费。 + if item.ResourceID != candidate.ResourceID { + return resourcedomain.ResourceShopItem{}, xerr.New(xerr.Conflict, "resource shop item changed while locking") + } + return item, nil +} + +func (r *Repository) getResourceShopItemByTierTx(ctx context.Context, tx *sql.Tx, resourceID int64, durationDays int32, lock bool) (resourcedomain.ResourceShopItem, bool, error) { + query := resourceShopItemSelectSQL() + ` WHERE si.app_code = ? AND si.resource_id = ? AND si.duration_days = ?` + if lock { + query += ` FOR UPDATE` + } + item, err := scanResourceShopItem(tx.QueryRowContext(ctx, query, appcode.FromContext(ctx), resourceID, durationDays)) + if errors.Is(err, sql.ErrNoRows) { + return resourcedomain.ResourceShopItem{}, false, nil + } + return item, err == nil, err +} + func (r *Repository) getResourceShopItemWithQuerier(ctx context.Context, querier sqlRowQuerier, shopItemID int64, lock bool) (resourcedomain.ResourceShopItem, error) { query := resourceShopItemSelectSQL() + ` WHERE si.app_code = ? AND si.shop_item_id = ?` if lock { @@ -361,15 +507,19 @@ func (r *Repository) getResourceShopItemWithQuerier(ctx context.Context, querier func (r *Repository) resourceShopPurchaseReceiptForTransaction(ctx context.Context, tx *sql.Tx, transactionID string, userID int64) (resourcedomain.ResourceShopPurchaseReceipt, error) { var orderID string var shopItemID int64 + var durationDays int32 var priceCoin int64 var grantID string var entitlementID string + var metadataJSON string err := tx.QueryRowContext(ctx, ` - SELECT order_id, shop_item_id, price_coin, resource_grant_id, entitlement_id - FROM resource_shop_purchase_orders - WHERE app_code = ? AND wallet_transaction_id = ? AND user_id = ?`, + SELECT po.order_id, po.shop_item_id, po.duration_days, po.price_coin, + po.resource_grant_id, po.entitlement_id, COALESCE(CAST(wt.metadata_json AS CHAR), '{}') + FROM resource_shop_purchase_orders po + JOIN wallet_transactions wt ON wt.app_code = po.app_code AND wt.transaction_id = po.wallet_transaction_id + WHERE po.app_code = ? AND po.wallet_transaction_id = ? AND po.user_id = ?`, appcode.FromContext(ctx), transactionID, userID, - ).Scan(&orderID, &shopItemID, &priceCoin, &grantID, &entitlementID) + ).Scan(&orderID, &shopItemID, &durationDays, &priceCoin, &grantID, &entitlementID, &metadataJSON) if err != nil { return resourcedomain.ResourceShopPurchaseReceipt{}, err } @@ -377,18 +527,53 @@ func (r *Repository) resourceShopPurchaseReceiptForTransaction(ctx context.Conte if err != nil { return resourcedomain.ResourceShopPurchaseReceipt{}, err } + // 幂等重试必须返回原订单规格;运营在首单后改价或改配置时,不能让回执里的商品价格与 coin_spent 自相矛盾。 + item.DurationDays = durationDays + item.CoinPrice = priceCoin resource, err := r.getUserResourceEntitlementTx(ctx, tx, entitlementID) if err != nil { return resourcedomain.ResourceShopPurchaseReceipt{}, err } + var metadata struct { + EntitlementSnapshotVersion int `json:"entitlement_snapshot_version"` + EntitlementID string `json:"entitlement_id"` + EntitlementStatus string `json:"entitlement_status"` + EntitlementQuantity int64 `json:"entitlement_quantity"` + EntitlementRemaining int64 `json:"entitlement_remaining_quantity"` + EntitlementEffectiveAtMS int64 `json:"entitlement_effective_at_ms"` + EntitlementExpiresAtMS int64 `json:"entitlement_expires_at_ms"` + EntitlementSourceGrantID string `json:"entitlement_source_grant_id"` + EntitlementCreatedAtMS int64 `json:"entitlement_created_at_ms"` + EntitlementUpdatedAtMS int64 `json:"entitlement_updated_at_ms"` + EntitlementEquipped bool `json:"entitlement_equipped"` + BalanceVersion int64 `json:"balance_version"` + } + if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil { + return resourcedomain.ResourceShopPurchaseReceipt{}, err + } + if metadata.EntitlementSnapshotVersion > 0 && metadata.EntitlementID == entitlementID { + resource.Status = metadata.EntitlementStatus + resource.Quantity = metadata.EntitlementQuantity + resource.RemainingQuantity = metadata.EntitlementRemaining + resource.EffectiveAtMS = metadata.EntitlementEffectiveAtMS + resource.ExpiresAtMS = metadata.EntitlementExpiresAtMS + resource.SourceGrantID = metadata.EntitlementSourceGrantID + resource.CreatedAtMS = metadata.EntitlementCreatedAtMS + resource.UpdatedAtMS = metadata.EntitlementUpdatedAtMS + resource.Equipped = metadata.EntitlementEquipped + } balance, err := r.balanceAfterTransaction(ctx, tx, transactionID, userID, ledger.AssetCoin) if err != nil { return resourcedomain.ResourceShopPurchaseReceipt{}, err } - if account, exists, err := r.queryAccountForUpdate(ctx, tx, userID, ledger.AssetCoin); err != nil { + if metadata.BalanceVersion > 0 { + balance.Version = metadata.BalanceVersion + } else if err := tx.QueryRowContext(ctx, ` + SELECT version FROM wallet_accounts + WHERE app_code = ? AND user_id = ? AND asset_type = ?`, + appcode.FromContext(ctx), userID, ledger.AssetCoin, + ).Scan(&balance.Version); err != nil && !errors.Is(err, sql.ErrNoRows) { return resourcedomain.ResourceShopPurchaseReceipt{}, err - } else if exists { - balance.Version = account.Version } return resourcedomain.ResourceShopPurchaseReceipt{ OrderID: orderID, @@ -532,9 +717,9 @@ func scanResourceShopPurchaseOrder(scanner scanTarget) (resourcedomain.ResourceS func resourceShopItemSelectSQL() string { return ` - SELECT si.app_code, si.shop_item_id, si.resource_id, si.status, si.duration_days, - r.price_type, - CASE WHEN r.price_type = 'coin' THEN r.coin_price * si.duration_days ELSE 0 END AS coin_price, + SELECT si.app_code, si.shop_item_id, si.resource_id, si.status, si.duration_days, + r.price_type, + CASE WHEN si.coin_price > 0 THEN si.coin_price ELSE r.coin_price * si.duration_days END AS coin_price, si.effective_from_ms, si.effective_to_ms, si.sort_order, si.created_by_user_id, si.updated_by_user_id, si.created_at_ms, si.updated_at_ms, ` + resourceColumnsWithAlias("r") + ` @@ -651,6 +836,9 @@ func validateResourceShopItemsCommand(command resourcedomain.ResourceShopItemsCo if !resourcedomain.ValidShopDurationDays(item.DurationDays) { return xerr.New(xerr.InvalidArgument, "resource shop duration is invalid") } + if item.CoinPrice < 0 { + return xerr.New(xerr.InvalidArgument, "resource shop coin price is invalid") + } if item.EffectiveFromMS < 0 || item.EffectiveToMS < 0 || (item.EffectiveFromMS > 0 && item.EffectiveToMS > 0 && item.EffectiveToMS <= item.EffectiveFromMS) { return xerr.New(xerr.InvalidArgument, "resource shop effective time is invalid") } diff --git a/services/wallet-service/internal/storage/mysql/salary_withdrawal.go b/services/wallet-service/internal/storage/mysql/salary_withdrawal.go index 884c5721..96dc20ea 100644 --- a/services/wallet-service/internal/storage/mysql/salary_withdrawal.go +++ b/services/wallet-service/internal/storage/mysql/salary_withdrawal.go @@ -2,6 +2,8 @@ package mysql import ( "context" + "database/sql" + "encoding/json" "fmt" "strings" "time" @@ -61,6 +63,15 @@ func (r *Repository) applySalaryWithdrawal(ctx context.Context, command ledger.S } defer func() { _ = tx.Rollback() }() + // 财务旧版 command id 带 approved/rejected,新版按 finance stage 固定。在 command 幂等前先锁定提现申请的唯一终局, + // 才能让旧 command 成功但 admin 未终态的 partial-pending 重试返回原回执,且阻止另一个 command 执行相反决策。 + if receipt, exists, err := r.lookupSalaryWithdrawalTerminal(ctx, tx, command, mutation.BizType); err != nil || exists { + if err != nil || !exists { + return ledger.SalaryWithdrawalReceipt{}, err + } + return receipt, nil + } + requestHash := salaryWithdrawalRequestHash(command, mutation.BizType) if txRow, exists, err := r.lookupTransactionWithConflictCode(ctx, tx, command.CommandID, requestHash, mutation.BizType, xerr.IdempotencyConflict); err != nil || exists { if err != nil || !exists { @@ -129,6 +140,23 @@ func (r *Repository) applySalaryWithdrawal(ctx context.Context, command ledger.S } func salaryWithdrawalRequestHash(command ledger.SalaryWithdrawalCommand, bizType string) string { + if strings.TrimSpace(command.WithdrawalApplicationID) != "" && (bizType == bizTypeSalaryWithdrawalSettle || bizType == bizTypeSalaryWithdrawalRelease) { + // 审核人和备注是钱包 metadata 快照,不决定资金突变。将它们排除后,admin 事务失败换人/改备注重试仍命中原交易。 + // bizType 仍在哈希中,且 lookupSalaryWithdrawalTerminal 会在申请维度检查相反终局,settle/release 绝不能共存。 + return stableHash(fmt.Sprintf("salary_withdrawal_terminal|%s|%s|%d|%s|%d|%d|%d|%d|%d|%s", + bizType, + appcode.Normalize(command.AppCode), + command.UserID, + strings.ToUpper(strings.TrimSpace(command.SalaryAssetType)), + command.SalaryUSDMinor, + command.PointFeeAmount, + command.PointNetAmount, + command.PointsPerUSD, + command.PointWithdrawFeeBPS, + strings.TrimSpace(command.WithdrawalApplicationID), + )) + } + // 冻结和申请创建失败的回滚没有 application id,继续使用旧哈希保持已有 command 兼容。 return stableHash(fmt.Sprintf("salary_withdrawal|%s|%s|%d|%s|%d|%d|%d|%d|%d|%d|%s|%s|%s", bizType, appcode.Normalize(command.AppCode), @@ -145,3 +173,83 @@ func salaryWithdrawalRequestHash(command ledger.SalaryWithdrawalCommand, bizType strings.TrimSpace(command.WithdrawalApplicationID), )) } + +// lookupSalaryWithdrawalTerminal 先用小型主键锁表串行化同一申请,再使用 (app_code, external_ref) 现有索引查找旧/新终局。 +// InnoDB 纯 gap lock 之间可兼容,不能单独作为“未存在终局”的互斥;显式锁行使首次并发 settle/release 也只有一个能落账。 +func (r *Repository) lookupSalaryWithdrawalTerminal(ctx context.Context, tx *sql.Tx, command ledger.SalaryWithdrawalCommand, requestedBizType string) (ledger.SalaryWithdrawalReceipt, bool, error) { + applicationID := strings.TrimSpace(command.WithdrawalApplicationID) + if applicationID == "" || (requestedBizType != bizTypeSalaryWithdrawalSettle && requestedBizType != bizTypeSalaryWithdrawalRelease) { + return ledger.SalaryWithdrawalReceipt{}, false, nil + } + nowMS := time.Now().UTC().UnixMilli() + if _, err := tx.ExecContext(ctx, ` + INSERT INTO wallet_withdrawal_terminal_locks ( + app_code, withdrawal_application_id, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?) + ON DUPLICATE KEY UPDATE withdrawal_application_id = VALUES(withdrawal_application_id)`, + appcode.FromContext(ctx), applicationID, nowMS, nowMS, + ); err != nil { + return ledger.SalaryWithdrawalReceipt{}, false, err + } + rows, err := tx.QueryContext(ctx, ` + SELECT transaction_id, biz_type, COALESCE(CAST(metadata_json AS CHAR), '{}') + FROM wallet_transactions + WHERE app_code = ? + AND external_ref = ? + AND biz_type IN (?, ?) + ORDER BY created_at_ms ASC, transaction_id ASC + FOR UPDATE`, appcode.FromContext(ctx), applicationID, bizTypeSalaryWithdrawalSettle, bizTypeSalaryWithdrawalRelease) + if err != nil { + return ledger.SalaryWithdrawalReceipt{}, false, err + } + defer rows.Close() + + var terminal *struct { + TransactionID string + BizType string + Metadata salaryWithdrawalMetadata + } + for rows.Next() { + var transactionID string + var bizType string + var metadataJSON string + if err := rows.Scan(&transactionID, &bizType, &metadataJSON); err != nil { + return ledger.SalaryWithdrawalReceipt{}, false, err + } + if terminal != nil { + // 历史如果已经存在多个终局,钱包不能猜测哪个是真实决策,必须 fail closed 交由人工对账。 + return ledger.SalaryWithdrawalReceipt{}, true, xerr.New(xerr.IdempotencyConflict, "withdrawal application has multiple wallet terminal transactions") + } + var metadata salaryWithdrawalMetadata + if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil { + return ledger.SalaryWithdrawalReceipt{}, false, err + } + terminal = &struct { + TransactionID string + BizType string + Metadata salaryWithdrawalMetadata + }{TransactionID: transactionID, BizType: bizType, Metadata: metadata} + } + if err := rows.Err(); err != nil { + return ledger.SalaryWithdrawalReceipt{}, false, err + } + if terminal == nil { + return ledger.SalaryWithdrawalReceipt{}, false, nil + } + if terminal.BizType != requestedBizType || !salaryWithdrawalTerminalMatches(command, terminal.Metadata) { + return ledger.SalaryWithdrawalReceipt{}, true, xerr.New(xerr.IdempotencyConflict, "withdrawal application terminal idempotency conflict") + } + return receiptFromSalaryWithdrawalMetadata(terminal.TransactionID, terminal.Metadata), true, nil +} + +func salaryWithdrawalTerminalMatches(command ledger.SalaryWithdrawalCommand, metadata salaryWithdrawalMetadata) bool { + return appcode.Normalize(metadata.AppCode) == appcode.Normalize(command.AppCode) && + metadata.UserID == command.UserID && + strings.ToUpper(strings.TrimSpace(metadata.SalaryAssetType)) == strings.ToUpper(strings.TrimSpace(command.SalaryAssetType)) && + metadata.SalaryUSDMinor == command.SalaryUSDMinor && + metadata.PointFeeAmount == command.PointFeeAmount && + metadata.PointNetAmount == command.PointNetAmount && + metadata.PointsPerUSD == command.PointsPerUSD && + metadata.PointWithdrawFeeBPS == command.PointWithdrawFeeBPS && + strings.TrimSpace(metadata.WithdrawalApplicationID) == strings.TrimSpace(command.WithdrawalApplicationID) +} diff --git a/services/wallet-service/internal/storage/mysql/vip_admin_repository.go b/services/wallet-service/internal/storage/mysql/vip_admin_repository.go index 205456b7..ba5253ba 100644 --- a/services/wallet-service/internal/storage/mysql/vip_admin_repository.go +++ b/services/wallet-service/internal/storage/mysql/vip_admin_repository.go @@ -198,6 +198,13 @@ func normalizeAdminVipLevelCommands(levels []ledger.AdminVipLevelCommand, progra benefit.ResourceType = resourcedomain.NormalizeResourceType(benefit.ResourceType) benefit.ExecutionScope = strings.ToLower(strings.TrimSpace(benefit.ExecutionScope)) benefit.MetadataJSON = strings.TrimSpace(benefit.MetadataJSON) + // 后台可直接提交结构化 presentation;钱包仍把它与 coin_amount/message 等扩展字段 + // 原子保存在同一 JSON 列,避免展示配置出现双写版本。 + mergedMetadata, mergeErr := ledger.MergeVipBenefitPresentation(benefit.MetadataJSON, benefit.Presentation) + if mergeErr != nil { + return nil, xerr.New(xerr.InvalidArgument, "vip benefit presentation is invalid") + } + benefit.MetadataJSON = mergedMetadata // 体验卡永远不参与金币返现;保存时强制收敛,运行时仍会按编码再次兜底。 if benefit.BenefitCode == ledger.VipBenefitCodeDailyCoinRebate { benefit.TrialEnabled = false @@ -265,6 +272,9 @@ func (r *Repository) validateAdminVipBenefit(ctx context.Context, tx *sql.Tx, le if benefit.MetadataJSON != "" && !json.Valid([]byte(benefit.MetadataJSON)) { return xerr.New(xerr.InvalidArgument, "vip benefit metadata_json is invalid") } + if _, err := ledger.ParseVipBenefitPresentation(benefit.MetadataJSON); err != nil { + return xerr.New(xerr.InvalidArgument, "vip benefit presentation is invalid") + } if benefit.BenefitCode == ledger.VipBenefitCodeDailyCoinRebate { if benefit.ExecutionScope != ledger.VipExecutionScopeWallet { return xerr.New(xerr.InvalidArgument, "daily_coin_rebate execution_scope must be wallet") diff --git a/services/wallet-service/internal/storage/mysql/vip_program_repository.go b/services/wallet-service/internal/storage/mysql/vip_program_repository.go index 3a01a948..2598d73c 100644 --- a/services/wallet-service/internal/storage/mysql/vip_program_repository.go +++ b/services/wallet-service/internal/storage/mysql/vip_program_repository.go @@ -80,7 +80,7 @@ func (r *Repository) GetVipState(ctx context.Context, userID int64) (ledger.VipS func (r *Repository) requireVipProgramConfig(ctx context.Context, querier vipSnapshotQuerier) (ledger.VipProgramConfig, error) { config, err := r.queryVipProgramConfig(ctx, querier.QueryRowContext(ctx, vipProgramSelectSQL(), appcode.FromContext(ctx))) if errors.Is(err, sql.ErrNoRows) { - return ledger.VipProgramConfig{}, xerr.New(xerr.NotFound, "vip program config not found") + return ledger.VipProgramConfig{}, xerr.New(xerr.VIPProgramInactive, "vip program config not found") } return config, err } @@ -282,6 +282,11 @@ func scanVipBenefit(scanner vipProgramScanner) (ledger.VipBenefit, error) { if metadata.Valid { benefit.MetadataJSON = metadata.String } + if err == nil { + // presentation 是 metadata_json 的稳定结构化投影;读取时统一解析,HTTP/gRPC 调用方 + // 无需按 benefit_code 重复维护 JSON schema。 + benefit.Presentation, err = ledger.ParseVipBenefitPresentation(benefit.MetadataJSON) + } return benefit, err } diff --git a/services/wallet-service/internal/storage/mysql/vip_purchase_repository.go b/services/wallet-service/internal/storage/mysql/vip_purchase_repository.go index b5877ebc..eb5741d2 100644 --- a/services/wallet-service/internal/storage/mysql/vip_purchase_repository.go +++ b/services/wallet-service/internal/storage/mysql/vip_purchase_repository.go @@ -43,23 +43,26 @@ func (r *Repository) PurchaseVip(ctx context.Context, command ledger.PurchaseVip program, err := r.queryVipProgramConfig(ctx, tx.QueryRowContext(ctx, vipProgramSelectSQL()+` LOCK IN SHARE MODE`, command.AppCode)) if errors.Is(err, sql.ErrNoRows) { - return ledger.PurchaseVipReceipt{}, xerr.New(xerr.NotFound, "vip program config not found") + return ledger.PurchaseVipReceipt{}, xerr.New(xerr.VIPProgramInactive, "vip program config not found") } if err != nil { return ledger.PurchaseVipReceipt{}, err } if program.Status != ledger.VipStatusActive { - return ledger.PurchaseVipReceipt{}, xerr.New(xerr.Conflict, "vip program is disabled") + return ledger.PurchaseVipReceipt{}, xerr.New(xerr.VIPProgramInactive, "vip program is disabled") } if command.Level > program.LevelCount { - return ledger.PurchaseVipReceipt{}, xerr.New(xerr.VIPLevelNotFound, "vip level exceeds program level_count") + return ledger.PurchaseVipReceipt{}, xerr.New(xerr.VIPPackageNotPurchasable, "vip level exceeds program level_count") } level, err := r.getVipLevelForUpdate(ctx, tx, command.Level) if err != nil { + if xerr.IsCode(err, xerr.VIPLevelNotFound) { + return ledger.PurchaseVipReceipt{}, xerr.New(xerr.VIPPackageNotPurchasable, "vip package not found") + } return ledger.PurchaseVipReceipt{}, err } if level.Status != ledger.VipStatusActive { - return ledger.PurchaseVipReceipt{}, xerr.New(xerr.VIPLevelDisabled, "vip level is disabled") + return ledger.PurchaseVipReceipt{}, xerr.New(xerr.VIPPackageNotPurchasable, "vip package is disabled") } current, err := r.ensureUserVipForUpdate(ctx, tx, command.UserID, nowMs) if err != nil { @@ -85,22 +88,25 @@ func (r *Repository) PurchaseVip(ctx context.Context, command ledger.PurchaseVip return ledger.PurchaseVipReceipt{}, err } if account.AvailableAmount < level.PriceCoin { - return ledger.PurchaseVipReceipt{}, xerr.New(xerr.InsufficientBalance, "insufficient balance") + return ledger.PurchaseVipReceipt{}, xerr.New(xerr.VIPInsufficientCoin, "insufficient coin balance") } transactionID := transactionID(command.AppCode, command.CommandID) orderID := "vip_order_" + stableHash(command.AppCode+"|"+command.CommandID) coinBalanceAfter := account.AvailableAmount - level.PriceCoin metadata := map[string]any{ - "app_code": command.AppCode, - "order_id": orderID, - "user_id": command.UserID, - "target_level": command.Level, - "vip_name": level.Name, - "previous_level": previousLevel, - "price_coin": level.PriceCoin, - "expires_at_ms": newExpiresAt, - "balance_after": coinBalanceAfter, + "app_code": command.AppCode, + "order_id": orderID, + "user_id": command.UserID, + "target_level": command.Level, + "vip_name": level.Name, + "previous_level": previousLevel, + "price_coin": level.PriceCoin, + "expires_at_ms": newExpiresAt, + "balance_after": coinBalanceAfter, + // 余额版本必须与本次交易后的快照一起固化,幂等重放不能读取已被后续交易推进的当前版本。 + "balance_version": account.Version + 1, + "frozen_after": account.FrozenAmount, "reward_group_id": level.RewardResourceGroupID, "duration_ms": level.DurationMS, "previous_expires_at_ms": current.ExpiresAtMS, @@ -203,8 +209,13 @@ func (r *Repository) PurchaseVip(ctx context.Context, command ledger.PurchaseVip Vip: activation.VIP, CoinSpent: level.PriceCoin, CoinBalanceAfter: coinBalanceAfter, - RewardItems: activation.RewardItems, - State: state, + CoinBalance: ledger.AssetBalance{ + AppCode: command.AppCode, UserID: command.UserID, AssetType: ledger.AssetCoin, + AvailableAmount: coinBalanceAfter, FrozenAmount: account.FrozenAmount, + Version: account.Version + 1, UpdatedAtMs: nowMs, + }, + RewardItems: activation.RewardItems, + State: state, }, nil } @@ -518,9 +529,10 @@ func (r *Repository) vipPurchaseReceiptForTransaction(ctx context.Context, tx *s return ledger.PurchaseVipReceipt{}, err } var metadata struct { - VIPName string `json:"vip_name"` - StartedAtMS int64 `json:"started_at_ms"` - ExpiresAtMS int64 `json:"expires_at_ms"` + VIPName string `json:"vip_name"` + StartedAtMS int64 `json:"started_at_ms"` + ExpiresAtMS int64 `json:"expires_at_ms"` + BalanceVersion int64 `json:"balance_version"` } _ = json.Unmarshal([]byte(txRow.MetadataJSON), &metadata) if expiresAtMS <= 0 { @@ -552,6 +564,9 @@ func (r *Repository) vipPurchaseReceiptForTransaction(ctx context.Context, tx *s if err != nil { return ledger.PurchaseVipReceipt{}, err } + // 2026-07-15 之后的新交易始终从交易 metadata 还原原始版本。旧交易没有该字段时保持 0, + // Flutter 看到 version=0 必须走余额查询,不能拿当前账户版本伪装成本次历史回执。 + balance.Version = metadata.BalanceVersion rewards, err := r.rewardItemsByGrant(ctx, tx, grantID, expiresAtMS) if err != nil { return ledger.PurchaseVipReceipt{}, err @@ -562,6 +577,7 @@ func (r *Repository) vipPurchaseReceiptForTransaction(ctx context.Context, tx *s Vip: vip, CoinSpent: priceCoin, CoinBalanceAfter: balance.AvailableAmount, + CoinBalance: balance, RewardItems: rewards, }, nil } diff --git a/services/wallet-service/internal/storage/mysql/vip_trial_card_repository.go b/services/wallet-service/internal/storage/mysql/vip_trial_card_repository.go index a2de54cd..48b2b716 100644 --- a/services/wallet-service/internal/storage/mysql/vip_trial_card_repository.go +++ b/services/wallet-service/internal/storage/mysql/vip_trial_card_repository.go @@ -238,29 +238,38 @@ func (r *Repository) EquipVipTrialCard(ctx context.Context, command ledger.Equip defer func() { _ = tx.Rollback() }() nowMS := time.Now().UnixMilli() program, err := r.queryVipProgramConfig(ctx, tx.QueryRowContext(ctx, vipProgramSelectSQL(), command.AppCode)) + if errors.Is(err, sql.ErrNoRows) { + return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.VIPProgramInactive, "vip program config not found") + } if err != nil { return ledger.VipTrialCard{}, ledger.VipState{}, err } if program.Status != ledger.VipStatusActive || !program.TrialCardEnabled { - return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.Conflict, "vip trial card is disabled for this app") + return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.VIPProgramInactive, "vip trial card is disabled for this app") } // 锁序必须与 RevokeResourceGrant 保持 entitlement -> trial_card;反向先锁 card 会和后台撤销形成死锁。 // entitlement 同时承担并发有效性门禁,避免撤销在校验后抢先提交又被重新写回 equipment。 entitlement, err := r.getUserResourceEntitlementForUpdateTx(ctx, tx, command.EntitlementID) if err != nil { + if xerr.IsCode(err, xerr.NotFound) { + return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.VIPTrialCardNotFound, "vip trial card entitlement not found") + } return ledger.VipTrialCard{}, ledger.VipState{}, err } card, err := r.queryVipTrialCardForUpdate(ctx, tx, command.UserID, command.EntitlementID, nowMS) if errors.Is(err, sql.ErrNoRows) { - return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.NotFound, "vip trial card not found") + return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.VIPTrialCardNotFound, "vip trial card not found") } if err != nil { return ledger.VipTrialCard{}, ledger.VipState{}, err } + if card.ExpiresAtMS <= nowMS || (entitlement.ExpiresAtMS > 0 && entitlement.ExpiresAtMS <= nowMS) { + return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.VIPTrialCardExpired, "vip trial card expired") + } if entitlement.UserID != command.UserID || entitlement.ResourceID != card.ResourceID || entitlement.Status != resourcedomain.StatusActive || entitlement.EffectiveAtMS > nowMS || - (entitlement.ExpiresAtMS > 0 && entitlement.ExpiresAtMS <= nowMS) || entitlement.RemainingQuantity <= 0 { - return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.Conflict, "vip trial card entitlement is inactive") + card.Status != ledger.VipTrialCardStatusActive || card.EffectiveAtMS > nowMS || entitlement.RemainingQuantity <= 0 { + return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.VIPTrialCardNotFound, "vip trial card entitlement is inactive") } if resourcedomain.NormalizeResourceType(entitlement.Resource.ResourceType) != resourcedomain.TypeVIPTrialCard { return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.Conflict, "vip trial card resource type mismatch") @@ -435,10 +444,9 @@ func (r *Repository) queryVipTrialCardForUpdate(ctx context.Context, tx *sql.Tx, duration_ms, effective_at_ms, expires_at_ms, grant_source, source_grant_id, created_at_ms, updated_at_ms FROM user_vip_trial_cards - WHERE app_code = ? AND user_id = ? AND entitlement_id = ? AND status = ? - AND effective_at_ms <= ? AND expires_at_ms > ? + WHERE app_code = ? AND user_id = ? AND entitlement_id = ? FOR UPDATE`, - appcode.FromContext(ctx), userID, entitlementID, ledger.VipTrialCardStatusActive, nowMS, nowMS, + appcode.FromContext(ctx), userID, entitlementID, ) return scanVipTrialCard(row, nowMS) } diff --git a/services/wallet-service/internal/storage/mysql/vip_user_settings_repository.go b/services/wallet-service/internal/storage/mysql/vip_user_settings_repository.go index 0bcd846e..07887e63 100644 --- a/services/wallet-service/internal/storage/mysql/vip_user_settings_repository.go +++ b/services/wallet-service/internal/storage/mysql/vip_user_settings_repository.go @@ -19,7 +19,9 @@ func (r *Repository) UpdateVipUserSettings(ctx context.Context, command ledger.U } ctx = contextWithCommandApp(ctx, command.AppCode) command.AppCode = appcode.FromContext(ctx) - if command.UserID <= 0 || (command.RoomEntryNoticeEnabled == nil && command.OnlineGlobalNoticeEnabled == nil) { + if command.UserID <= 0 || (command.RoomEntryNoticeEnabled == nil && command.OnlineGlobalNoticeEnabled == nil && + command.HideProfileDataEnabled == nil && command.AnonymousProfileVisitEnabled == nil && + command.LeaderboardInvisibleEnabled == nil) { return ledger.VipUserSettings{}, xerr.New(xerr.InvalidArgument, "vip user settings update is incomplete") } @@ -39,17 +41,39 @@ func (r *Repository) UpdateVipUserSettings(ctx context.Context, command ledger.U if onlineProvided { onlineValue = *command.OnlineGlobalNoticeEnabled } + hideProfileValue := true + hideProfileProvided := command.HideProfileDataEnabled != nil + if hideProfileProvided { + hideProfileValue = *command.HideProfileDataEnabled + } + anonymousVisitValue := true + anonymousVisitProvided := command.AnonymousProfileVisitEnabled != nil + if anonymousVisitProvided { + anonymousVisitValue = *command.AnonymousProfileVisitEnabled + } + leaderboardInvisibleValue := true + leaderboardInvisibleProvided := command.LeaderboardInvisibleEnabled != nil + if leaderboardInvisibleProvided { + leaderboardInvisibleValue = *command.LeaderboardInvisibleEnabled + } if _, err := tx.ExecContext(ctx, ` INSERT INTO user_vip_settings ( app_code, user_id, room_entry_notice_enabled, online_global_notice_enabled, + hide_profile_data_enabled, anonymous_profile_visit_enabled, leaderboard_invisible_enabled, created_at_ms, updated_at_ms - ) VALUES (?, ?, ?, ?, ?, ?) + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE room_entry_notice_enabled = IF(?, ?, room_entry_notice_enabled), online_global_notice_enabled = IF(?, ?, online_global_notice_enabled), + hide_profile_data_enabled = IF(?, ?, hide_profile_data_enabled), + anonymous_profile_visit_enabled = IF(?, ?, anonymous_profile_visit_enabled), + leaderboard_invisible_enabled = IF(?, ?, leaderboard_invisible_enabled), updated_at_ms = ?`, - command.AppCode, command.UserID, roomValue, onlineValue, nowMS, nowMS, - roomProvided, roomValue, onlineProvided, onlineValue, nowMS, + command.AppCode, command.UserID, roomValue, onlineValue, hideProfileValue, + anonymousVisitValue, leaderboardInvisibleValue, nowMS, nowMS, + roomProvided, roomValue, onlineProvided, onlineValue, + hideProfileProvided, hideProfileValue, anonymousVisitProvided, anonymousVisitValue, + leaderboardInvisibleProvided, leaderboardInvisibleValue, nowMS, ); err != nil { return ledger.VipUserSettings{}, err } @@ -70,7 +94,8 @@ func (r *Repository) queryVipUserSettings(ctx context.Context, querier interface }, userID int64, lock bool) (ledger.VipUserSettings, error) { query := ` SELECT app_code, user_id, room_entry_notice_enabled, - online_global_notice_enabled, updated_at_ms + online_global_notice_enabled, hide_profile_data_enabled, + anonymous_profile_visit_enabled, leaderboard_invisible_enabled, updated_at_ms FROM user_vip_settings WHERE app_code = ? AND user_id = ?` if lock { @@ -79,7 +104,9 @@ func (r *Repository) queryVipUserSettings(ctx context.Context, querier interface var settings ledger.VipUserSettings if err := querier.QueryRowContext(ctx, query, appcode.FromContext(ctx), userID).Scan( &settings.AppCode, &settings.UserID, &settings.RoomEntryNoticeEnabled, - &settings.OnlineGlobalNoticeEnabled, &settings.UpdatedAtMS, + &settings.OnlineGlobalNoticeEnabled, &settings.HideProfileDataEnabled, + &settings.AnonymousProfileVisitEnabled, &settings.LeaderboardInvisibleEnabled, + &settings.UpdatedAtMS, ); err != nil { if errors.Is(err, sql.ErrNoRows) { return ledger.DefaultVipUserSettings(appcode.FromContext(ctx), userID), nil diff --git a/services/wallet-service/internal/transport/grpc/resource.go b/services/wallet-service/internal/transport/grpc/resource.go index 08442f16..69ebdf72 100644 --- a/services/wallet-service/internal/transport/grpc/resource.go +++ b/services/wallet-service/internal/transport/grpc/resource.go @@ -349,6 +349,21 @@ func (s *Server) RevokeResourceGrant(ctx context.Context, req *walletv1.RevokeRe return &walletv1.ResourceGrantResponse{Grant: resourceGrantToProto(grant)}, nil } +func (s *Server) RevokeUserResource(ctx context.Context, req *walletv1.RevokeUserResourceRequest) (*walletv1.RevokeUserResourceResponse, error) { + resource, err := s.svc.RevokeUserResource(ctx, resourcedomain.RevokeUserResourceCommand{ + RequestID: req.GetRequestId(), + AppCode: req.GetAppCode(), + UserID: req.GetUserId(), + EntitlementID: req.GetEntitlementId(), + Reason: req.GetReason(), + OperatorUserID: req.GetOperatorUserId(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &walletv1.RevokeUserResourceResponse{Resource: userResourceToProto(resource)}, nil +} + func (s *Server) ListUserResources(ctx context.Context, req *walletv1.ListUserResourcesRequest) (*walletv1.ListUserResourcesResponse, error) { items, err := s.svc.ListUserResources(ctx, resourcedomain.ListUserResourcesQuery{ AppCode: req.GetAppCode(), diff --git a/services/wallet-service/internal/transport/grpc/resource_command_mapper.go b/services/wallet-service/internal/transport/grpc/resource_command_mapper.go index c245653b..69a18c98 100644 --- a/services/wallet-service/internal/transport/grpc/resource_command_mapper.go +++ b/services/wallet-service/internal/transport/grpc/resource_command_mapper.go @@ -164,6 +164,7 @@ func resourceShopItemInputs(items []*walletv1.ResourceShopItemInput) []resourced ResourceID: item.GetResourceId(), Status: item.GetStatus(), DurationDays: item.GetDurationDays(), + CoinPrice: item.GetCoinPrice(), EffectiveFromMS: item.GetEffectiveFromMs(), EffectiveToMS: item.GetEffectiveToMs(), SortOrder: item.GetSortOrder(), diff --git a/services/wallet-service/internal/transport/grpc/vip.go b/services/wallet-service/internal/transport/grpc/vip.go index 5d8a2782..8e0305d5 100644 --- a/services/wallet-service/internal/transport/grpc/vip.go +++ b/services/wallet-service/internal/transport/grpc/vip.go @@ -90,6 +90,7 @@ func (s *Server) PurchaseVip(ctx context.Context, req *walletv1.PurchaseVipReque CoinBalanceAfter: receipt.CoinBalanceAfter, RewardItems: vipRewardItemsToProto(receipt.RewardItems), State: vipStateToProto(receipt.State), + CoinBalance: balanceToProto(receipt.CoinBalance), }, nil } @@ -255,9 +256,26 @@ func (s *Server) UpdateMyVipSettings(ctx context.Context, req *walletv1.UpdateMy value := req.GetOnlineGlobalNoticeEnabled() onlineGlobalNoticeEnabled = &value } + var hideProfileDataEnabled *bool + if req.HideProfileDataEnabled != nil { + value := req.GetHideProfileDataEnabled() + hideProfileDataEnabled = &value + } + var anonymousProfileVisitEnabled *bool + if req.AnonymousProfileVisitEnabled != nil { + value := req.GetAnonymousProfileVisitEnabled() + anonymousProfileVisitEnabled = &value + } + var leaderboardInvisibleEnabled *bool + if req.LeaderboardInvisibleEnabled != nil { + value := req.GetLeaderboardInvisibleEnabled() + leaderboardInvisibleEnabled = &value + } settings, err := s.svc.UpdateVipUserSettings(ctx, ledger.UpdateVipUserSettingsCommand{ AppCode: req.GetAppCode(), UserID: req.GetUserId(), RoomEntryNoticeEnabled: roomEntryNoticeEnabled, OnlineGlobalNoticeEnabled: onlineGlobalNoticeEnabled, + HideProfileDataEnabled: hideProfileDataEnabled, AnonymousProfileVisitEnabled: anonymousProfileVisitEnabled, + LeaderboardInvisibleEnabled: leaderboardInvisibleEnabled, }) if err != nil { return nil, xerr.ToGRPCError(err) @@ -355,9 +373,12 @@ func vipDailyCoinRebateToProto(rebate ledger.VipDailyCoinRebate) *walletv1.VipDa func vipUserSettingsToProto(settings ledger.VipUserSettings) *walletv1.VipUserSettings { return &walletv1.VipUserSettings{ AppCode: settings.AppCode, UserId: settings.UserID, - RoomEntryNoticeEnabled: settings.RoomEntryNoticeEnabled, - OnlineGlobalNoticeEnabled: settings.OnlineGlobalNoticeEnabled, - UpdatedAtMs: settings.UpdatedAtMS, + RoomEntryNoticeEnabled: settings.RoomEntryNoticeEnabled, + OnlineGlobalNoticeEnabled: settings.OnlineGlobalNoticeEnabled, + HideProfileDataEnabled: settings.HideProfileDataEnabled, + AnonymousProfileVisitEnabled: settings.AnonymousProfileVisitEnabled, + LeaderboardInvisibleEnabled: settings.LeaderboardInvisibleEnabled, + UpdatedAtMs: settings.UpdatedAtMS, } } @@ -439,6 +460,7 @@ func vipBenefitToProto(benefit ledger.VipBenefit) *walletv1.VipBenefit { MetadataJson: benefit.MetadataJSON, CreatedAtMs: benefit.CreatedAtMS, UpdatedAtMs: benefit.UpdatedAtMS, + Presentation: vipBenefitPresentationToProto(benefit.Presentation), } } @@ -471,11 +493,62 @@ func vipBenefitsFromProto(benefits []*walletv1.VipBenefit) []ledger.VipBenefit { AutoEquip: benefit.GetAutoEquip(), SortOrder: benefit.GetSortOrder(), MetadataJSON: benefit.GetMetadataJson(), + Presentation: vipBenefitPresentationFromProto(benefit.GetPresentation()), }) } return items } +func vipBenefitPresentationToProto(presentation *ledger.VipBenefitPresentation) *walletv1.VipBenefitPresentation { + if presentation == nil { + return nil + } + result := &walletv1.VipBenefitPresentation{ + Description: presentation.Description, + PreviewItems: make([]*walletv1.VipBenefitPreviewItem, 0, len(presentation.PreviewItems)), + } + for _, item := range presentation.PreviewItems { + result.PreviewItems = append(result.PreviewItems, &walletv1.VipBenefitPreviewItem{ + PreviewId: item.PreviewID, Title: item.Title, MediaType: item.MediaType, + AssetUrl: item.AssetURL, PreviewUrl: item.PreviewURL, AnimationUrl: item.AnimationURL, + CompositionType: item.CompositionType, SortOrder: item.SortOrder, + }) + } + if presentation.NumericReward != nil { + result.NumericReward = &walletv1.VipBenefitNumericReward{ + Label: presentation.NumericReward.Label, Value: presentation.NumericReward.Value, + Unit: presentation.NumericReward.Unit, Period: presentation.NumericReward.Period, + } + } + return result +} + +func vipBenefitPresentationFromProto(presentation *walletv1.VipBenefitPresentation) *ledger.VipBenefitPresentation { + if presentation == nil { + return nil + } + result := &ledger.VipBenefitPresentation{ + Description: presentation.GetDescription(), + PreviewItems: make([]ledger.VipBenefitPreviewItem, 0, len(presentation.GetPreviewItems())), + } + for _, item := range presentation.GetPreviewItems() { + if item == nil { + continue + } + result.PreviewItems = append(result.PreviewItems, ledger.VipBenefitPreviewItem{ + PreviewID: item.GetPreviewId(), Title: item.GetTitle(), MediaType: item.GetMediaType(), + AssetURL: item.GetAssetUrl(), PreviewURL: item.GetPreviewUrl(), AnimationURL: item.GetAnimationUrl(), + CompositionType: item.GetCompositionType(), SortOrder: item.GetSortOrder(), + }) + } + if reward := presentation.GetNumericReward(); reward != nil { + result.NumericReward = &ledger.VipBenefitNumericReward{ + Label: reward.GetLabel(), Value: reward.GetValue(), Unit: reward.GetUnit(), Period: reward.GetPeriod(), + } + } + return result +} + func vipTrialCardToProto(card ledger.VipTrialCard) *walletv1.VipTrialCard { if card.TrialCardID == "" { return nil