diff --git a/.gitignore b/.gitignore index c0661130..88abf702 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ redis-data/ .tmp/ /tmp/ .claude/settings.local.json +backfill-last7 diff --git a/api/proto/activity/v1/activity.pb.go b/api/proto/activity/v1/activity.pb.go index 60b2863d..399ffd34 100644 --- a/api/proto/activity/v1/activity.pb.go +++ b/api/proto/activity/v1/activity.pb.go @@ -13031,19 +13031,26 @@ type LevelRewardJob struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - RewardJobId string `protobuf:"bytes,1,opt,name=reward_job_id,json=rewardJobId,proto3" json:"reward_job_id,omitempty"` - UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Track string `protobuf:"bytes,3,opt,name=track,proto3" json:"track,omitempty"` - RewardSourceType string `protobuf:"bytes,4,opt,name=reward_source_type,json=rewardSourceType,proto3" json:"reward_source_type,omitempty"` - RewardSourceId string `protobuf:"bytes,5,opt,name=reward_source_id,json=rewardSourceId,proto3" json:"reward_source_id,omitempty"` - ResourceGroupId int64 `protobuf:"varint,6,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` - WalletCommandId string `protobuf:"bytes,7,opt,name=wallet_command_id,json=walletCommandId,proto3" json:"wallet_command_id,omitempty"` - WalletGrantId string `protobuf:"bytes,8,opt,name=wallet_grant_id,json=walletGrantId,proto3" json:"wallet_grant_id,omitempty"` - Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"` - AttemptCount int32 `protobuf:"varint,10,opt,name=attempt_count,json=attemptCount,proto3" json:"attempt_count,omitempty"` - FailureReason string `protobuf:"bytes,11,opt,name=failure_reason,json=failureReason,proto3" json:"failure_reason,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"` + RewardJobId string `protobuf:"bytes,1,opt,name=reward_job_id,json=rewardJobId,proto3" json:"reward_job_id,omitempty"` + UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Track string `protobuf:"bytes,3,opt,name=track,proto3" json:"track,omitempty"` + RewardSourceType string `protobuf:"bytes,4,opt,name=reward_source_type,json=rewardSourceType,proto3" json:"reward_source_type,omitempty"` + RewardSourceId string `protobuf:"bytes,5,opt,name=reward_source_id,json=rewardSourceId,proto3" json:"reward_source_id,omitempty"` + ResourceGroupId int64 `protobuf:"varint,6,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` + WalletCommandId string `protobuf:"bytes,7,opt,name=wallet_command_id,json=walletCommandId,proto3" json:"wallet_command_id,omitempty"` + WalletGrantId string `protobuf:"bytes,8,opt,name=wallet_grant_id,json=walletGrantId,proto3" json:"wallet_grant_id,omitempty"` + Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"` + AttemptCount int32 `protobuf:"varint,10,opt,name=attempt_count,json=attemptCount,proto3" json:"attempt_count,omitempty"` + FailureReason string `protobuf:"bytes,11,opt,name=failure_reason,json=failureReason,proto3" json:"failure_reason,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"` + RewardOrigin string `protobuf:"bytes,14,opt,name=reward_origin,json=rewardOrigin,proto3" json:"reward_origin,omitempty"` + TemporaryLevelId string `protobuf:"bytes,15,opt,name=temporary_level_id,json=temporaryLevelId,proto3" json:"temporary_level_id,omitempty"` + GrantGeneration int32 `protobuf:"varint,16,opt,name=grant_generation,json=grantGeneration,proto3" json:"grant_generation,omitempty"` + RewardLevel int32 `protobuf:"varint,17,opt,name=reward_level,json=rewardLevel,proto3" json:"reward_level,omitempty"` + Permanent bool `protobuf:"varint,18,opt,name=permanent,proto3" json:"permanent,omitempty"` + TemporaryExpiresAtMs int64 `protobuf:"varint,19,opt,name=temporary_expires_at_ms,json=temporaryExpiresAtMs,proto3" json:"temporary_expires_at_ms,omitempty"` + RevokeStatus string `protobuf:"bytes,20,opt,name=revoke_status,json=revokeStatus,proto3" json:"revoke_status,omitempty"` } func (x *LevelRewardJob) Reset() { @@ -13167,6 +13174,55 @@ func (x *LevelRewardJob) GetUpdatedAtMs() int64 { return 0 } +func (x *LevelRewardJob) GetRewardOrigin() string { + if x != nil { + return x.RewardOrigin + } + return "" +} + +func (x *LevelRewardJob) GetTemporaryLevelId() string { + if x != nil { + return x.TemporaryLevelId + } + return "" +} + +func (x *LevelRewardJob) GetGrantGeneration() int32 { + if x != nil { + return x.GrantGeneration + } + return 0 +} + +func (x *LevelRewardJob) GetRewardLevel() int32 { + if x != nil { + return x.RewardLevel + } + return 0 +} + +func (x *LevelRewardJob) GetPermanent() bool { + if x != nil { + return x.Permanent + } + return false +} + +func (x *LevelRewardJob) GetTemporaryExpiresAtMs() int64 { + if x != nil { + return x.TemporaryExpiresAtMs + } + return 0 +} + +func (x *LevelRewardJob) GetRevokeStatus() string { + if x != nil { + return x.RevokeStatus + } + return "" +} + type ListLevelRewardsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -13710,6 +13766,475 @@ func (x *SetUserLevelResponse) GetServerTimeMs() int64 { return 0 } +// AdminLevelTrackProfile keeps the permanent account and the currently effective display overlay separate. +type AdminLevelTrackProfile struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Track string `protobuf:"bytes,1,opt,name=track,proto3" json:"track,omitempty"` + RealLevel int32 `protobuf:"varint,2,opt,name=real_level,json=realLevel,proto3" json:"real_level,omitempty"` + RealTotalValue int64 `protobuf:"varint,3,opt,name=real_total_value,json=realTotalValue,proto3" json:"real_total_value,omitempty"` + DisplayLevel int32 `protobuf:"varint,4,opt,name=display_level,json=displayLevel,proto3" json:"display_level,omitempty"` + DisplayValue int64 `protobuf:"varint,5,opt,name=display_value,json=displayValue,proto3" json:"display_value,omitempty"` + TemporaryLevelId string `protobuf:"bytes,6,opt,name=temporary_level_id,json=temporaryLevelId,proto3" json:"temporary_level_id,omitempty"` + TemporaryTargetLevel int32 `protobuf:"varint,7,opt,name=temporary_target_level,json=temporaryTargetLevel,proto3" json:"temporary_target_level,omitempty"` + StartedAtMs int64 `protobuf:"varint,8,opt,name=started_at_ms,json=startedAtMs,proto3" json:"started_at_ms,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,9,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` +} + +func (x *AdminLevelTrackProfile) Reset() { + *x = AdminLevelTrackProfile{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[171] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdminLevelTrackProfile) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdminLevelTrackProfile) ProtoMessage() {} + +func (x *AdminLevelTrackProfile) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[171] + 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 AdminLevelTrackProfile.ProtoReflect.Descriptor instead. +func (*AdminLevelTrackProfile) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{171} +} + +func (x *AdminLevelTrackProfile) GetTrack() string { + if x != nil { + return x.Track + } + return "" +} + +func (x *AdminLevelTrackProfile) GetRealLevel() int32 { + if x != nil { + return x.RealLevel + } + return 0 +} + +func (x *AdminLevelTrackProfile) GetRealTotalValue() int64 { + if x != nil { + return x.RealTotalValue + } + return 0 +} + +func (x *AdminLevelTrackProfile) GetDisplayLevel() int32 { + if x != nil { + return x.DisplayLevel + } + return 0 +} + +func (x *AdminLevelTrackProfile) GetDisplayValue() int64 { + if x != nil { + return x.DisplayValue + } + return 0 +} + +func (x *AdminLevelTrackProfile) GetTemporaryLevelId() string { + if x != nil { + return x.TemporaryLevelId + } + return "" +} + +func (x *AdminLevelTrackProfile) GetTemporaryTargetLevel() int32 { + if x != nil { + return x.TemporaryTargetLevel + } + return 0 +} + +func (x *AdminLevelTrackProfile) GetStartedAtMs() int64 { + if x != nil { + return x.StartedAtMs + } + return 0 +} + +func (x *AdminLevelTrackProfile) GetExpiresAtMs() int64 { + if x != nil { + return x.ExpiresAtMs + } + return 0 +} + +type AdminUserLevelProfile 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"` + Tracks []*AdminLevelTrackProfile `protobuf:"bytes,2,rep,name=tracks,proto3" json:"tracks,omitempty"` +} + +func (x *AdminUserLevelProfile) Reset() { + *x = AdminUserLevelProfile{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[172] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdminUserLevelProfile) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdminUserLevelProfile) ProtoMessage() {} + +func (x *AdminUserLevelProfile) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[172] + 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 AdminUserLevelProfile.ProtoReflect.Descriptor instead. +func (*AdminUserLevelProfile) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{172} +} + +func (x *AdminUserLevelProfile) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *AdminUserLevelProfile) GetTracks() []*AdminLevelTrackProfile { + if x != nil { + return x.Tracks + } + return nil +} + +type BatchGetUserLevelAdminProfilesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *BatchGetUserLevelAdminProfilesRequest) Reset() { + *x = BatchGetUserLevelAdminProfilesRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[173] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BatchGetUserLevelAdminProfilesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BatchGetUserLevelAdminProfilesRequest) ProtoMessage() {} + +func (x *BatchGetUserLevelAdminProfilesRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[173] + 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 BatchGetUserLevelAdminProfilesRequest.ProtoReflect.Descriptor instead. +func (*BatchGetUserLevelAdminProfilesRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{173} +} + +func (x *BatchGetUserLevelAdminProfilesRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *BatchGetUserLevelAdminProfilesRequest) GetUserIds() []int64 { + if x != nil { + return x.UserIds + } + return nil +} + +type BatchGetUserLevelAdminProfilesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Profiles []*AdminUserLevelProfile `protobuf:"bytes,1,rep,name=profiles,proto3" json:"profiles,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` +} + +func (x *BatchGetUserLevelAdminProfilesResponse) Reset() { + *x = BatchGetUserLevelAdminProfilesResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[174] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BatchGetUserLevelAdminProfilesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BatchGetUserLevelAdminProfilesResponse) ProtoMessage() {} + +func (x *BatchGetUserLevelAdminProfilesResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[174] + 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 BatchGetUserLevelAdminProfilesResponse.ProtoReflect.Descriptor instead. +func (*BatchGetUserLevelAdminProfilesResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{174} +} + +func (x *BatchGetUserLevelAdminProfilesResponse) GetProfiles() []*AdminUserLevelProfile { + if x != nil { + return x.Profiles + } + return nil +} + +func (x *BatchGetUserLevelAdminProfilesResponse) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +// TemporaryLevelAdjustment is limited to wealth/charm; duration_days must be positive and level is 1..50. +type TemporaryLevelAdjustment struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Track string `protobuf:"bytes,1,opt,name=track,proto3" json:"track,omitempty"` + Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` + DurationDays int32 `protobuf:"varint,3,opt,name=duration_days,json=durationDays,proto3" json:"duration_days,omitempty"` +} + +func (x *TemporaryLevelAdjustment) Reset() { + *x = TemporaryLevelAdjustment{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[175] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TemporaryLevelAdjustment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TemporaryLevelAdjustment) ProtoMessage() {} + +func (x *TemporaryLevelAdjustment) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[175] + 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 TemporaryLevelAdjustment.ProtoReflect.Descriptor instead. +func (*TemporaryLevelAdjustment) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{175} +} + +func (x *TemporaryLevelAdjustment) GetTrack() string { + if x != nil { + return x.Track + } + return "" +} + +func (x *TemporaryLevelAdjustment) GetLevel() int32 { + if x != nil { + return x.Level + } + return 0 +} + +func (x *TemporaryLevelAdjustment) GetDurationDays() int32 { + if x != nil { + return x.DurationDays + } + return 0 +} + +type AdjustTemporaryUserLevelsRequest 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"` + Adjustments []*TemporaryLevelAdjustment `protobuf:"bytes,4,rep,name=adjustments,proto3" json:"adjustments,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"` +} + +func (x *AdjustTemporaryUserLevelsRequest) Reset() { + *x = AdjustTemporaryUserLevelsRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[176] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdjustTemporaryUserLevelsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdjustTemporaryUserLevelsRequest) ProtoMessage() {} + +func (x *AdjustTemporaryUserLevelsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[176] + 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 AdjustTemporaryUserLevelsRequest.ProtoReflect.Descriptor instead. +func (*AdjustTemporaryUserLevelsRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{176} +} + +func (x *AdjustTemporaryUserLevelsRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *AdjustTemporaryUserLevelsRequest) GetCommandId() string { + if x != nil { + return x.CommandId + } + return "" +} + +func (x *AdjustTemporaryUserLevelsRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *AdjustTemporaryUserLevelsRequest) GetAdjustments() []*TemporaryLevelAdjustment { + if x != nil { + return x.Adjustments + } + return nil +} + +func (x *AdjustTemporaryUserLevelsRequest) GetOperatorAdminId() int64 { + if x != nil { + return x.OperatorAdminId + } + return 0 +} + +func (x *AdjustTemporaryUserLevelsRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type AdjustTemporaryUserLevelsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Profile *AdminUserLevelProfile `protobuf:"bytes,1,opt,name=profile,proto3" json:"profile,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` +} + +func (x *AdjustTemporaryUserLevelsResponse) Reset() { + *x = AdjustTemporaryUserLevelsResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[177] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdjustTemporaryUserLevelsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdjustTemporaryUserLevelsResponse) ProtoMessage() {} + +func (x *AdjustTemporaryUserLevelsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_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 AdjustTemporaryUserLevelsResponse.ProtoReflect.Descriptor instead. +func (*AdjustTemporaryUserLevelsResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{177} +} + +func (x *AdjustTemporaryUserLevelsResponse) GetProfile() *AdminUserLevelProfile { + if x != nil { + return x.Profile + } + return nil +} + +func (x *AdjustTemporaryUserLevelsResponse) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + type RegistrationLevelBadgeGrant struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -13723,7 +14248,7 @@ type RegistrationLevelBadgeGrant struct { func (x *RegistrationLevelBadgeGrant) Reset() { *x = RegistrationLevelBadgeGrant{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[171] + mi := &file_proto_activity_v1_activity_proto_msgTypes[178] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13735,7 +14260,7 @@ func (x *RegistrationLevelBadgeGrant) String() string { func (*RegistrationLevelBadgeGrant) ProtoMessage() {} func (x *RegistrationLevelBadgeGrant) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[171] + mi := &file_proto_activity_v1_activity_proto_msgTypes[178] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13748,7 +14273,7 @@ func (x *RegistrationLevelBadgeGrant) ProtoReflect() protoreflect.Message { // Deprecated: Use RegistrationLevelBadgeGrant.ProtoReflect.Descriptor instead. func (*RegistrationLevelBadgeGrant) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{171} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{178} } func (x *RegistrationLevelBadgeGrant) GetTrack() string { @@ -13791,7 +14316,7 @@ type IssueRegistrationLevelBadgesRequest struct { func (x *IssueRegistrationLevelBadgesRequest) Reset() { *x = IssueRegistrationLevelBadgesRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[172] + mi := &file_proto_activity_v1_activity_proto_msgTypes[179] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13803,7 +14328,7 @@ func (x *IssueRegistrationLevelBadgesRequest) String() string { func (*IssueRegistrationLevelBadgesRequest) ProtoMessage() {} func (x *IssueRegistrationLevelBadgesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[172] + mi := &file_proto_activity_v1_activity_proto_msgTypes[179] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13816,7 +14341,7 @@ func (x *IssueRegistrationLevelBadgesRequest) ProtoReflect() protoreflect.Messag // Deprecated: Use IssueRegistrationLevelBadgesRequest.ProtoReflect.Descriptor instead. func (*IssueRegistrationLevelBadgesRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{172} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{179} } func (x *IssueRegistrationLevelBadgesRequest) GetMeta() *RequestMeta { @@ -13851,7 +14376,7 @@ type IssueRegistrationLevelBadgesResponse struct { func (x *IssueRegistrationLevelBadgesResponse) Reset() { *x = IssueRegistrationLevelBadgesResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[173] + mi := &file_proto_activity_v1_activity_proto_msgTypes[180] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13863,7 +14388,7 @@ func (x *IssueRegistrationLevelBadgesResponse) String() string { func (*IssueRegistrationLevelBadgesResponse) ProtoMessage() {} func (x *IssueRegistrationLevelBadgesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[173] + mi := &file_proto_activity_v1_activity_proto_msgTypes[180] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13876,7 +14401,7 @@ func (x *IssueRegistrationLevelBadgesResponse) ProtoReflect() protoreflect.Messa // Deprecated: Use IssueRegistrationLevelBadgesResponse.ProtoReflect.Descriptor instead. func (*IssueRegistrationLevelBadgesResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{173} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{180} } func (x *IssueRegistrationLevelBadgesResponse) GetGrants() []*RegistrationLevelBadgeGrant { @@ -13908,7 +14433,7 @@ type UpsertLevelTrackRequest struct { func (x *UpsertLevelTrackRequest) Reset() { *x = UpsertLevelTrackRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[174] + mi := &file_proto_activity_v1_activity_proto_msgTypes[181] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13920,7 +14445,7 @@ func (x *UpsertLevelTrackRequest) String() string { func (*UpsertLevelTrackRequest) ProtoMessage() {} func (x *UpsertLevelTrackRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[174] + mi := &file_proto_activity_v1_activity_proto_msgTypes[181] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13933,7 +14458,7 @@ func (x *UpsertLevelTrackRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertLevelTrackRequest.ProtoReflect.Descriptor instead. func (*UpsertLevelTrackRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{174} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{181} } func (x *UpsertLevelTrackRequest) GetMeta() *RequestMeta { @@ -13989,7 +14514,7 @@ type UpsertLevelTrackResponse struct { func (x *UpsertLevelTrackResponse) Reset() { *x = UpsertLevelTrackResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[175] + mi := &file_proto_activity_v1_activity_proto_msgTypes[182] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14001,7 +14526,7 @@ func (x *UpsertLevelTrackResponse) String() string { func (*UpsertLevelTrackResponse) ProtoMessage() {} func (x *UpsertLevelTrackResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[175] + mi := &file_proto_activity_v1_activity_proto_msgTypes[182] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14014,7 +14539,7 @@ func (x *UpsertLevelTrackResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertLevelTrackResponse.ProtoReflect.Descriptor instead. func (*UpsertLevelTrackResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{175} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{182} } func (x *UpsertLevelTrackResponse) GetTrack() *LevelTrack { @@ -14050,7 +14575,7 @@ type UpsertLevelRuleRequest struct { func (x *UpsertLevelRuleRequest) Reset() { *x = UpsertLevelRuleRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[176] + mi := &file_proto_activity_v1_activity_proto_msgTypes[183] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14062,7 +14587,7 @@ func (x *UpsertLevelRuleRequest) String() string { func (*UpsertLevelRuleRequest) ProtoMessage() {} func (x *UpsertLevelRuleRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[176] + mi := &file_proto_activity_v1_activity_proto_msgTypes[183] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14075,7 +14600,7 @@ func (x *UpsertLevelRuleRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertLevelRuleRequest.ProtoReflect.Descriptor instead. func (*UpsertLevelRuleRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{176} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{183} } func (x *UpsertLevelRuleRequest) GetMeta() *RequestMeta { @@ -14159,7 +14684,7 @@ type UpsertLevelRuleResponse struct { func (x *UpsertLevelRuleResponse) Reset() { *x = UpsertLevelRuleResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[177] + mi := &file_proto_activity_v1_activity_proto_msgTypes[184] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14171,7 +14696,7 @@ func (x *UpsertLevelRuleResponse) String() string { func (*UpsertLevelRuleResponse) ProtoMessage() {} func (x *UpsertLevelRuleResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[177] + mi := &file_proto_activity_v1_activity_proto_msgTypes[184] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14184,7 +14709,7 @@ func (x *UpsertLevelRuleResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertLevelRuleResponse.ProtoReflect.Descriptor instead. func (*UpsertLevelRuleResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{177} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{184} } func (x *UpsertLevelRuleResponse) GetRule() *LevelRule { @@ -14222,7 +14747,7 @@ type UpsertLevelTierRequest struct { func (x *UpsertLevelTierRequest) Reset() { *x = UpsertLevelTierRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[178] + mi := &file_proto_activity_v1_activity_proto_msgTypes[185] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14234,7 +14759,7 @@ func (x *UpsertLevelTierRequest) String() string { func (*UpsertLevelTierRequest) ProtoMessage() {} func (x *UpsertLevelTierRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[178] + mi := &file_proto_activity_v1_activity_proto_msgTypes[185] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14247,7 +14772,7 @@ func (x *UpsertLevelTierRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertLevelTierRequest.ProtoReflect.Descriptor instead. func (*UpsertLevelTierRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{178} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{185} } func (x *UpsertLevelTierRequest) GetMeta() *RequestMeta { @@ -14345,7 +14870,7 @@ type UpsertLevelTierResponse struct { func (x *UpsertLevelTierResponse) Reset() { *x = UpsertLevelTierResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[179] + mi := &file_proto_activity_v1_activity_proto_msgTypes[186] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14357,7 +14882,7 @@ func (x *UpsertLevelTierResponse) String() string { func (*UpsertLevelTierResponse) ProtoMessage() {} func (x *UpsertLevelTierResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[179] + mi := &file_proto_activity_v1_activity_proto_msgTypes[186] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14370,7 +14895,7 @@ func (x *UpsertLevelTierResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertLevelTierResponse.ProtoReflect.Descriptor instead. func (*UpsertLevelTierResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{179} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{186} } func (x *UpsertLevelTierResponse) GetTier() *LevelTier { @@ -14400,7 +14925,7 @@ type ListLevelConfigRequest struct { func (x *ListLevelConfigRequest) Reset() { *x = ListLevelConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[180] + mi := &file_proto_activity_v1_activity_proto_msgTypes[187] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14412,7 +14937,7 @@ func (x *ListLevelConfigRequest) String() string { func (*ListLevelConfigRequest) ProtoMessage() {} func (x *ListLevelConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[180] + mi := &file_proto_activity_v1_activity_proto_msgTypes[187] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14425,7 +14950,7 @@ func (x *ListLevelConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLevelConfigRequest.ProtoReflect.Descriptor instead. func (*ListLevelConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{180} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{187} } func (x *ListLevelConfigRequest) GetMeta() *RequestMeta { @@ -14462,7 +14987,7 @@ type ListLevelConfigResponse struct { func (x *ListLevelConfigResponse) Reset() { *x = ListLevelConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[181] + mi := &file_proto_activity_v1_activity_proto_msgTypes[188] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14474,7 +14999,7 @@ func (x *ListLevelConfigResponse) String() string { func (*ListLevelConfigResponse) ProtoMessage() {} func (x *ListLevelConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[181] + mi := &file_proto_activity_v1_activity_proto_msgTypes[188] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14487,7 +15012,7 @@ func (x *ListLevelConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLevelConfigResponse.ProtoReflect.Descriptor instead. func (*ListLevelConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{181} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{188} } func (x *ListLevelConfigResponse) GetTracks() []*LevelTrack { @@ -14534,7 +15059,7 @@ type AchievementCondition struct { func (x *AchievementCondition) Reset() { *x = AchievementCondition{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[182] + mi := &file_proto_activity_v1_activity_proto_msgTypes[189] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14546,7 +15071,7 @@ func (x *AchievementCondition) String() string { func (*AchievementCondition) ProtoMessage() {} func (x *AchievementCondition) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[182] + mi := &file_proto_activity_v1_activity_proto_msgTypes[189] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14559,7 +15084,7 @@ func (x *AchievementCondition) ProtoReflect() protoreflect.Message { // Deprecated: Use AchievementCondition.ProtoReflect.Descriptor instead. func (*AchievementCondition) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{182} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{189} } func (x *AchievementCondition) GetConditionId() string { @@ -14641,7 +15166,7 @@ type AchievementDefinition struct { func (x *AchievementDefinition) Reset() { *x = AchievementDefinition{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[183] + mi := &file_proto_activity_v1_activity_proto_msgTypes[190] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14653,7 +15178,7 @@ func (x *AchievementDefinition) String() string { func (*AchievementDefinition) ProtoMessage() {} func (x *AchievementDefinition) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[183] + mi := &file_proto_activity_v1_activity_proto_msgTypes[190] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14666,7 +15191,7 @@ func (x *AchievementDefinition) ProtoReflect() protoreflect.Message { // Deprecated: Use AchievementDefinition.ProtoReflect.Descriptor instead. func (*AchievementDefinition) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{183} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{190} } func (x *AchievementDefinition) GetAchievementId() string { @@ -14832,7 +15357,7 @@ type UserAchievement struct { func (x *UserAchievement) Reset() { *x = UserAchievement{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[184] + mi := &file_proto_activity_v1_activity_proto_msgTypes[191] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14844,7 +15369,7 @@ func (x *UserAchievement) String() string { func (*UserAchievement) ProtoMessage() {} func (x *UserAchievement) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[184] + mi := &file_proto_activity_v1_activity_proto_msgTypes[191] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14857,7 +15382,7 @@ func (x *UserAchievement) ProtoReflect() protoreflect.Message { // Deprecated: Use UserAchievement.ProtoReflect.Descriptor instead. func (*UserAchievement) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{184} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{191} } func (x *UserAchievement) GetDefinition() *AchievementDefinition { @@ -14924,7 +15449,7 @@ type ListAchievementsRequest struct { func (x *ListAchievementsRequest) Reset() { *x = ListAchievementsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[185] + mi := &file_proto_activity_v1_activity_proto_msgTypes[192] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14936,7 +15461,7 @@ func (x *ListAchievementsRequest) String() string { func (*ListAchievementsRequest) ProtoMessage() {} func (x *ListAchievementsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[185] + mi := &file_proto_activity_v1_activity_proto_msgTypes[192] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14949,7 +15474,7 @@ func (x *ListAchievementsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAchievementsRequest.ProtoReflect.Descriptor instead. func (*ListAchievementsRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{185} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{192} } func (x *ListAchievementsRequest) GetMeta() *RequestMeta { @@ -15006,7 +15531,7 @@ type ListAchievementsResponse struct { func (x *ListAchievementsResponse) Reset() { *x = ListAchievementsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[186] + mi := &file_proto_activity_v1_activity_proto_msgTypes[193] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15018,7 +15543,7 @@ func (x *ListAchievementsResponse) String() string { func (*ListAchievementsResponse) ProtoMessage() {} func (x *ListAchievementsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[186] + mi := &file_proto_activity_v1_activity_proto_msgTypes[193] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15031,7 +15556,7 @@ func (x *ListAchievementsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAchievementsResponse.ProtoReflect.Descriptor instead. func (*ListAchievementsResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{186} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{193} } func (x *ListAchievementsResponse) GetAchievements() []*UserAchievement { @@ -15073,7 +15598,7 @@ type ConsumeAchievementEventRequest struct { func (x *ConsumeAchievementEventRequest) Reset() { *x = ConsumeAchievementEventRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[187] + mi := &file_proto_activity_v1_activity_proto_msgTypes[194] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15085,7 +15610,7 @@ func (x *ConsumeAchievementEventRequest) String() string { func (*ConsumeAchievementEventRequest) ProtoMessage() {} func (x *ConsumeAchievementEventRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[187] + mi := &file_proto_activity_v1_activity_proto_msgTypes[194] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15098,7 +15623,7 @@ func (x *ConsumeAchievementEventRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConsumeAchievementEventRequest.ProtoReflect.Descriptor instead. func (*ConsumeAchievementEventRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{187} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{194} } func (x *ConsumeAchievementEventRequest) GetMeta() *RequestMeta { @@ -15178,7 +15703,7 @@ type ConsumeAchievementEventResponse struct { func (x *ConsumeAchievementEventResponse) Reset() { *x = ConsumeAchievementEventResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[188] + mi := &file_proto_activity_v1_activity_proto_msgTypes[195] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15190,7 +15715,7 @@ func (x *ConsumeAchievementEventResponse) String() string { func (*ConsumeAchievementEventResponse) ProtoMessage() {} func (x *ConsumeAchievementEventResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[188] + mi := &file_proto_activity_v1_activity_proto_msgTypes[195] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15203,7 +15728,7 @@ func (x *ConsumeAchievementEventResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ConsumeAchievementEventResponse.ProtoReflect.Descriptor instead. func (*ConsumeAchievementEventResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{188} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{195} } func (x *ConsumeAchievementEventResponse) GetEventId() string { @@ -15259,7 +15784,7 @@ type BadgeDisplayItem struct { func (x *BadgeDisplayItem) Reset() { *x = BadgeDisplayItem{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[189] + mi := &file_proto_activity_v1_activity_proto_msgTypes[196] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15271,7 +15796,7 @@ func (x *BadgeDisplayItem) String() string { func (*BadgeDisplayItem) ProtoMessage() {} func (x *BadgeDisplayItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[189] + mi := &file_proto_activity_v1_activity_proto_msgTypes[196] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15284,7 +15809,7 @@ func (x *BadgeDisplayItem) ProtoReflect() protoreflect.Message { // Deprecated: Use BadgeDisplayItem.ProtoReflect.Descriptor instead. func (*BadgeDisplayItem) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{189} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{196} } func (x *BadgeDisplayItem) GetSlot() string { @@ -15361,7 +15886,7 @@ type ListMyBadgesRequest struct { func (x *ListMyBadgesRequest) Reset() { *x = ListMyBadgesRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[190] + mi := &file_proto_activity_v1_activity_proto_msgTypes[197] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15373,7 +15898,7 @@ func (x *ListMyBadgesRequest) String() string { func (*ListMyBadgesRequest) ProtoMessage() {} func (x *ListMyBadgesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[190] + mi := &file_proto_activity_v1_activity_proto_msgTypes[197] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15386,7 +15911,7 @@ func (x *ListMyBadgesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListMyBadgesRequest.ProtoReflect.Descriptor instead. func (*ListMyBadgesRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{190} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{197} } func (x *ListMyBadgesRequest) GetMeta() *RequestMeta { @@ -15416,7 +15941,7 @@ type ListMyBadgesResponse struct { func (x *ListMyBadgesResponse) Reset() { *x = ListMyBadgesResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[191] + mi := &file_proto_activity_v1_activity_proto_msgTypes[198] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15428,7 +15953,7 @@ func (x *ListMyBadgesResponse) String() string { func (*ListMyBadgesResponse) ProtoMessage() {} func (x *ListMyBadgesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[191] + mi := &file_proto_activity_v1_activity_proto_msgTypes[198] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15441,7 +15966,7 @@ func (x *ListMyBadgesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListMyBadgesResponse.ProtoReflect.Descriptor instead. func (*ListMyBadgesResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{191} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{198} } func (x *ListMyBadgesResponse) GetStripBadges() []*BadgeDisplayItem { @@ -15486,7 +16011,7 @@ type SetBadgeDisplayRequest struct { func (x *SetBadgeDisplayRequest) Reset() { *x = SetBadgeDisplayRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[192] + mi := &file_proto_activity_v1_activity_proto_msgTypes[199] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15498,7 +16023,7 @@ func (x *SetBadgeDisplayRequest) String() string { func (*SetBadgeDisplayRequest) ProtoMessage() {} func (x *SetBadgeDisplayRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[192] + mi := &file_proto_activity_v1_activity_proto_msgTypes[199] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15511,7 +16036,7 @@ func (x *SetBadgeDisplayRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetBadgeDisplayRequest.ProtoReflect.Descriptor instead. func (*SetBadgeDisplayRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{192} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{199} } func (x *SetBadgeDisplayRequest) GetMeta() *RequestMeta { @@ -15559,7 +16084,7 @@ type SetBadgeDisplayResponse struct { func (x *SetBadgeDisplayResponse) Reset() { *x = SetBadgeDisplayResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[193] + mi := &file_proto_activity_v1_activity_proto_msgTypes[200] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15571,7 +16096,7 @@ func (x *SetBadgeDisplayResponse) String() string { func (*SetBadgeDisplayResponse) ProtoMessage() {} func (x *SetBadgeDisplayResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[193] + mi := &file_proto_activity_v1_activity_proto_msgTypes[200] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15584,7 +16109,7 @@ func (x *SetBadgeDisplayResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetBadgeDisplayResponse.ProtoReflect.Descriptor instead. func (*SetBadgeDisplayResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{193} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{200} } func (x *SetBadgeDisplayResponse) GetProfile() *ListMyBadgesResponse { @@ -15621,7 +16146,7 @@ type UpsertAchievementDefinitionRequest struct { func (x *UpsertAchievementDefinitionRequest) Reset() { *x = UpsertAchievementDefinitionRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[194] + mi := &file_proto_activity_v1_activity_proto_msgTypes[201] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15633,7 +16158,7 @@ func (x *UpsertAchievementDefinitionRequest) String() string { func (*UpsertAchievementDefinitionRequest) ProtoMessage() {} func (x *UpsertAchievementDefinitionRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[194] + mi := &file_proto_activity_v1_activity_proto_msgTypes[201] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15646,7 +16171,7 @@ func (x *UpsertAchievementDefinitionRequest) ProtoReflect() protoreflect.Message // Deprecated: Use UpsertAchievementDefinitionRequest.ProtoReflect.Descriptor instead. func (*UpsertAchievementDefinitionRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{194} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{201} } func (x *UpsertAchievementDefinitionRequest) GetMeta() *RequestMeta { @@ -15786,7 +16311,7 @@ type UpsertAchievementDefinitionResponse struct { func (x *UpsertAchievementDefinitionResponse) Reset() { *x = UpsertAchievementDefinitionResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[195] + mi := &file_proto_activity_v1_activity_proto_msgTypes[202] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15798,7 +16323,7 @@ func (x *UpsertAchievementDefinitionResponse) String() string { func (*UpsertAchievementDefinitionResponse) ProtoMessage() {} func (x *UpsertAchievementDefinitionResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[195] + mi := &file_proto_activity_v1_activity_proto_msgTypes[202] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15811,7 +16336,7 @@ func (x *UpsertAchievementDefinitionResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use UpsertAchievementDefinitionResponse.ProtoReflect.Descriptor instead. func (*UpsertAchievementDefinitionResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{195} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{202} } func (x *UpsertAchievementDefinitionResponse) GetAchievement() *AchievementDefinition { @@ -15840,7 +16365,7 @@ type DeleteAchievementDefinitionRequest struct { func (x *DeleteAchievementDefinitionRequest) Reset() { *x = DeleteAchievementDefinitionRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[196] + mi := &file_proto_activity_v1_activity_proto_msgTypes[203] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15852,7 +16377,7 @@ func (x *DeleteAchievementDefinitionRequest) String() string { func (*DeleteAchievementDefinitionRequest) ProtoMessage() {} func (x *DeleteAchievementDefinitionRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[196] + mi := &file_proto_activity_v1_activity_proto_msgTypes[203] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15865,7 +16390,7 @@ func (x *DeleteAchievementDefinitionRequest) ProtoReflect() protoreflect.Message // Deprecated: Use DeleteAchievementDefinitionRequest.ProtoReflect.Descriptor instead. func (*DeleteAchievementDefinitionRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{196} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{203} } func (x *DeleteAchievementDefinitionRequest) GetMeta() *RequestMeta { @@ -15899,7 +16424,7 @@ type DeleteAchievementDefinitionResponse struct { func (x *DeleteAchievementDefinitionResponse) Reset() { *x = DeleteAchievementDefinitionResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[197] + mi := &file_proto_activity_v1_activity_proto_msgTypes[204] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15911,7 +16436,7 @@ func (x *DeleteAchievementDefinitionResponse) String() string { func (*DeleteAchievementDefinitionResponse) ProtoMessage() {} func (x *DeleteAchievementDefinitionResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[197] + mi := &file_proto_activity_v1_activity_proto_msgTypes[204] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15924,7 +16449,7 @@ func (x *DeleteAchievementDefinitionResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use DeleteAchievementDefinitionResponse.ProtoReflect.Descriptor instead. func (*DeleteAchievementDefinitionResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{197} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{204} } func (x *DeleteAchievementDefinitionResponse) GetAchievement() *AchievementDefinition { @@ -15953,7 +16478,7 @@ type WheelPrizeTier struct { func (x *WheelPrizeTier) Reset() { *x = WheelPrizeTier{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[198] + mi := &file_proto_activity_v1_activity_proto_msgTypes[205] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15965,7 +16490,7 @@ func (x *WheelPrizeTier) String() string { func (*WheelPrizeTier) ProtoMessage() {} func (x *WheelPrizeTier) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[198] + mi := &file_proto_activity_v1_activity_proto_msgTypes[205] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15978,7 +16503,7 @@ func (x *WheelPrizeTier) ProtoReflect() protoreflect.Message { // Deprecated: Use WheelPrizeTier.ProtoReflect.Descriptor instead. func (*WheelPrizeTier) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{198} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{205} } func (x *WheelPrizeTier) GetTierId() string { @@ -16075,7 +16600,7 @@ type WheelRuleConfig struct { func (x *WheelRuleConfig) Reset() { *x = WheelRuleConfig{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[199] + mi := &file_proto_activity_v1_activity_proto_msgTypes[206] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16087,7 +16612,7 @@ func (x *WheelRuleConfig) String() string { func (*WheelRuleConfig) ProtoMessage() {} func (x *WheelRuleConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[199] + mi := &file_proto_activity_v1_activity_proto_msgTypes[206] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16100,7 +16625,7 @@ func (x *WheelRuleConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use WheelRuleConfig.ProtoReflect.Descriptor instead. func (*WheelRuleConfig) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{199} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{206} } func (x *WheelRuleConfig) GetAppCode() string { @@ -16226,7 +16751,7 @@ type WheelDrawMeta struct { func (x *WheelDrawMeta) Reset() { *x = WheelDrawMeta{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[200] + mi := &file_proto_activity_v1_activity_proto_msgTypes[207] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16238,7 +16763,7 @@ func (x *WheelDrawMeta) String() string { func (*WheelDrawMeta) ProtoMessage() {} func (x *WheelDrawMeta) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[200] + mi := &file_proto_activity_v1_activity_proto_msgTypes[207] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16251,7 +16776,7 @@ func (x *WheelDrawMeta) ProtoReflect() protoreflect.Message { // Deprecated: Use WheelDrawMeta.ProtoReflect.Descriptor instead. func (*WheelDrawMeta) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{200} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{207} } func (x *WheelDrawMeta) GetMeta() *RequestMeta { @@ -16345,7 +16870,7 @@ type WheelDrawResult struct { func (x *WheelDrawResult) Reset() { *x = WheelDrawResult{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[201] + mi := &file_proto_activity_v1_activity_proto_msgTypes[208] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16357,7 +16882,7 @@ func (x *WheelDrawResult) String() string { func (*WheelDrawResult) ProtoMessage() {} func (x *WheelDrawResult) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[201] + mi := &file_proto_activity_v1_activity_proto_msgTypes[208] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16370,7 +16895,7 @@ func (x *WheelDrawResult) ProtoReflect() protoreflect.Message { // Deprecated: Use WheelDrawResult.ProtoReflect.Descriptor instead. func (*WheelDrawResult) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{201} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{208} } func (x *WheelDrawResult) GetDrawId() string { @@ -16523,7 +17048,7 @@ type WheelDrawReward struct { func (x *WheelDrawReward) Reset() { *x = WheelDrawReward{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[202] + mi := &file_proto_activity_v1_activity_proto_msgTypes[209] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16535,7 +17060,7 @@ func (x *WheelDrawReward) String() string { func (*WheelDrawReward) ProtoMessage() {} func (x *WheelDrawReward) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[202] + mi := &file_proto_activity_v1_activity_proto_msgTypes[209] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16548,7 +17073,7 @@ func (x *WheelDrawReward) ProtoReflect() protoreflect.Message { // Deprecated: Use WheelDrawReward.ProtoReflect.Descriptor instead. func (*WheelDrawReward) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{202} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{209} } func (x *WheelDrawReward) GetSelectedTierId() string { @@ -16617,7 +17142,7 @@ type ExecuteWheelDrawRequest struct { func (x *ExecuteWheelDrawRequest) Reset() { *x = ExecuteWheelDrawRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[203] + mi := &file_proto_activity_v1_activity_proto_msgTypes[210] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16629,7 +17154,7 @@ func (x *ExecuteWheelDrawRequest) String() string { func (*ExecuteWheelDrawRequest) ProtoMessage() {} func (x *ExecuteWheelDrawRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[203] + mi := &file_proto_activity_v1_activity_proto_msgTypes[210] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16642,7 +17167,7 @@ func (x *ExecuteWheelDrawRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecuteWheelDrawRequest.ProtoReflect.Descriptor instead. func (*ExecuteWheelDrawRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{203} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{210} } func (x *ExecuteWheelDrawRequest) GetWheel() *WheelDrawMeta { @@ -16662,7 +17187,7 @@ type ExecuteWheelDrawResponse struct { func (x *ExecuteWheelDrawResponse) Reset() { *x = ExecuteWheelDrawResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[204] + mi := &file_proto_activity_v1_activity_proto_msgTypes[211] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16674,7 +17199,7 @@ func (x *ExecuteWheelDrawResponse) String() string { func (*ExecuteWheelDrawResponse) ProtoMessage() {} func (x *ExecuteWheelDrawResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[204] + mi := &file_proto_activity_v1_activity_proto_msgTypes[211] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16687,7 +17212,7 @@ func (x *ExecuteWheelDrawResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecuteWheelDrawResponse.ProtoReflect.Descriptor instead. func (*ExecuteWheelDrawResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{204} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{211} } func (x *ExecuteWheelDrawResponse) GetResult() *WheelDrawResult { @@ -16708,7 +17233,7 @@ type GetWheelConfigRequest struct { func (x *GetWheelConfigRequest) Reset() { *x = GetWheelConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[205] + mi := &file_proto_activity_v1_activity_proto_msgTypes[212] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16720,7 +17245,7 @@ func (x *GetWheelConfigRequest) String() string { func (*GetWheelConfigRequest) ProtoMessage() {} func (x *GetWheelConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[205] + mi := &file_proto_activity_v1_activity_proto_msgTypes[212] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16733,7 +17258,7 @@ func (x *GetWheelConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWheelConfigRequest.ProtoReflect.Descriptor instead. func (*GetWheelConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{205} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{212} } func (x *GetWheelConfigRequest) GetMeta() *RequestMeta { @@ -16760,7 +17285,7 @@ type GetWheelConfigResponse struct { func (x *GetWheelConfigResponse) Reset() { *x = GetWheelConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[206] + mi := &file_proto_activity_v1_activity_proto_msgTypes[213] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16772,7 +17297,7 @@ func (x *GetWheelConfigResponse) String() string { func (*GetWheelConfigResponse) ProtoMessage() {} func (x *GetWheelConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[206] + mi := &file_proto_activity_v1_activity_proto_msgTypes[213] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16785,7 +17310,7 @@ func (x *GetWheelConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWheelConfigResponse.ProtoReflect.Descriptor instead. func (*GetWheelConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{206} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{213} } func (x *GetWheelConfigResponse) GetConfig() *WheelRuleConfig { @@ -16807,7 +17332,7 @@ type UpsertWheelConfigRequest struct { func (x *UpsertWheelConfigRequest) Reset() { *x = UpsertWheelConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[207] + mi := &file_proto_activity_v1_activity_proto_msgTypes[214] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16819,7 +17344,7 @@ func (x *UpsertWheelConfigRequest) String() string { func (*UpsertWheelConfigRequest) ProtoMessage() {} func (x *UpsertWheelConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[207] + mi := &file_proto_activity_v1_activity_proto_msgTypes[214] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16832,7 +17357,7 @@ func (x *UpsertWheelConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertWheelConfigRequest.ProtoReflect.Descriptor instead. func (*UpsertWheelConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{207} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{214} } func (x *UpsertWheelConfigRequest) GetMeta() *RequestMeta { @@ -16866,7 +17391,7 @@ type UpsertWheelConfigResponse struct { func (x *UpsertWheelConfigResponse) Reset() { *x = UpsertWheelConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[208] + mi := &file_proto_activity_v1_activity_proto_msgTypes[215] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16878,7 +17403,7 @@ func (x *UpsertWheelConfigResponse) String() string { func (*UpsertWheelConfigResponse) ProtoMessage() {} func (x *UpsertWheelConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[208] + mi := &file_proto_activity_v1_activity_proto_msgTypes[215] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16891,7 +17416,7 @@ func (x *UpsertWheelConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertWheelConfigResponse.ProtoReflect.Descriptor instead. func (*UpsertWheelConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{208} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{215} } func (x *UpsertWheelConfigResponse) GetConfig() *WheelRuleConfig { @@ -16916,7 +17441,7 @@ type ListWheelDrawsRequest struct { func (x *ListWheelDrawsRequest) Reset() { *x = ListWheelDrawsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[209] + mi := &file_proto_activity_v1_activity_proto_msgTypes[216] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16928,7 +17453,7 @@ func (x *ListWheelDrawsRequest) String() string { func (*ListWheelDrawsRequest) ProtoMessage() {} func (x *ListWheelDrawsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[209] + mi := &file_proto_activity_v1_activity_proto_msgTypes[216] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16941,7 +17466,7 @@ func (x *ListWheelDrawsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWheelDrawsRequest.ProtoReflect.Descriptor instead. func (*ListWheelDrawsRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{209} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{216} } func (x *ListWheelDrawsRequest) GetMeta() *RequestMeta { @@ -16997,7 +17522,7 @@ type ListWheelDrawsResponse struct { func (x *ListWheelDrawsResponse) Reset() { *x = ListWheelDrawsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[210] + mi := &file_proto_activity_v1_activity_proto_msgTypes[217] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17009,7 +17534,7 @@ func (x *ListWheelDrawsResponse) String() string { func (*ListWheelDrawsResponse) ProtoMessage() {} func (x *ListWheelDrawsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[210] + mi := &file_proto_activity_v1_activity_proto_msgTypes[217] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17022,7 +17547,7 @@ func (x *ListWheelDrawsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWheelDrawsResponse.ProtoReflect.Descriptor instead. func (*ListWheelDrawsResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{210} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{217} } func (x *ListWheelDrawsResponse) GetDraws() []*WheelDrawResult { @@ -17057,7 +17582,7 @@ type WheelDrawSummary struct { func (x *WheelDrawSummary) Reset() { *x = WheelDrawSummary{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[211] + mi := &file_proto_activity_v1_activity_proto_msgTypes[218] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17069,7 +17594,7 @@ func (x *WheelDrawSummary) String() string { func (*WheelDrawSummary) ProtoMessage() {} func (x *WheelDrawSummary) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[211] + mi := &file_proto_activity_v1_activity_proto_msgTypes[218] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17082,7 +17607,7 @@ func (x *WheelDrawSummary) ProtoReflect() protoreflect.Message { // Deprecated: Use WheelDrawSummary.ProtoReflect.Descriptor instead. func (*WheelDrawSummary) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{211} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{218} } func (x *WheelDrawSummary) GetWheelId() string { @@ -17161,7 +17686,7 @@ type GetWheelDrawSummaryRequest struct { func (x *GetWheelDrawSummaryRequest) Reset() { *x = GetWheelDrawSummaryRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[212] + mi := &file_proto_activity_v1_activity_proto_msgTypes[219] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17173,7 +17698,7 @@ func (x *GetWheelDrawSummaryRequest) String() string { func (*GetWheelDrawSummaryRequest) ProtoMessage() {} func (x *GetWheelDrawSummaryRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[212] + mi := &file_proto_activity_v1_activity_proto_msgTypes[219] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17186,7 +17711,7 @@ func (x *GetWheelDrawSummaryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWheelDrawSummaryRequest.ProtoReflect.Descriptor instead. func (*GetWheelDrawSummaryRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{212} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{219} } func (x *GetWheelDrawSummaryRequest) GetMeta() *RequestMeta { @@ -17227,7 +17752,7 @@ type GetWheelDrawSummaryResponse struct { func (x *GetWheelDrawSummaryResponse) Reset() { *x = GetWheelDrawSummaryResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[213] + mi := &file_proto_activity_v1_activity_proto_msgTypes[220] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17239,7 +17764,7 @@ func (x *GetWheelDrawSummaryResponse) String() string { func (*GetWheelDrawSummaryResponse) ProtoMessage() {} func (x *GetWheelDrawSummaryResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[213] + mi := &file_proto_activity_v1_activity_proto_msgTypes[220] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17252,7 +17777,7 @@ func (x *GetWheelDrawSummaryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWheelDrawSummaryResponse.ProtoReflect.Descriptor instead. func (*GetWheelDrawSummaryResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{213} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{220} } func (x *GetWheelDrawSummaryResponse) GetSummary() *WheelDrawSummary { @@ -17274,7 +17799,7 @@ type WeeklyStarGift struct { func (x *WeeklyStarGift) Reset() { *x = WeeklyStarGift{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[214] + mi := &file_proto_activity_v1_activity_proto_msgTypes[221] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17286,7 +17811,7 @@ func (x *WeeklyStarGift) String() string { func (*WeeklyStarGift) ProtoMessage() {} func (x *WeeklyStarGift) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[214] + mi := &file_proto_activity_v1_activity_proto_msgTypes[221] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17299,7 +17824,7 @@ func (x *WeeklyStarGift) ProtoReflect() protoreflect.Message { // Deprecated: Use WeeklyStarGift.ProtoReflect.Descriptor instead. func (*WeeklyStarGift) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{214} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{221} } func (x *WeeklyStarGift) GetGiftId() string { @@ -17328,7 +17853,7 @@ type WeeklyStarReward struct { func (x *WeeklyStarReward) Reset() { *x = WeeklyStarReward{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[215] + mi := &file_proto_activity_v1_activity_proto_msgTypes[222] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17340,7 +17865,7 @@ func (x *WeeklyStarReward) String() string { func (*WeeklyStarReward) ProtoMessage() {} func (x *WeeklyStarReward) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[215] + mi := &file_proto_activity_v1_activity_proto_msgTypes[222] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17353,7 +17878,7 @@ func (x *WeeklyStarReward) ProtoReflect() protoreflect.Message { // Deprecated: Use WeeklyStarReward.ProtoReflect.Descriptor instead. func (*WeeklyStarReward) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{215} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{222} } func (x *WeeklyStarReward) GetRankNo() int32 { @@ -17395,7 +17920,7 @@ type WeeklyStarCycle struct { func (x *WeeklyStarCycle) Reset() { *x = WeeklyStarCycle{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[216] + mi := &file_proto_activity_v1_activity_proto_msgTypes[223] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17407,7 +17932,7 @@ func (x *WeeklyStarCycle) String() string { func (*WeeklyStarCycle) ProtoMessage() {} func (x *WeeklyStarCycle) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[216] + mi := &file_proto_activity_v1_activity_proto_msgTypes[223] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17420,7 +17945,7 @@ func (x *WeeklyStarCycle) ProtoReflect() protoreflect.Message { // Deprecated: Use WeeklyStarCycle.ProtoReflect.Descriptor instead. func (*WeeklyStarCycle) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{216} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{223} } func (x *WeeklyStarCycle) GetCycleId() string { @@ -17543,7 +18068,7 @@ type WeeklyStarLeaderboardEntry struct { func (x *WeeklyStarLeaderboardEntry) Reset() { *x = WeeklyStarLeaderboardEntry{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[217] + mi := &file_proto_activity_v1_activity_proto_msgTypes[224] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17555,7 +18080,7 @@ func (x *WeeklyStarLeaderboardEntry) String() string { func (*WeeklyStarLeaderboardEntry) ProtoMessage() {} func (x *WeeklyStarLeaderboardEntry) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[217] + mi := &file_proto_activity_v1_activity_proto_msgTypes[224] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17568,7 +18093,7 @@ func (x *WeeklyStarLeaderboardEntry) ProtoReflect() protoreflect.Message { // Deprecated: Use WeeklyStarLeaderboardEntry.ProtoReflect.Descriptor instead. func (*WeeklyStarLeaderboardEntry) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{217} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{224} } func (x *WeeklyStarLeaderboardEntry) GetRankNo() int32 { @@ -17629,7 +18154,7 @@ type WeeklyStarSettlement struct { func (x *WeeklyStarSettlement) Reset() { *x = WeeklyStarSettlement{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[218] + mi := &file_proto_activity_v1_activity_proto_msgTypes[225] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17641,7 +18166,7 @@ func (x *WeeklyStarSettlement) String() string { func (*WeeklyStarSettlement) ProtoMessage() {} func (x *WeeklyStarSettlement) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[218] + mi := &file_proto_activity_v1_activity_proto_msgTypes[225] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17654,7 +18179,7 @@ func (x *WeeklyStarSettlement) ProtoReflect() protoreflect.Message { // Deprecated: Use WeeklyStarSettlement.ProtoReflect.Descriptor instead. func (*WeeklyStarSettlement) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{218} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{225} } func (x *WeeklyStarSettlement) GetSettlementId() string { @@ -17764,7 +18289,7 @@ type ListWeeklyStarCyclesRequest struct { func (x *ListWeeklyStarCyclesRequest) Reset() { *x = ListWeeklyStarCyclesRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[219] + mi := &file_proto_activity_v1_activity_proto_msgTypes[226] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17776,7 +18301,7 @@ func (x *ListWeeklyStarCyclesRequest) String() string { func (*ListWeeklyStarCyclesRequest) ProtoMessage() {} func (x *ListWeeklyStarCyclesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[219] + mi := &file_proto_activity_v1_activity_proto_msgTypes[226] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17789,7 +18314,7 @@ func (x *ListWeeklyStarCyclesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWeeklyStarCyclesRequest.ProtoReflect.Descriptor instead. func (*ListWeeklyStarCyclesRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{219} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{226} } func (x *ListWeeklyStarCyclesRequest) GetMeta() *RequestMeta { @@ -17852,7 +18377,7 @@ type ListWeeklyStarCyclesResponse struct { func (x *ListWeeklyStarCyclesResponse) Reset() { *x = ListWeeklyStarCyclesResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[220] + mi := &file_proto_activity_v1_activity_proto_msgTypes[227] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17864,7 +18389,7 @@ func (x *ListWeeklyStarCyclesResponse) String() string { func (*ListWeeklyStarCyclesResponse) ProtoMessage() {} func (x *ListWeeklyStarCyclesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[220] + mi := &file_proto_activity_v1_activity_proto_msgTypes[227] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17877,7 +18402,7 @@ func (x *ListWeeklyStarCyclesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWeeklyStarCyclesResponse.ProtoReflect.Descriptor instead. func (*ListWeeklyStarCyclesResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{220} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{227} } func (x *ListWeeklyStarCyclesResponse) GetCycles() []*WeeklyStarCycle { @@ -17905,7 +18430,7 @@ type GetWeeklyStarCycleRequest struct { func (x *GetWeeklyStarCycleRequest) Reset() { *x = GetWeeklyStarCycleRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[221] + mi := &file_proto_activity_v1_activity_proto_msgTypes[228] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17917,7 +18442,7 @@ func (x *GetWeeklyStarCycleRequest) String() string { func (*GetWeeklyStarCycleRequest) ProtoMessage() {} func (x *GetWeeklyStarCycleRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[221] + mi := &file_proto_activity_v1_activity_proto_msgTypes[228] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17930,7 +18455,7 @@ func (x *GetWeeklyStarCycleRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWeeklyStarCycleRequest.ProtoReflect.Descriptor instead. func (*GetWeeklyStarCycleRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{221} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{228} } func (x *GetWeeklyStarCycleRequest) GetMeta() *RequestMeta { @@ -17957,7 +18482,7 @@ type GetWeeklyStarCycleResponse struct { func (x *GetWeeklyStarCycleResponse) Reset() { *x = GetWeeklyStarCycleResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[222] + mi := &file_proto_activity_v1_activity_proto_msgTypes[229] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17969,7 +18494,7 @@ func (x *GetWeeklyStarCycleResponse) String() string { func (*GetWeeklyStarCycleResponse) ProtoMessage() {} func (x *GetWeeklyStarCycleResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[222] + mi := &file_proto_activity_v1_activity_proto_msgTypes[229] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17982,7 +18507,7 @@ func (x *GetWeeklyStarCycleResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWeeklyStarCycleResponse.ProtoReflect.Descriptor instead. func (*GetWeeklyStarCycleResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{222} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{229} } func (x *GetWeeklyStarCycleResponse) GetCycle() *WeeklyStarCycle { @@ -18004,7 +18529,7 @@ type UpsertWeeklyStarCycleRequest struct { func (x *UpsertWeeklyStarCycleRequest) Reset() { *x = UpsertWeeklyStarCycleRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[223] + mi := &file_proto_activity_v1_activity_proto_msgTypes[230] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18016,7 +18541,7 @@ func (x *UpsertWeeklyStarCycleRequest) String() string { func (*UpsertWeeklyStarCycleRequest) ProtoMessage() {} func (x *UpsertWeeklyStarCycleRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[223] + mi := &file_proto_activity_v1_activity_proto_msgTypes[230] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18029,7 +18554,7 @@ func (x *UpsertWeeklyStarCycleRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertWeeklyStarCycleRequest.ProtoReflect.Descriptor instead. func (*UpsertWeeklyStarCycleRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{223} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{230} } func (x *UpsertWeeklyStarCycleRequest) GetMeta() *RequestMeta { @@ -18064,7 +18589,7 @@ type UpsertWeeklyStarCycleResponse struct { func (x *UpsertWeeklyStarCycleResponse) Reset() { *x = UpsertWeeklyStarCycleResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[224] + mi := &file_proto_activity_v1_activity_proto_msgTypes[231] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18076,7 +18601,7 @@ func (x *UpsertWeeklyStarCycleResponse) String() string { func (*UpsertWeeklyStarCycleResponse) ProtoMessage() {} func (x *UpsertWeeklyStarCycleResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[224] + mi := &file_proto_activity_v1_activity_proto_msgTypes[231] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18089,7 +18614,7 @@ func (x *UpsertWeeklyStarCycleResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertWeeklyStarCycleResponse.ProtoReflect.Descriptor instead. func (*UpsertWeeklyStarCycleResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{224} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{231} } func (x *UpsertWeeklyStarCycleResponse) GetCycle() *WeeklyStarCycle { @@ -18119,7 +18644,7 @@ type SetWeeklyStarCycleStatusRequest struct { func (x *SetWeeklyStarCycleStatusRequest) Reset() { *x = SetWeeklyStarCycleStatusRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[225] + mi := &file_proto_activity_v1_activity_proto_msgTypes[232] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18131,7 +18656,7 @@ func (x *SetWeeklyStarCycleStatusRequest) String() string { func (*SetWeeklyStarCycleStatusRequest) ProtoMessage() {} func (x *SetWeeklyStarCycleStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[225] + mi := &file_proto_activity_v1_activity_proto_msgTypes[232] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18144,7 +18669,7 @@ func (x *SetWeeklyStarCycleStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetWeeklyStarCycleStatusRequest.ProtoReflect.Descriptor instead. func (*SetWeeklyStarCycleStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{225} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{232} } func (x *SetWeeklyStarCycleStatusRequest) GetMeta() *RequestMeta { @@ -18185,7 +18710,7 @@ type SetWeeklyStarCycleStatusResponse struct { func (x *SetWeeklyStarCycleStatusResponse) Reset() { *x = SetWeeklyStarCycleStatusResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[226] + mi := &file_proto_activity_v1_activity_proto_msgTypes[233] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18197,7 +18722,7 @@ func (x *SetWeeklyStarCycleStatusResponse) String() string { func (*SetWeeklyStarCycleStatusResponse) ProtoMessage() {} func (x *SetWeeklyStarCycleStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[226] + mi := &file_proto_activity_v1_activity_proto_msgTypes[233] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18210,7 +18735,7 @@ func (x *SetWeeklyStarCycleStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetWeeklyStarCycleStatusResponse.ProtoReflect.Descriptor instead. func (*SetWeeklyStarCycleStatusResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{226} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{233} } func (x *SetWeeklyStarCycleStatusResponse) GetCycle() *WeeklyStarCycle { @@ -18234,7 +18759,7 @@ type ListWeeklyStarLeaderboardRequest struct { func (x *ListWeeklyStarLeaderboardRequest) Reset() { *x = ListWeeklyStarLeaderboardRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[227] + mi := &file_proto_activity_v1_activity_proto_msgTypes[234] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18246,7 +18771,7 @@ func (x *ListWeeklyStarLeaderboardRequest) String() string { func (*ListWeeklyStarLeaderboardRequest) ProtoMessage() {} func (x *ListWeeklyStarLeaderboardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[227] + mi := &file_proto_activity_v1_activity_proto_msgTypes[234] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18259,7 +18784,7 @@ func (x *ListWeeklyStarLeaderboardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWeeklyStarLeaderboardRequest.ProtoReflect.Descriptor instead. func (*ListWeeklyStarLeaderboardRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{227} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{234} } func (x *ListWeeklyStarLeaderboardRequest) GetMeta() *RequestMeta { @@ -18310,7 +18835,7 @@ type ListWeeklyStarLeaderboardResponse struct { func (x *ListWeeklyStarLeaderboardResponse) Reset() { *x = ListWeeklyStarLeaderboardResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[228] + mi := &file_proto_activity_v1_activity_proto_msgTypes[235] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18322,7 +18847,7 @@ func (x *ListWeeklyStarLeaderboardResponse) String() string { func (*ListWeeklyStarLeaderboardResponse) ProtoMessage() {} func (x *ListWeeklyStarLeaderboardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[228] + mi := &file_proto_activity_v1_activity_proto_msgTypes[235] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18335,7 +18860,7 @@ func (x *ListWeeklyStarLeaderboardResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ListWeeklyStarLeaderboardResponse.ProtoReflect.Descriptor instead. func (*ListWeeklyStarLeaderboardResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{228} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{235} } func (x *ListWeeklyStarLeaderboardResponse) GetCycle() *WeeklyStarCycle { @@ -18377,7 +18902,7 @@ type ListWeeklyStarSettlementsRequest struct { func (x *ListWeeklyStarSettlementsRequest) Reset() { *x = ListWeeklyStarSettlementsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[229] + mi := &file_proto_activity_v1_activity_proto_msgTypes[236] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18389,7 +18914,7 @@ func (x *ListWeeklyStarSettlementsRequest) String() string { func (*ListWeeklyStarSettlementsRequest) ProtoMessage() {} func (x *ListWeeklyStarSettlementsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[229] + mi := &file_proto_activity_v1_activity_proto_msgTypes[236] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18402,7 +18927,7 @@ func (x *ListWeeklyStarSettlementsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWeeklyStarSettlementsRequest.ProtoReflect.Descriptor instead. func (*ListWeeklyStarSettlementsRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{229} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{236} } func (x *ListWeeklyStarSettlementsRequest) GetMeta() *RequestMeta { @@ -18429,7 +18954,7 @@ type ListWeeklyStarSettlementsResponse struct { func (x *ListWeeklyStarSettlementsResponse) Reset() { *x = ListWeeklyStarSettlementsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[230] + mi := &file_proto_activity_v1_activity_proto_msgTypes[237] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18441,7 +18966,7 @@ func (x *ListWeeklyStarSettlementsResponse) String() string { func (*ListWeeklyStarSettlementsResponse) ProtoMessage() {} func (x *ListWeeklyStarSettlementsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[230] + mi := &file_proto_activity_v1_activity_proto_msgTypes[237] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18454,7 +18979,7 @@ func (x *ListWeeklyStarSettlementsResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ListWeeklyStarSettlementsResponse.ProtoReflect.Descriptor instead. func (*ListWeeklyStarSettlementsResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{230} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{237} } func (x *ListWeeklyStarSettlementsResponse) GetSettlements() []*WeeklyStarSettlement { @@ -18476,7 +19001,7 @@ type GetWeeklyStarCurrentRequest struct { func (x *GetWeeklyStarCurrentRequest) Reset() { *x = GetWeeklyStarCurrentRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[231] + mi := &file_proto_activity_v1_activity_proto_msgTypes[238] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18488,7 +19013,7 @@ func (x *GetWeeklyStarCurrentRequest) String() string { func (*GetWeeklyStarCurrentRequest) ProtoMessage() {} func (x *GetWeeklyStarCurrentRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[231] + mi := &file_proto_activity_v1_activity_proto_msgTypes[238] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18501,7 +19026,7 @@ func (x *GetWeeklyStarCurrentRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWeeklyStarCurrentRequest.ProtoReflect.Descriptor instead. func (*GetWeeklyStarCurrentRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{231} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{238} } func (x *GetWeeklyStarCurrentRequest) GetMeta() *RequestMeta { @@ -18538,7 +19063,7 @@ type GetWeeklyStarCurrentResponse struct { func (x *GetWeeklyStarCurrentResponse) Reset() { *x = GetWeeklyStarCurrentResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[232] + mi := &file_proto_activity_v1_activity_proto_msgTypes[239] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18550,7 +19075,7 @@ func (x *GetWeeklyStarCurrentResponse) String() string { func (*GetWeeklyStarCurrentResponse) ProtoMessage() {} func (x *GetWeeklyStarCurrentResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[232] + mi := &file_proto_activity_v1_activity_proto_msgTypes[239] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18563,7 +19088,7 @@ func (x *GetWeeklyStarCurrentResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWeeklyStarCurrentResponse.ProtoReflect.Descriptor instead. func (*GetWeeklyStarCurrentResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{232} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{239} } func (x *GetWeeklyStarCurrentResponse) GetCycle() *WeeklyStarCycle { @@ -18606,7 +19131,7 @@ type ListWeeklyStarHistoryRequest struct { func (x *ListWeeklyStarHistoryRequest) Reset() { *x = ListWeeklyStarHistoryRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[233] + mi := &file_proto_activity_v1_activity_proto_msgTypes[240] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18618,7 +19143,7 @@ func (x *ListWeeklyStarHistoryRequest) String() string { func (*ListWeeklyStarHistoryRequest) ProtoMessage() {} func (x *ListWeeklyStarHistoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[233] + mi := &file_proto_activity_v1_activity_proto_msgTypes[240] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18631,7 +19156,7 @@ func (x *ListWeeklyStarHistoryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWeeklyStarHistoryRequest.ProtoReflect.Descriptor instead. func (*ListWeeklyStarHistoryRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{233} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{240} } func (x *ListWeeklyStarHistoryRequest) GetMeta() *RequestMeta { @@ -18666,7 +19191,7 @@ type WeeklyStarHistoryCycle struct { func (x *WeeklyStarHistoryCycle) Reset() { *x = WeeklyStarHistoryCycle{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[234] + mi := &file_proto_activity_v1_activity_proto_msgTypes[241] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18678,7 +19203,7 @@ func (x *WeeklyStarHistoryCycle) String() string { func (*WeeklyStarHistoryCycle) ProtoMessage() {} func (x *WeeklyStarHistoryCycle) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[234] + mi := &file_proto_activity_v1_activity_proto_msgTypes[241] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18691,7 +19216,7 @@ func (x *WeeklyStarHistoryCycle) ProtoReflect() protoreflect.Message { // Deprecated: Use WeeklyStarHistoryCycle.ProtoReflect.Descriptor instead. func (*WeeklyStarHistoryCycle) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{234} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{241} } func (x *WeeklyStarHistoryCycle) GetCycle() *WeeklyStarCycle { @@ -18719,7 +19244,7 @@ type ListWeeklyStarHistoryResponse struct { func (x *ListWeeklyStarHistoryResponse) Reset() { *x = ListWeeklyStarHistoryResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[235] + mi := &file_proto_activity_v1_activity_proto_msgTypes[242] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18731,7 +19256,7 @@ func (x *ListWeeklyStarHistoryResponse) String() string { func (*ListWeeklyStarHistoryResponse) ProtoMessage() {} func (x *ListWeeklyStarHistoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[235] + mi := &file_proto_activity_v1_activity_proto_msgTypes[242] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18744,7 +19269,7 @@ func (x *ListWeeklyStarHistoryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWeeklyStarHistoryResponse.ProtoReflect.Descriptor instead. func (*ListWeeklyStarHistoryResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{235} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{242} } func (x *ListWeeklyStarHistoryResponse) GetCycles() []*WeeklyStarHistoryCycle { @@ -18773,7 +19298,7 @@ type CPWeeklyRankReward struct { func (x *CPWeeklyRankReward) Reset() { *x = CPWeeklyRankReward{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[236] + mi := &file_proto_activity_v1_activity_proto_msgTypes[243] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18785,7 +19310,7 @@ func (x *CPWeeklyRankReward) String() string { func (*CPWeeklyRankReward) ProtoMessage() {} func (x *CPWeeklyRankReward) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[236] + mi := &file_proto_activity_v1_activity_proto_msgTypes[243] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18798,7 +19323,7 @@ func (x *CPWeeklyRankReward) ProtoReflect() protoreflect.Message { // Deprecated: Use CPWeeklyRankReward.ProtoReflect.Descriptor instead. func (*CPWeeklyRankReward) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{236} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{243} } func (x *CPWeeklyRankReward) GetRankNo() int32 { @@ -18834,7 +19359,7 @@ type CPWeeklyRankConfig struct { func (x *CPWeeklyRankConfig) Reset() { *x = CPWeeklyRankConfig{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[237] + mi := &file_proto_activity_v1_activity_proto_msgTypes[244] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18846,7 +19371,7 @@ func (x *CPWeeklyRankConfig) String() string { func (*CPWeeklyRankConfig) ProtoMessage() {} func (x *CPWeeklyRankConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[237] + mi := &file_proto_activity_v1_activity_proto_msgTypes[244] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18859,7 +19384,7 @@ func (x *CPWeeklyRankConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use CPWeeklyRankConfig.ProtoReflect.Descriptor instead. func (*CPWeeklyRankConfig) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{237} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{244} } func (x *CPWeeklyRankConfig) GetActivityCode() string { @@ -18939,7 +19464,7 @@ type CPWeeklyRankUser struct { func (x *CPWeeklyRankUser) Reset() { *x = CPWeeklyRankUser{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[238] + mi := &file_proto_activity_v1_activity_proto_msgTypes[245] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18951,7 +19476,7 @@ func (x *CPWeeklyRankUser) String() string { func (*CPWeeklyRankUser) ProtoMessage() {} func (x *CPWeeklyRankUser) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[238] + mi := &file_proto_activity_v1_activity_proto_msgTypes[245] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18964,7 +19489,7 @@ func (x *CPWeeklyRankUser) ProtoReflect() protoreflect.Message { // Deprecated: Use CPWeeklyRankUser.ProtoReflect.Descriptor instead. func (*CPWeeklyRankUser) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{238} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{245} } func (x *CPWeeklyRankUser) GetUserId() int64 { @@ -19015,7 +19540,7 @@ type CPWeeklyRankEntry struct { func (x *CPWeeklyRankEntry) Reset() { *x = CPWeeklyRankEntry{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[239] + mi := &file_proto_activity_v1_activity_proto_msgTypes[246] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19027,7 +19552,7 @@ func (x *CPWeeklyRankEntry) String() string { func (*CPWeeklyRankEntry) ProtoMessage() {} func (x *CPWeeklyRankEntry) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[239] + mi := &file_proto_activity_v1_activity_proto_msgTypes[246] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19040,7 +19565,7 @@ func (x *CPWeeklyRankEntry) ProtoReflect() protoreflect.Message { // Deprecated: Use CPWeeklyRankEntry.ProtoReflect.Descriptor instead. func (*CPWeeklyRankEntry) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{239} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{246} } func (x *CPWeeklyRankEntry) GetRank() int64 { @@ -19138,7 +19663,7 @@ type CPWeeklyRankSettlement struct { func (x *CPWeeklyRankSettlement) Reset() { *x = CPWeeklyRankSettlement{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[240] + mi := &file_proto_activity_v1_activity_proto_msgTypes[247] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19150,7 +19675,7 @@ func (x *CPWeeklyRankSettlement) String() string { func (*CPWeeklyRankSettlement) ProtoMessage() {} func (x *CPWeeklyRankSettlement) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[240] + mi := &file_proto_activity_v1_activity_proto_msgTypes[247] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19163,7 +19688,7 @@ func (x *CPWeeklyRankSettlement) ProtoReflect() protoreflect.Message { // Deprecated: Use CPWeeklyRankSettlement.ProtoReflect.Descriptor instead. func (*CPWeeklyRankSettlement) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{240} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{247} } func (x *CPWeeklyRankSettlement) GetSettlementId() string { @@ -19283,7 +19808,7 @@ type GetCPWeeklyRankStatusRequest struct { func (x *GetCPWeeklyRankStatusRequest) Reset() { *x = GetCPWeeklyRankStatusRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[241] + mi := &file_proto_activity_v1_activity_proto_msgTypes[248] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19295,7 +19820,7 @@ func (x *GetCPWeeklyRankStatusRequest) String() string { func (*GetCPWeeklyRankStatusRequest) ProtoMessage() {} func (x *GetCPWeeklyRankStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[241] + mi := &file_proto_activity_v1_activity_proto_msgTypes[248] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19308,7 +19833,7 @@ func (x *GetCPWeeklyRankStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCPWeeklyRankStatusRequest.ProtoReflect.Descriptor instead. func (*GetCPWeeklyRankStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{241} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{248} } func (x *GetCPWeeklyRankStatusRequest) GetMeta() *RequestMeta { @@ -19347,7 +19872,7 @@ type GetCPWeeklyRankStatusResponse struct { func (x *GetCPWeeklyRankStatusResponse) Reset() { *x = GetCPWeeklyRankStatusResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[242] + mi := &file_proto_activity_v1_activity_proto_msgTypes[249] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19359,7 +19884,7 @@ func (x *GetCPWeeklyRankStatusResponse) String() string { func (*GetCPWeeklyRankStatusResponse) ProtoMessage() {} func (x *GetCPWeeklyRankStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[242] + mi := &file_proto_activity_v1_activity_proto_msgTypes[249] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19372,7 +19897,7 @@ func (x *GetCPWeeklyRankStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCPWeeklyRankStatusResponse.ProtoReflect.Descriptor instead. func (*GetCPWeeklyRankStatusResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{242} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{249} } func (x *GetCPWeeklyRankStatusResponse) GetConfig() *CPWeeklyRankConfig { @@ -19427,7 +19952,7 @@ type GetCPWeeklyRankConfigRequest struct { func (x *GetCPWeeklyRankConfigRequest) Reset() { *x = GetCPWeeklyRankConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[243] + mi := &file_proto_activity_v1_activity_proto_msgTypes[250] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19439,7 +19964,7 @@ func (x *GetCPWeeklyRankConfigRequest) String() string { func (*GetCPWeeklyRankConfigRequest) ProtoMessage() {} func (x *GetCPWeeklyRankConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[243] + mi := &file_proto_activity_v1_activity_proto_msgTypes[250] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19452,7 +19977,7 @@ func (x *GetCPWeeklyRankConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCPWeeklyRankConfigRequest.ProtoReflect.Descriptor instead. func (*GetCPWeeklyRankConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{243} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{250} } func (x *GetCPWeeklyRankConfigRequest) GetMeta() *RequestMeta { @@ -19472,7 +19997,7 @@ type GetCPWeeklyRankConfigResponse struct { func (x *GetCPWeeklyRankConfigResponse) Reset() { *x = GetCPWeeklyRankConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[244] + mi := &file_proto_activity_v1_activity_proto_msgTypes[251] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19484,7 +20009,7 @@ func (x *GetCPWeeklyRankConfigResponse) String() string { func (*GetCPWeeklyRankConfigResponse) ProtoMessage() {} func (x *GetCPWeeklyRankConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[244] + mi := &file_proto_activity_v1_activity_proto_msgTypes[251] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19497,7 +20022,7 @@ func (x *GetCPWeeklyRankConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCPWeeklyRankConfigResponse.ProtoReflect.Descriptor instead. func (*GetCPWeeklyRankConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{244} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{251} } func (x *GetCPWeeklyRankConfigResponse) GetConfig() *CPWeeklyRankConfig { @@ -19519,7 +20044,7 @@ type UpdateCPWeeklyRankConfigRequest struct { func (x *UpdateCPWeeklyRankConfigRequest) Reset() { *x = UpdateCPWeeklyRankConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[245] + mi := &file_proto_activity_v1_activity_proto_msgTypes[252] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19531,7 +20056,7 @@ func (x *UpdateCPWeeklyRankConfigRequest) String() string { func (*UpdateCPWeeklyRankConfigRequest) ProtoMessage() {} func (x *UpdateCPWeeklyRankConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[245] + mi := &file_proto_activity_v1_activity_proto_msgTypes[252] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19544,7 +20069,7 @@ func (x *UpdateCPWeeklyRankConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateCPWeeklyRankConfigRequest.ProtoReflect.Descriptor instead. func (*UpdateCPWeeklyRankConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{245} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{252} } func (x *UpdateCPWeeklyRankConfigRequest) GetMeta() *RequestMeta { @@ -19578,7 +20103,7 @@ type UpdateCPWeeklyRankConfigResponse struct { func (x *UpdateCPWeeklyRankConfigResponse) Reset() { *x = UpdateCPWeeklyRankConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[246] + mi := &file_proto_activity_v1_activity_proto_msgTypes[253] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19590,7 +20115,7 @@ func (x *UpdateCPWeeklyRankConfigResponse) String() string { func (*UpdateCPWeeklyRankConfigResponse) ProtoMessage() {} func (x *UpdateCPWeeklyRankConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[246] + mi := &file_proto_activity_v1_activity_proto_msgTypes[253] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19603,7 +20128,7 @@ func (x *UpdateCPWeeklyRankConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateCPWeeklyRankConfigResponse.ProtoReflect.Descriptor instead. func (*UpdateCPWeeklyRankConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{246} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{253} } func (x *UpdateCPWeeklyRankConfigResponse) GetConfig() *CPWeeklyRankConfig { @@ -19625,7 +20150,7 @@ type ListCPWeeklyRankSettlementsRequest struct { func (x *ListCPWeeklyRankSettlementsRequest) Reset() { *x = ListCPWeeklyRankSettlementsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[247] + mi := &file_proto_activity_v1_activity_proto_msgTypes[254] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19637,7 +20162,7 @@ func (x *ListCPWeeklyRankSettlementsRequest) String() string { func (*ListCPWeeklyRankSettlementsRequest) ProtoMessage() {} func (x *ListCPWeeklyRankSettlementsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[247] + mi := &file_proto_activity_v1_activity_proto_msgTypes[254] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19650,7 +20175,7 @@ func (x *ListCPWeeklyRankSettlementsRequest) ProtoReflect() protoreflect.Message // Deprecated: Use ListCPWeeklyRankSettlementsRequest.ProtoReflect.Descriptor instead. func (*ListCPWeeklyRankSettlementsRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{247} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{254} } func (x *ListCPWeeklyRankSettlementsRequest) GetMeta() *RequestMeta { @@ -19684,7 +20209,7 @@ type ListCPWeeklyRankSettlementsResponse struct { func (x *ListCPWeeklyRankSettlementsResponse) Reset() { *x = ListCPWeeklyRankSettlementsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[248] + mi := &file_proto_activity_v1_activity_proto_msgTypes[255] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19696,7 +20221,7 @@ func (x *ListCPWeeklyRankSettlementsResponse) String() string { func (*ListCPWeeklyRankSettlementsResponse) ProtoMessage() {} func (x *ListCPWeeklyRankSettlementsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[248] + mi := &file_proto_activity_v1_activity_proto_msgTypes[255] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19709,7 +20234,7 @@ func (x *ListCPWeeklyRankSettlementsResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use ListCPWeeklyRankSettlementsResponse.ProtoReflect.Descriptor instead. func (*ListCPWeeklyRankSettlementsResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{248} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{255} } func (x *ListCPWeeklyRankSettlementsResponse) GetSettlements() []*CPWeeklyRankSettlement { @@ -19733,7 +20258,7 @@ type AgencyOpeningReward struct { func (x *AgencyOpeningReward) Reset() { *x = AgencyOpeningReward{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[249] + mi := &file_proto_activity_v1_activity_proto_msgTypes[256] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19745,7 +20270,7 @@ func (x *AgencyOpeningReward) String() string { func (*AgencyOpeningReward) ProtoMessage() {} func (x *AgencyOpeningReward) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[249] + mi := &file_proto_activity_v1_activity_proto_msgTypes[256] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19758,7 +20283,7 @@ func (x *AgencyOpeningReward) ProtoReflect() protoreflect.Message { // Deprecated: Use AgencyOpeningReward.ProtoReflect.Descriptor instead. func (*AgencyOpeningReward) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{249} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{256} } func (x *AgencyOpeningReward) GetRankNo() int32 { @@ -19807,7 +20332,7 @@ type AgencyOpeningCycle struct { func (x *AgencyOpeningCycle) Reset() { *x = AgencyOpeningCycle{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[250] + mi := &file_proto_activity_v1_activity_proto_msgTypes[257] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19819,7 +20344,7 @@ func (x *AgencyOpeningCycle) String() string { func (*AgencyOpeningCycle) ProtoMessage() {} func (x *AgencyOpeningCycle) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[250] + mi := &file_proto_activity_v1_activity_proto_msgTypes[257] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19832,7 +20357,7 @@ func (x *AgencyOpeningCycle) ProtoReflect() protoreflect.Message { // Deprecated: Use AgencyOpeningCycle.ProtoReflect.Descriptor instead. func (*AgencyOpeningCycle) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{250} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{257} } func (x *AgencyOpeningCycle) GetCycleId() string { @@ -19972,7 +20497,7 @@ type AgencyOpeningApplication struct { func (x *AgencyOpeningApplication) Reset() { *x = AgencyOpeningApplication{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[251] + mi := &file_proto_activity_v1_activity_proto_msgTypes[258] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19984,7 +20509,7 @@ func (x *AgencyOpeningApplication) String() string { func (*AgencyOpeningApplication) ProtoMessage() {} func (x *AgencyOpeningApplication) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[251] + mi := &file_proto_activity_v1_activity_proto_msgTypes[258] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19997,7 +20522,7 @@ func (x *AgencyOpeningApplication) ProtoReflect() protoreflect.Message { // Deprecated: Use AgencyOpeningApplication.ProtoReflect.Descriptor instead. func (*AgencyOpeningApplication) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{251} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{258} } func (x *AgencyOpeningApplication) GetApplicationId() string { @@ -20170,7 +20695,7 @@ type AgencyOpeningAgencySnapshot struct { func (x *AgencyOpeningAgencySnapshot) Reset() { *x = AgencyOpeningAgencySnapshot{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[252] + mi := &file_proto_activity_v1_activity_proto_msgTypes[259] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20182,7 +20707,7 @@ func (x *AgencyOpeningAgencySnapshot) String() string { func (*AgencyOpeningAgencySnapshot) ProtoMessage() {} func (x *AgencyOpeningAgencySnapshot) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[252] + mi := &file_proto_activity_v1_activity_proto_msgTypes[259] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20195,7 +20720,7 @@ func (x *AgencyOpeningAgencySnapshot) ProtoReflect() protoreflect.Message { // Deprecated: Use AgencyOpeningAgencySnapshot.ProtoReflect.Descriptor instead. func (*AgencyOpeningAgencySnapshot) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{252} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{259} } func (x *AgencyOpeningAgencySnapshot) GetAgencyId() int64 { @@ -20255,7 +20780,7 @@ type ListAgencyOpeningCyclesRequest struct { func (x *ListAgencyOpeningCyclesRequest) Reset() { *x = ListAgencyOpeningCyclesRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[253] + mi := &file_proto_activity_v1_activity_proto_msgTypes[260] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20267,7 +20792,7 @@ func (x *ListAgencyOpeningCyclesRequest) String() string { func (*ListAgencyOpeningCyclesRequest) ProtoMessage() {} func (x *ListAgencyOpeningCyclesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[253] + mi := &file_proto_activity_v1_activity_proto_msgTypes[260] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20280,7 +20805,7 @@ func (x *ListAgencyOpeningCyclesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAgencyOpeningCyclesRequest.ProtoReflect.Descriptor instead. func (*ListAgencyOpeningCyclesRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{253} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{260} } func (x *ListAgencyOpeningCyclesRequest) GetMeta() *RequestMeta { @@ -20336,7 +20861,7 @@ type ListAgencyOpeningCyclesResponse struct { func (x *ListAgencyOpeningCyclesResponse) Reset() { *x = ListAgencyOpeningCyclesResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[254] + mi := &file_proto_activity_v1_activity_proto_msgTypes[261] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20348,7 +20873,7 @@ func (x *ListAgencyOpeningCyclesResponse) String() string { func (*ListAgencyOpeningCyclesResponse) ProtoMessage() {} func (x *ListAgencyOpeningCyclesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[254] + mi := &file_proto_activity_v1_activity_proto_msgTypes[261] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20361,7 +20886,7 @@ func (x *ListAgencyOpeningCyclesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAgencyOpeningCyclesResponse.ProtoReflect.Descriptor instead. func (*ListAgencyOpeningCyclesResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{254} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{261} } func (x *ListAgencyOpeningCyclesResponse) GetCycles() []*AgencyOpeningCycle { @@ -20389,7 +20914,7 @@ type GetAgencyOpeningCycleRequest struct { func (x *GetAgencyOpeningCycleRequest) Reset() { *x = GetAgencyOpeningCycleRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[255] + mi := &file_proto_activity_v1_activity_proto_msgTypes[262] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20401,7 +20926,7 @@ func (x *GetAgencyOpeningCycleRequest) String() string { func (*GetAgencyOpeningCycleRequest) ProtoMessage() {} func (x *GetAgencyOpeningCycleRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[255] + mi := &file_proto_activity_v1_activity_proto_msgTypes[262] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20414,7 +20939,7 @@ func (x *GetAgencyOpeningCycleRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyOpeningCycleRequest.ProtoReflect.Descriptor instead. func (*GetAgencyOpeningCycleRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{255} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{262} } func (x *GetAgencyOpeningCycleRequest) GetMeta() *RequestMeta { @@ -20441,7 +20966,7 @@ type GetAgencyOpeningCycleResponse struct { func (x *GetAgencyOpeningCycleResponse) Reset() { *x = GetAgencyOpeningCycleResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[256] + mi := &file_proto_activity_v1_activity_proto_msgTypes[263] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20453,7 +20978,7 @@ func (x *GetAgencyOpeningCycleResponse) String() string { func (*GetAgencyOpeningCycleResponse) ProtoMessage() {} func (x *GetAgencyOpeningCycleResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[256] + mi := &file_proto_activity_v1_activity_proto_msgTypes[263] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20466,7 +20991,7 @@ func (x *GetAgencyOpeningCycleResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyOpeningCycleResponse.ProtoReflect.Descriptor instead. func (*GetAgencyOpeningCycleResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{256} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{263} } func (x *GetAgencyOpeningCycleResponse) GetCycle() *AgencyOpeningCycle { @@ -20488,7 +21013,7 @@ type UpsertAgencyOpeningCycleRequest struct { func (x *UpsertAgencyOpeningCycleRequest) Reset() { *x = UpsertAgencyOpeningCycleRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[257] + mi := &file_proto_activity_v1_activity_proto_msgTypes[264] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20500,7 +21025,7 @@ func (x *UpsertAgencyOpeningCycleRequest) String() string { func (*UpsertAgencyOpeningCycleRequest) ProtoMessage() {} func (x *UpsertAgencyOpeningCycleRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[257] + mi := &file_proto_activity_v1_activity_proto_msgTypes[264] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20513,7 +21038,7 @@ func (x *UpsertAgencyOpeningCycleRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertAgencyOpeningCycleRequest.ProtoReflect.Descriptor instead. func (*UpsertAgencyOpeningCycleRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{257} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{264} } func (x *UpsertAgencyOpeningCycleRequest) GetMeta() *RequestMeta { @@ -20548,7 +21073,7 @@ type UpsertAgencyOpeningCycleResponse struct { func (x *UpsertAgencyOpeningCycleResponse) Reset() { *x = UpsertAgencyOpeningCycleResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[258] + mi := &file_proto_activity_v1_activity_proto_msgTypes[265] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20560,7 +21085,7 @@ func (x *UpsertAgencyOpeningCycleResponse) String() string { func (*UpsertAgencyOpeningCycleResponse) ProtoMessage() {} func (x *UpsertAgencyOpeningCycleResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[258] + mi := &file_proto_activity_v1_activity_proto_msgTypes[265] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20573,7 +21098,7 @@ func (x *UpsertAgencyOpeningCycleResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertAgencyOpeningCycleResponse.ProtoReflect.Descriptor instead. func (*UpsertAgencyOpeningCycleResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{258} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{265} } func (x *UpsertAgencyOpeningCycleResponse) GetCycle() *AgencyOpeningCycle { @@ -20603,7 +21128,7 @@ type SetAgencyOpeningCycleStatusRequest struct { func (x *SetAgencyOpeningCycleStatusRequest) Reset() { *x = SetAgencyOpeningCycleStatusRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[259] + mi := &file_proto_activity_v1_activity_proto_msgTypes[266] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20615,7 +21140,7 @@ func (x *SetAgencyOpeningCycleStatusRequest) String() string { func (*SetAgencyOpeningCycleStatusRequest) ProtoMessage() {} func (x *SetAgencyOpeningCycleStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[259] + mi := &file_proto_activity_v1_activity_proto_msgTypes[266] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20628,7 +21153,7 @@ func (x *SetAgencyOpeningCycleStatusRequest) ProtoReflect() protoreflect.Message // Deprecated: Use SetAgencyOpeningCycleStatusRequest.ProtoReflect.Descriptor instead. func (*SetAgencyOpeningCycleStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{259} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{266} } func (x *SetAgencyOpeningCycleStatusRequest) GetMeta() *RequestMeta { @@ -20669,7 +21194,7 @@ type SetAgencyOpeningCycleStatusResponse struct { func (x *SetAgencyOpeningCycleStatusResponse) Reset() { *x = SetAgencyOpeningCycleStatusResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[260] + mi := &file_proto_activity_v1_activity_proto_msgTypes[267] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20681,7 +21206,7 @@ func (x *SetAgencyOpeningCycleStatusResponse) String() string { func (*SetAgencyOpeningCycleStatusResponse) ProtoMessage() {} func (x *SetAgencyOpeningCycleStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[260] + mi := &file_proto_activity_v1_activity_proto_msgTypes[267] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20694,7 +21219,7 @@ func (x *SetAgencyOpeningCycleStatusResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use SetAgencyOpeningCycleStatusResponse.ProtoReflect.Descriptor instead. func (*SetAgencyOpeningCycleStatusResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{260} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{267} } func (x *SetAgencyOpeningCycleStatusResponse) GetCycle() *AgencyOpeningCycle { @@ -20720,7 +21245,7 @@ type ListAgencyOpeningApplicationsRequest struct { func (x *ListAgencyOpeningApplicationsRequest) Reset() { *x = ListAgencyOpeningApplicationsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[261] + mi := &file_proto_activity_v1_activity_proto_msgTypes[268] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20732,7 +21257,7 @@ func (x *ListAgencyOpeningApplicationsRequest) String() string { func (*ListAgencyOpeningApplicationsRequest) ProtoMessage() {} func (x *ListAgencyOpeningApplicationsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[261] + mi := &file_proto_activity_v1_activity_proto_msgTypes[268] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20745,7 +21270,7 @@ func (x *ListAgencyOpeningApplicationsRequest) ProtoReflect() protoreflect.Messa // Deprecated: Use ListAgencyOpeningApplicationsRequest.ProtoReflect.Descriptor instead. func (*ListAgencyOpeningApplicationsRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{261} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{268} } func (x *ListAgencyOpeningApplicationsRequest) GetMeta() *RequestMeta { @@ -20808,7 +21333,7 @@ type ListAgencyOpeningApplicationsResponse struct { func (x *ListAgencyOpeningApplicationsResponse) Reset() { *x = ListAgencyOpeningApplicationsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[262] + mi := &file_proto_activity_v1_activity_proto_msgTypes[269] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20820,7 +21345,7 @@ func (x *ListAgencyOpeningApplicationsResponse) String() string { func (*ListAgencyOpeningApplicationsResponse) ProtoMessage() {} func (x *ListAgencyOpeningApplicationsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[262] + mi := &file_proto_activity_v1_activity_proto_msgTypes[269] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20833,7 +21358,7 @@ func (x *ListAgencyOpeningApplicationsResponse) ProtoReflect() protoreflect.Mess // Deprecated: Use ListAgencyOpeningApplicationsResponse.ProtoReflect.Descriptor instead. func (*ListAgencyOpeningApplicationsResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{262} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{269} } func (x *ListAgencyOpeningApplicationsResponse) GetApplications() []*AgencyOpeningApplication { @@ -20863,7 +21388,7 @@ type ReviewAgencyOpeningApplicationRequest struct { func (x *ReviewAgencyOpeningApplicationRequest) Reset() { *x = ReviewAgencyOpeningApplicationRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[263] + mi := &file_proto_activity_v1_activity_proto_msgTypes[270] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20875,7 +21400,7 @@ func (x *ReviewAgencyOpeningApplicationRequest) String() string { func (*ReviewAgencyOpeningApplicationRequest) ProtoMessage() {} func (x *ReviewAgencyOpeningApplicationRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[263] + mi := &file_proto_activity_v1_activity_proto_msgTypes[270] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20888,7 +21413,7 @@ func (x *ReviewAgencyOpeningApplicationRequest) ProtoReflect() protoreflect.Mess // Deprecated: Use ReviewAgencyOpeningApplicationRequest.ProtoReflect.Descriptor instead. func (*ReviewAgencyOpeningApplicationRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{263} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{270} } func (x *ReviewAgencyOpeningApplicationRequest) GetMeta() *RequestMeta { @@ -20929,7 +21454,7 @@ type ReviewAgencyOpeningApplicationResponse struct { func (x *ReviewAgencyOpeningApplicationResponse) Reset() { *x = ReviewAgencyOpeningApplicationResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[264] + mi := &file_proto_activity_v1_activity_proto_msgTypes[271] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20941,7 +21466,7 @@ func (x *ReviewAgencyOpeningApplicationResponse) String() string { func (*ReviewAgencyOpeningApplicationResponse) ProtoMessage() {} func (x *ReviewAgencyOpeningApplicationResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[264] + mi := &file_proto_activity_v1_activity_proto_msgTypes[271] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20954,7 +21479,7 @@ func (x *ReviewAgencyOpeningApplicationResponse) ProtoReflect() protoreflect.Mes // Deprecated: Use ReviewAgencyOpeningApplicationResponse.ProtoReflect.Descriptor instead. func (*ReviewAgencyOpeningApplicationResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{264} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{271} } func (x *ReviewAgencyOpeningApplicationResponse) GetApplication() *AgencyOpeningApplication { @@ -20975,7 +21500,7 @@ type GetAgencyOpeningStatusRequest struct { func (x *GetAgencyOpeningStatusRequest) Reset() { *x = GetAgencyOpeningStatusRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[265] + mi := &file_proto_activity_v1_activity_proto_msgTypes[272] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20987,7 +21512,7 @@ func (x *GetAgencyOpeningStatusRequest) String() string { func (*GetAgencyOpeningStatusRequest) ProtoMessage() {} func (x *GetAgencyOpeningStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[265] + mi := &file_proto_activity_v1_activity_proto_msgTypes[272] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -21000,7 +21525,7 @@ func (x *GetAgencyOpeningStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyOpeningStatusRequest.ProtoReflect.Descriptor instead. func (*GetAgencyOpeningStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{265} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{272} } func (x *GetAgencyOpeningStatusRequest) GetMeta() *RequestMeta { @@ -21034,7 +21559,7 @@ type GetAgencyOpeningStatusResponse struct { func (x *GetAgencyOpeningStatusResponse) Reset() { *x = GetAgencyOpeningStatusResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[266] + mi := &file_proto_activity_v1_activity_proto_msgTypes[273] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -21046,7 +21571,7 @@ func (x *GetAgencyOpeningStatusResponse) String() string { func (*GetAgencyOpeningStatusResponse) ProtoMessage() {} func (x *GetAgencyOpeningStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[266] + mi := &file_proto_activity_v1_activity_proto_msgTypes[273] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -21059,7 +21584,7 @@ func (x *GetAgencyOpeningStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyOpeningStatusResponse.ProtoReflect.Descriptor instead. func (*GetAgencyOpeningStatusResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{266} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{273} } func (x *GetAgencyOpeningStatusResponse) GetCycle() *AgencyOpeningCycle { @@ -21130,7 +21655,7 @@ type ApplyAgencyOpeningRequest struct { func (x *ApplyAgencyOpeningRequest) Reset() { *x = ApplyAgencyOpeningRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[267] + mi := &file_proto_activity_v1_activity_proto_msgTypes[274] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -21142,7 +21667,7 @@ func (x *ApplyAgencyOpeningRequest) String() string { func (*ApplyAgencyOpeningRequest) ProtoMessage() {} func (x *ApplyAgencyOpeningRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[267] + mi := &file_proto_activity_v1_activity_proto_msgTypes[274] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -21155,7 +21680,7 @@ func (x *ApplyAgencyOpeningRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyAgencyOpeningRequest.ProtoReflect.Descriptor instead. func (*ApplyAgencyOpeningRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{267} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{274} } func (x *ApplyAgencyOpeningRequest) GetMeta() *RequestMeta { @@ -21190,7 +21715,7 @@ type ApplyAgencyOpeningResponse struct { func (x *ApplyAgencyOpeningResponse) Reset() { *x = ApplyAgencyOpeningResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[268] + mi := &file_proto_activity_v1_activity_proto_msgTypes[275] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -21202,7 +21727,7 @@ func (x *ApplyAgencyOpeningResponse) String() string { func (*ApplyAgencyOpeningResponse) ProtoMessage() {} func (x *ApplyAgencyOpeningResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[268] + mi := &file_proto_activity_v1_activity_proto_msgTypes[275] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -21215,7 +21740,7 @@ func (x *ApplyAgencyOpeningResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyAgencyOpeningResponse.ProtoReflect.Descriptor instead. func (*ApplyAgencyOpeningResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{268} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{275} } func (x *ApplyAgencyOpeningResponse) GetApplication() *AgencyOpeningApplication { @@ -23640,7 +24165,7 @@ var file_proto_activity_v1_activity_proto_rawDesc = []byte{ 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 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, 0xe7, 0x03, 0x0a, 0x0e, 0x4c, + 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x82, 0x06, 0x0a, 0x0e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x4a, 0x6f, 0x62, 0x12, 0x22, 0x0a, 0x0d, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x4a, 0x6f, 0x62, 0x49, @@ -23671,98 +24196,197 @@ var file_proto_activity_v1_activity_proto_rawDesc = []byte{ 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, 0xc5, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x32, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 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, 0x14, 0x0a, - 0x05, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x72, - 0x61, 0x63, 0x6b, 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, 0x6d, 0x0a, 0x18, - 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x07, 0x72, 0x65, 0x77, 0x61, - 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, - 0x76, 0x65, 0x6c, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x07, 0x72, 0x65, - 0x77, 0x61, 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, 0xa4, 0x03, 0x0a, 0x18, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, + 0x41, 0x74, 0x4d, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x6f, + 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x77, + 0x61, 0x72, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x65, 0x6d, + 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, + 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, + 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x67, 0x72, 0x61, 0x6e, 0x74, + 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x10, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x0f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x6c, 0x65, 0x76, + 0x65, 0x6c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, + 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, + 0x6e, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, + 0x65, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x17, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, + 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x13, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x45, + 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, + 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, + 0xc5, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x77, + 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x04, 0x6d, + 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 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, 0x14, 0x0a, 0x05, 0x74, 0x72, 0x61, 0x63, + 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x72, 0x61, 0x63, 0x6b, 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, 0x6d, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x07, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x4a, 0x6f, 0x62, 0x52, 0x07, 0x72, 0x65, 0x77, 0x61, 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, 0xa4, 0x03, 0x0a, 0x18, 0x43, 0x6f, 0x6e, 0x73, 0x75, + 0x6d, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 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, 0x26, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, + 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, + 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x12, 0x1f, 0x0a, 0x0b, + 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, + 0x0b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x24, + 0x0a, 0x0e, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x64, + 0x41, 0x74, 0x4d, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, + 0x6e, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x64, + 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x4a, 0x73, 0x6f, 0x6e, 0x22, 0xe1, 0x01, + 0x0a, 0x19, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, + 0x0a, 0x0d, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, + 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x70, 0x72, 0x65, + 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x65, + 0x77, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6e, + 0x65, 0x77, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x65, 0x77, 0x61, 0x72, + 0x64, 0x5f, 0x6a, 0x6f, 0x62, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0e, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x4a, 0x6f, 0x62, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x22, 0xef, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x04, 0x6d, 0x65, 0x74, + 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 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, 0x14, 0x0a, 0x05, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x6c, + 0x65, 0x76, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 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, 0x94, 0x02, 0x0a, 0x14, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x14, 0x0a, 0x05, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x74, 0x72, 0x61, 0x63, 0x6b, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, + 0x73, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x70, + 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1b, 0x0a, 0x09, + 0x6e, 0x65, 0x77, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x08, 0x6e, 0x65, 0x77, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x5f, 0x6a, 0x6f, 0x62, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x4a, 0x6f, 0x62, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xed, 0x02, 0x0a, 0x16, 0x41, + 0x64, 0x6d, 0x69, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x12, 0x1d, 0x0a, 0x0a, 0x72, + 0x65, 0x61, 0x6c, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x09, 0x72, 0x65, 0x61, 0x6c, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x65, + 0x61, 0x6c, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, 0x65, 0x61, 0x6c, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, + 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x64, 0x69, 0x73, + 0x70, 0x6c, 0x61, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x69, 0x73, + 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, + 0x0a, 0x12, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x65, 0x6d, 0x70, + 0x6f, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x16, + 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x74, 0x65, + 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x5f, 0x6d, 0x73, 0x18, 0x08, 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, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x65, + 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, 0x22, 0x73, 0x0a, 0x15, 0x41, 0x64, + 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 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, 0x41, 0x0a, 0x06, + 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x6b, + 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x22, + 0x76, 0x0a, 0x25, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 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, 0x26, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, - 0x25, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, - 0x72, 0x61, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x72, 0x61, 0x63, - 0x6b, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, - 0x61, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, - 0x6c, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x63, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x69, 0x6d, - 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0e, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x4a, 0x73, - 0x6f, 0x6e, 0x22, 0xe1, 0x01, 0x0a, 0x19, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x4c, 0x65, - 0x76, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x63, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6c, 0x65, 0x76, 0x65, - 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x65, 0x76, - 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x0d, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, - 0x1b, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x28, 0x0a, 0x10, - 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x6a, 0x6f, 0x62, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x4a, 0x6f, - 0x62, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xef, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, - 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 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, 0x14, 0x0a, 0x05, 0x74, 0x72, - 0x61, 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x72, 0x61, 0x63, 0x6b, - 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 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, 0x94, 0x02, 0x0a, 0x14, 0x53, 0x65, 0x74, - 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, - 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0d, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4c, 0x65, 0x76, 0x65, - 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1f, - 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x28, 0x0a, 0x10, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x6a, 0x6f, 0x62, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x4a, 0x6f, 0x62, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x03, 0x52, 0x07, + 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x22, 0x94, 0x01, 0x0a, 0x26, 0x42, 0x61, 0x74, 0x63, + 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x41, 0x64, 0x6d, + 0x69, 0x6e, 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, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, + 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x08, + 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 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, 0x6b, + 0x0a, 0x18, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, + 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x72, + 0x61, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x72, 0x61, 0x63, 0x6b, + 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x64, 0x61, 0x79, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x64, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x79, 0x73, 0x22, 0xa1, 0x02, 0x0a, 0x20, + 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x55, + 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x32, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 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, 0x4d, 0x0a, 0x0b, + 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, + 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 0x74, 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, + 0x8d, 0x01, 0x0a, 0x21, 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, + 0x61, 0x72, 0x79, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x73, 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, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, + 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x52, 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 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, 0x85, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x42, 0x61, 0x64, 0x67, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x12, @@ -25248,7 +25872,7 @@ var file_proto_activity_v1_activity_proto_rawDesc = []byte{ 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x32, 0x98, 0x06, 0x0a, 0x13, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x6e, 0x73, 0x65, 0x32, 0x81, 0x07, 0x0a, 0x13, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x43, 0x72, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x66, 0x0a, 0x19, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x61, 0x6e, 0x6f, 0x75, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, @@ -25262,853 +25886,878 @@ var file_proto_activity_v1_activity_proto_rawDesc = []byte{ 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x1d, 0x50, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x28, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, - 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, - 0x72, 0x64, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, - 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x20, - 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, - 0x72, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, - 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, - 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x22, 0x50, - 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, - 0x6e, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, - 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70, 0x0a, 0x23, - 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, - 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, + 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x1a, 0x50, 0x72, 0x6f, + 0x63, 0x65, 0x73, 0x73, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x1d, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x41, 0x63, 0x68, + 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, - 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc8, - 0x02, 0x0a, 0x0b, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x62, - 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x12, - 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x54, 0x61, 0x73, 0x6b, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x55, 0x73, 0x65, 0x72, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0f, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x52, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x54, - 0x61, 0x73, 0x6b, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, - 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x10, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x54, 0x61, 0x73, 0x6b, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, + 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, + 0x0a, 0x28, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, + 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x74, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x20, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, + 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x22, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, + 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70, 0x0a, 0x23, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, + 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xd9, 0x06, 0x0a, 0x12, 0x47, 0x72, - 0x6f, 0x77, 0x74, 0x68, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x71, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x79, - 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x4c, 0x65, - 0x76, 0x65, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, - 0x72, 0x61, 0x63, 0x6b, 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x76, 0x65, - 0x6c, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, + 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc8, 0x02, 0x0a, 0x0b, 0x54, 0x61, 0x73, 0x6b, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x62, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x54, 0x61, + 0x73, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0f, 0x43, + 0x6c, 0x61, 0x69, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, 0x29, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x77, 0x61, + 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, + 0x61, 0x69, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, + 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, + 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x32, 0xd9, 0x06, 0x0a, 0x12, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x71, 0x0a, 0x12, 0x47, 0x65, 0x74, + 0x4d, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x12, + 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0d, + 0x47, 0x65, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x9b, 0x01, 0x0a, 0x20, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x44, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x3a, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, - 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x44, 0x69, - 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x65, + 0x76, 0x65, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x9b, 0x01, 0x0a, 0x20, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, + 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x3a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, + 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x44, 0x69, 0x73, 0x70, 0x6c, + 0x61, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x3b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, + 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, + 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x77, 0x61, 0x72, + 0x64, 0x73, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, + 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x77, 0x61, + 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x11, 0x43, + 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x4c, 0x65, 0x76, 0x65, + 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0c, 0x53, + 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x26, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8f, 0x01, 0x0a, + 0x1c, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x42, 0x61, 0x64, 0x67, 0x65, 0x73, 0x12, 0x36, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, + 0x31, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x42, 0x61, 0x64, 0x67, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, + 0x42, 0x61, 0x64, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xcf, + 0x03, 0x0a, 0x12, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x68, + 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, + 0x73, 0x74, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, - 0x76, 0x65, 0x6c, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, - 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, - 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x8f, 0x01, 0x0a, 0x1c, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x42, 0x61, - 0x64, 0x67, 0x65, 0x73, 0x12, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x42, - 0x61, 0x64, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x42, 0x61, 0x64, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xcf, 0x03, 0x0a, 0x12, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x10, - 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x17, 0x43, 0x6f, - 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, - 0x65, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6d, 0x65, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0c, - 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x79, 0x42, 0x61, 0x64, 0x67, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x79, 0x42, 0x61, 0x64, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x79, 0x42, - 0x61, 0x64, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, - 0x0f, 0x53, 0x65, 0x74, 0x42, 0x61, 0x64, 0x67, 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, - 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x42, 0x61, 0x64, 0x67, 0x65, 0x44, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, + 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x17, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x63, + 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x31, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x41, 0x63, 0x68, + 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x79, 0x42, + 0x61, 0x64, 0x67, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x79, + 0x42, 0x61, 0x64, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x79, 0x42, 0x61, 0x64, 0x67, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x42, 0x61, 0x64, + 0x67, 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x74, 0x42, 0x61, 0x64, 0x67, 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x42, 0x61, 0x64, 0x67, + 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x32, 0x7b, 0x0a, 0x0c, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x6b, 0x0a, 0x10, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x57, 0x68, 0x65, 0x65, 0x6c, + 0x44, 0x72, 0x61, 0x77, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, + 0x57, 0x68, 0x65, 0x65, 0x6c, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x57, 0x68, 0x65, 0x65, + 0x6c, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xaa, 0x01, + 0x0a, 0x19, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, + 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x65, 0x74, 0x42, 0x61, 0x64, 0x67, 0x65, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x7b, 0x0a, 0x0c, 0x57, 0x68, 0x65, 0x65, 0x6c, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x10, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x65, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x44, 0x72, 0x61, 0x77, 0x12, 0x2a, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x44, 0x72, 0x61, 0x77, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x65, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xaa, 0x01, 0x0a, 0x19, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, - 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, - 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, - 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x32, 0x91, 0x03, 0x0a, 0x11, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x77, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x57, 0x65, - 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, - 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, - 0x72, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, - 0x72, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x86, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, - 0x74, 0x61, 0x72, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, 0x33, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, - 0x72, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, - 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x15, 0x4c, 0x69, 0x73, - 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x48, 0x69, 0x73, 0x74, 0x6f, - 0x72, 0x79, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, - 0x79, 0x53, 0x74, 0x61, 0x72, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, - 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x91, 0x01, 0x0a, 0x13, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, - 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7a, 0x0a, - 0x15, 0x47, 0x65, 0x74, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x50, - 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, - 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x9c, 0x03, 0x0a, 0x14, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x7d, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, - 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x30, 0x2e, 0x68, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x91, 0x03, 0x0a, 0x11, 0x57, + 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x77, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, + 0x72, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, 0x0a, 0x19, 0x4c, 0x69, + 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x4c, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, - 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x4c, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, + 0x53, 0x74, 0x61, 0x72, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x2f, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x48, 0x69, + 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x48, + 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x91, + 0x01, 0x0a, 0x13, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7a, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x50, 0x57, + 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, + 0x61, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, + 0x52, 0x61, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x32, 0x9c, 0x03, 0x0a, 0x14, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, + 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7d, 0x0a, 0x16, 0x47, + 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, + 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, + 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x12, 0x41, 0x70, + 0x70, 0x6c, 0x79, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, + 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, + 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, - 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x71, 0x0a, 0x12, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, - 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, - 0x79, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x91, 0x01, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, + 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, + 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x91, 0x01, + 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, + 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x8b, 0x05, 0x0a, 0x10, 0x42, 0x72, 0x6f, - 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7a, 0x0a, - 0x15, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x73, 0x75, 0x72, - 0x65, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x73, 0x75, - 0x72, 0x65, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x16, 0x50, 0x75, 0x62, - 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, - 0x61, 0x73, 0x74, 0x12, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, - 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, - 0x68, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x77, 0x0a, 0x16, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x47, 0x6c, 0x6f, - 0x62, 0x61, 0x6c, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12, 0x30, 0x2e, 0x68, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x32, 0x8b, 0x05, 0x0a, 0x10, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7a, 0x0a, 0x15, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, + 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, + 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, + 0x61, 0x73, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x42, 0x72, 0x6f, 0x61, 0x64, + 0x63, 0x61, 0x73, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x77, 0x0a, 0x16, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x67, + 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x42, 0x72, + 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, - 0x61, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x6f, 0x61, - 0x64, 0x63, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x35, 0x2e, 0x68, 0x79, + 0x61, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x16, 0x50, + 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x42, 0x72, 0x6f, 0x61, + 0x64, 0x63, 0x61, 0x73, 0x74, 0x12, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, + 0x68, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x73, 0x68, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x4d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x4d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x6f, 0x61, - 0x64, 0x63, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x67, - 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x1b, 0x50, 0x72, - 0x6f, 0x63, 0x65, 0x73, 0x73, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x4f, 0x75, - 0x74, 0x62, 0x6f, 0x78, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, - 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, - 0x61, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x78, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x87, 0x01, 0x0a, 0x18, 0x52, 0x6f, 0x6f, 0x6d, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x52, 0x6f, - 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x52, - 0x6f, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x32, 0x87, 0x04, 0x0a, 0x10, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x74, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x73, - 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2d, 0x2e, 0x68, + 0x64, 0x63, 0x61, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x1b, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x42, 0x72, + 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x78, 0x42, 0x61, 0x74, + 0x63, 0x68, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, + 0x65, 0x73, 0x73, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, + 0x6f, 0x78, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, + 0x87, 0x01, 0x0a, 0x18, 0x52, 0x6f, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6d, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x10, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x52, 0x6f, 0x6f, 0x6d, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, + 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x87, 0x04, 0x0a, 0x10, 0x41, 0x64, + 0x6d, 0x69, 0x6e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x74, + 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, + 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x73, + 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x14, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x54, 0x61, + 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, + 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, + 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, + 0x0a, 0x17, 0x53, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x74, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x80, 0x01, 0x0a, 0x17, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x54, 0x61, 0x73, 0x6b, + 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x31, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x77, 0x61, + 0x72, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x54, 0x61, 0x73, 0x6b, 0x52, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x32, 0xbc, 0x02, 0x0a, 0x19, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x9b, 0x01, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x45, 0x6c, 0x69, 0x67, 0x69, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x3a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, + 0x45, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x45, 0x6c, 0x69, 0x67, + 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x80, 0x01, 0x0a, 0x17, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x14, 0x55, - 0x70, 0x73, 0x65, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x54, 0x61, - 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x54, 0x61, - 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, - 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, - 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x44, - 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x17, 0x50, 0x75, 0x62, 0x6c, - 0x69, 0x73, 0x68, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x12, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x54, - 0x61, 0x73, 0x6b, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, - 0x73, 0x68, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xbc, 0x02, 0x0a, 0x19, 0x52, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x9b, 0x01, 0x0a, 0x20, 0x47, 0x65, 0x74, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, - 0x72, 0x64, 0x45, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x3a, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x45, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, - 0x61, 0x72, 0x64, 0x45, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x17, 0x49, 0x73, 0x73, 0x75, 0x65, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, - 0x72, 0x64, 0x12, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xd9, 0x03, 0x0a, 0x1e, 0x41, 0x64, - 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x8c, 0x01, 0x0a, - 0x1b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x2e, 0x68, + 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, + 0x76, 0x31, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x32, 0xd9, 0x03, 0x0a, 0x1e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x95, 0x01, 0x0a, 0x1e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x8f, 0x01, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6c, - 0x61, 0x69, 0x6d, 0x73, 0x12, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, - 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xba, 0x02, 0x0a, 0x1a, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, - 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x8f, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x72, - 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, - 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x89, 0x01, 0x0a, 0x1a, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6d, 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, - 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, - 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x32, 0xe3, 0x03, 0x0a, 0x1f, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x8f, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x46, 0x69, - 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, - 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, - 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x98, 0x01, 0x0a, 0x1f, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, - 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x95, 0x01, 0x0a, 0x1e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, + 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x92, 0x01, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x72, 0x73, - 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, - 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x12, 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, + 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x39, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8f, 0x01, 0x0a, + 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x12, 0x36, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, + 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xba, + 0x02, 0x0a, 0x1a, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, + 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x8f, 0x01, + 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, + 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x36, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, + 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, + 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x89, 0x01, 0x0a, 0x1a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, + 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, 0x34, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, + 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, + 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, + 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe3, 0x03, 0x0a, 0x1f, + 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, + 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x8f, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, + 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, + 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, + 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x98, 0x01, 0x0a, 0x1f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x72, 0x73, + 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, + 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x3a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, + 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x92, 0x01, 0x0a, + 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, + 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x12, 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xdd, 0x02, 0x0a, 0x1f, 0x43, 0x75, 0x6d, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, + 0x61, 0x72, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x32, 0xdd, 0x02, 0x0a, 0x1f, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, + 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x9e, 0x01, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x9e, 0x01, 0x0a, - 0x21, 0x47, 0x65, 0x74, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, - 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x3b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, - 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, - 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x3c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, - 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x98, 0x01, - 0x0a, 0x1f, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, - 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x12, 0x39, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x43, 0x75, 0x6d, - 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, - 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xd0, 0x03, 0x0a, 0x1b, 0x49, 0x6e, 0x76, - 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x92, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, - 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, - 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x37, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3b, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, + 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, + 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x98, 0x01, 0x0a, 0x1f, 0x43, 0x6f, 0x6e, 0x73, 0x75, + 0x6d, 0x65, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, + 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, 0x39, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, + 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, + 0x65, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, + 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x32, 0xd0, 0x03, 0x0a, 0x1b, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x92, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, - 0x0a, 0x19, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, 0x33, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6c, 0x61, 0x69, 0x6d, 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, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 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, 0x92, 0x01, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x4c, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x4c, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, 0x0a, 0x19, 0x43, 0x6c, 0x61, 0x69, 0x6d, + 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x12, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 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, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, + 0x61, 0x69, 0x6d, 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, + 0x92, 0x01, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, + 0x64, 0x12, 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, - 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x95, 0x04, 0x0a, 0x24, - 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, - 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x9e, 0x01, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x43, 0x75, 0x6d, 0x75, - 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, - 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, - 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, - 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, - 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0xa7, 0x01, 0x0a, 0x24, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, - 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3e, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, - 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3f, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, - 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0xa1, 0x01, 0x0a, 0x22, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, + 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x95, 0x04, 0x0a, 0x24, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x75, + 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, + 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x9e, 0x01, + 0x0a, 0x21, 0x47, 0x65, 0x74, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, + 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x3b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x75, 0x6d, 0x75, 0x6c, + 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, + 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x3c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, - 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x3c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, - 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x75, 0x6d, - 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x32, 0x8e, 0x05, 0x0a, 0x20, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x6e, 0x76, - 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x92, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, - 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, - 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x37, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0xa7, + 0x01, 0x0a, 0x24, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, + 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, + 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, + 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, + 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0xa1, 0x01, 0x0a, 0x22, 0x4c, 0x69, 0x73, + 0x74, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, + 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, + 0x3c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, + 0x76, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, + 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, + 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, 0x72, + 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x8e, 0x05, 0x0a, + 0x20, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x92, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x9b, 0x01, - 0x0a, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x3a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x9b, 0x01, 0x0a, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x95, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x95, 0x01, 0x0a, 0x1e, - 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x12, 0x38, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x9e, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x69, - 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, - 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, 0x12, 0x3b, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, - 0x61, 0x72, 0x64, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x89, 0x05, 0x0a, 0x1e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, - 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x52, - 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x12, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x39, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, + 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6c, + 0x61, 0x69, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x9e, 0x01, 0x0a, + 0x21, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, + 0x65, 0x73, 0x12, 0x3b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, + 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, + 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x3c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x75, 0x6d, 0x6d, + 0x61, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x89, 0x05, + 0x0a, 0x1e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, + 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, + 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, + 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, - 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x95, 0x01, 0x0a, 0x1e, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, - 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, - 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, - 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x9e, - 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, - 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, - 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, - 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x3c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, - 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x74, 0x74, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x9e, 0x01, 0x0a, 0x21, 0x52, 0x65, 0x74, 0x72, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, - 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x74, 0x74, 0x6c, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x52, - 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x52, 0x6f, 0x6f, 0x6d, - 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, - 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x32, 0x94, 0x07, 0x0a, 0x16, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, - 0x53, 0x74, 0x61, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x77, 0x0a, 0x14, 0x4c, - 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, - 0x6c, 0x65, 0x73, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, - 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, - 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x65, - 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x2f, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, - 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, - 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, - 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x71, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, - 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x65, - 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x65, 0x65, 0x6b, - 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x65, 0x65, - 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x2f, 0x2e, 0x68, + 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x95, 0x01, 0x0a, 0x1e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, + 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, + 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, - 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, + 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x9e, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, + 0x72, 0x64, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, - 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, - 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x83, 0x01, 0x0a, 0x18, 0x53, 0x65, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, - 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x32, 0x2e, 0x68, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, + 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x9e, 0x01, 0x0a, 0x21, 0x52, 0x65, 0x74, + 0x72, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3b, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, + 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x74, 0x72, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, + 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x94, 0x07, 0x0a, 0x16, 0x41, 0x64, + 0x6d, 0x69, 0x6e, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x77, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, + 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x65, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, - 0x63, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, - 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, - 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, - 0x61, 0x72, 0x64, 0x12, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, - 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, - 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x4c, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, + 0x79, 0x63, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, + 0x79, 0x63, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, + 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, + 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, + 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, + 0x72, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x12, 0x47, 0x65, 0x74, + 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x12, + 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, + 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, + 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x15, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, + 0x43, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, + 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, + 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x18, 0x53, 0x65, 0x74, + 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x57, 0x65, 0x65, + 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x43, 0x79, 0x63, 0x6c, 0x65, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, - 0x72, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x33, 0x2e, 0x68, + 0x72, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x53, - 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x4c, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, - 0x53, 0x74, 0x61, 0x72, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xab, 0x03, 0x0a, 0x18, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x7a, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x50, 0x57, 0x65, 0x65, - 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2f, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, - 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, - 0x6e, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x83, 0x01, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x50, 0x57, 0x65, 0x65, - 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, - 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, - 0x52, 0x61, 0x6e, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x50, 0x57, 0x65, - 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x6c, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, + 0x53, 0x74, 0x61, 0x72, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, + 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, + 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x72, 0x53, 0x65, 0x74, + 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x32, 0xab, 0x03, 0x0a, 0x18, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, + 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7a, 0x0a, + 0x15, 0x47, 0x65, 0x74, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x50, + 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, + 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x18, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, + 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x8c, 0x01, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, + 0x52, 0x61, 0x6e, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, + 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, + 0x52, 0x61, 0x6e, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x6c, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x50, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, - 0x6e, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe2, 0x07, 0x0a, 0x19, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, - 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x12, - 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, - 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, - 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, - 0x63, 0x6c, 0x65, 0x12, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, - 0x72, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, - 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x15, - 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, - 0x43, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe2, + 0x07, 0x0a, 0x19, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, + 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x80, 0x01, 0x0a, + 0x17, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, + 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x12, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, + 0x63, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, + 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x83, 0x01, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, + 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x32, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, + 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, + 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, + 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, + 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x2f, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, + 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, + 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x83, 0x01, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, + 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x32, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, + 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, + 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x18, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, - 0x43, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, - 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, - 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, - 0x73, 0x65, 0x72, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, - 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8c, - 0x01, 0x0a, 0x1b, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, - 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x35, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x53, 0x65, 0x74, 0x41, + 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, + 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x92, 0x01, - 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, - 0x69, 0x6e, 0x67, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, - 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x92, 0x01, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x41, + 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x37, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x95, 0x01, 0x0a, 0x1e, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, - 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x70, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x39, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x94, 0x02, 0x0a, 0x16, 0x53, - 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x65, 0x76, - 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, - 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, - 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x13, 0x53, - 0x69, 0x67, 0x6e, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x49, 0x6e, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x53, 0x65, 0x76, 0x65, 0x6e, - 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, - 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x32, 0xbb, 0x03, 0x0a, 0x1b, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x53, 0x65, 0x76, 0x65, 0x6e, - 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x83, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, - 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x95, 0x01, 0x0a, 0x1e, + 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, + 0x69, 0x6e, 0x67, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, - 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, - 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, + 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, + 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, + 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x32, 0x94, 0x02, 0x0a, 0x16, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x83, + 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x32, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x49, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x13, 0x53, 0x69, 0x67, 0x6e, 0x53, 0x65, 0x76, 0x65, + 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x12, 0x2d, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x69, 0x67, 0x6e, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xbb, 0x03, 0x0a, 0x1b, 0x41, + 0x64, 0x6d, 0x69, 0x6e, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x49, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x18, 0x47, + 0x65, 0x74, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, + 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, + 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x49, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x76, 0x65, 0x6e, + 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x76, 0x65, 0x6e, + 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, - 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, + 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x86, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x12, 0x33, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x76, 0x65, 0x6e, + 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe5, 0x05, 0x0a, 0x17, 0x41, 0x64, 0x6d, + 0x69, 0x6e, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x68, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x76, 0x65, + 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, + 0x0a, 0x10, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x72, 0x61, + 0x63, 0x6b, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, - 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x43, 0x6c, - 0x61, 0x69, 0x6d, 0x73, 0x12, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x76, - 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x43, 0x6c, 0x61, 0x69, - 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x65, 0x76, 0x65, 0x6e, 0x44, 0x61, 0x79, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, - 0x6e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, - 0xc4, 0x03, 0x0a, 0x17, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x4c, - 0x65, 0x76, 0x65, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x68, 0x0a, 0x0f, 0x4c, - 0x69, 0x73, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, + 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x72, + 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0f, 0x55, + 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x10, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, - 0x65, 0x76, 0x65, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x75, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, - 0x73, 0x65, 0x72, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, - 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0f, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x65, 0x76, 0x65, - 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, - 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, - 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0f, - 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x69, 0x65, 0x72, 0x12, - 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, - 0x69, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x69, 0x65, 0x72, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xae, 0x03, 0x0a, 0x17, 0x41, 0x64, 0x6d, 0x69, 0x6e, - 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x75, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, + 0x73, 0x65, 0x72, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0f, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x54, 0x69, 0x65, 0x72, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, + 0x65, 0x72, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x54, 0x69, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4c, 0x65, + 0x76, 0x65, 0x6c, 0x54, 0x69, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x95, 0x01, 0x0a, 0x1e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, + 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x12, 0x38, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x55, 0x70, - 0x73, 0x65, 0x72, 0x74, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, - 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, - 0x73, 0x65, 0x72, 0x74, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, - 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x63, 0x68, 0x69, 0x65, - 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, - 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, - 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc7, 0x03, 0x0a, 0x11, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x65, 0x0a, - 0x0e, 0x47, 0x65, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, 0x0a, 0x19, 0x41, 0x64, 0x6a, 0x75, + 0x73, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x55, 0x73, 0x65, 0x72, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x73, 0x12, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, + 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x64, 0x6a, 0x75, 0x73, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x55, 0x73, + 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x32, 0xae, 0x03, 0x0a, 0x17, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x75, 0x0a, 0x1a, + 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, + 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, + 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x63, + 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x63, + 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x68, + 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x68, + 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x68, 0x69, 0x65, 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, + 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x32, 0xc7, 0x03, 0x0a, 0x11, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x57, 0x68, 0x65, 0x65, 0x6c, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x65, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x57, 0x68, + 0x65, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x11, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x57, 0x68, - 0x65, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, - 0x73, 0x65, 0x72, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, - 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x68, 0x65, 0x65, - 0x6c, 0x44, 0x72, 0x61, 0x77, 0x73, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, - 0x68, 0x65, 0x65, 0x6c, 0x44, 0x72, 0x61, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, + 0x0a, 0x11, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x57, 0x68, + 0x65, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, + 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x44, 0x72, 0x61, 0x77, 0x73, + 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x44, 0x72, - 0x61, 0x77, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x13, 0x47, - 0x65, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x44, 0x72, 0x61, 0x77, 0x53, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x79, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x44, - 0x72, 0x61, 0x77, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x44, 0x72, - 0x61, 0x77, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x42, 0x2e, 0x5a, 0x2c, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x76, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x44, 0x72, 0x61, 0x77, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x57, 0x68, 0x65, 0x65, + 0x6c, 0x44, 0x72, 0x61, 0x77, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x2d, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x44, 0x72, 0x61, 0x77, 0x53, 0x75, 0x6d, + 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x57, 0x68, 0x65, 0x65, 0x6c, 0x44, 0x72, 0x61, 0x77, 0x53, 0x75, 0x6d, 0x6d, + 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2e, 0x5a, 0x2c, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2f, 0x76, 0x31, + 0x3b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -26123,7 +26772,7 @@ func file_proto_activity_v1_activity_proto_rawDescGZIP() []byte { return file_proto_activity_v1_activity_proto_rawDescData } -var file_proto_activity_v1_activity_proto_msgTypes = make([]protoimpl.MessageInfo, 269) +var file_proto_activity_v1_activity_proto_msgTypes = make([]protoimpl.MessageInfo, 276) var file_proto_activity_v1_activity_proto_goTypes = []any{ (*RequestMeta)(nil), // 0: hyapp.activity.v1.RequestMeta (*PingActivityRequest)(nil), // 1: hyapp.activity.v1.PingActivityRequest @@ -26296,105 +26945,112 @@ var file_proto_activity_v1_activity_proto_goTypes = []any{ (*ConsumeLevelEventResponse)(nil), // 168: hyapp.activity.v1.ConsumeLevelEventResponse (*SetUserLevelRequest)(nil), // 169: hyapp.activity.v1.SetUserLevelRequest (*SetUserLevelResponse)(nil), // 170: hyapp.activity.v1.SetUserLevelResponse - (*RegistrationLevelBadgeGrant)(nil), // 171: hyapp.activity.v1.RegistrationLevelBadgeGrant - (*IssueRegistrationLevelBadgesRequest)(nil), // 172: hyapp.activity.v1.IssueRegistrationLevelBadgesRequest - (*IssueRegistrationLevelBadgesResponse)(nil), // 173: hyapp.activity.v1.IssueRegistrationLevelBadgesResponse - (*UpsertLevelTrackRequest)(nil), // 174: hyapp.activity.v1.UpsertLevelTrackRequest - (*UpsertLevelTrackResponse)(nil), // 175: hyapp.activity.v1.UpsertLevelTrackResponse - (*UpsertLevelRuleRequest)(nil), // 176: hyapp.activity.v1.UpsertLevelRuleRequest - (*UpsertLevelRuleResponse)(nil), // 177: hyapp.activity.v1.UpsertLevelRuleResponse - (*UpsertLevelTierRequest)(nil), // 178: hyapp.activity.v1.UpsertLevelTierRequest - (*UpsertLevelTierResponse)(nil), // 179: hyapp.activity.v1.UpsertLevelTierResponse - (*ListLevelConfigRequest)(nil), // 180: hyapp.activity.v1.ListLevelConfigRequest - (*ListLevelConfigResponse)(nil), // 181: hyapp.activity.v1.ListLevelConfigResponse - (*AchievementCondition)(nil), // 182: hyapp.activity.v1.AchievementCondition - (*AchievementDefinition)(nil), // 183: hyapp.activity.v1.AchievementDefinition - (*UserAchievement)(nil), // 184: hyapp.activity.v1.UserAchievement - (*ListAchievementsRequest)(nil), // 185: hyapp.activity.v1.ListAchievementsRequest - (*ListAchievementsResponse)(nil), // 186: hyapp.activity.v1.ListAchievementsResponse - (*ConsumeAchievementEventRequest)(nil), // 187: hyapp.activity.v1.ConsumeAchievementEventRequest - (*ConsumeAchievementEventResponse)(nil), // 188: hyapp.activity.v1.ConsumeAchievementEventResponse - (*BadgeDisplayItem)(nil), // 189: hyapp.activity.v1.BadgeDisplayItem - (*ListMyBadgesRequest)(nil), // 190: hyapp.activity.v1.ListMyBadgesRequest - (*ListMyBadgesResponse)(nil), // 191: hyapp.activity.v1.ListMyBadgesResponse - (*SetBadgeDisplayRequest)(nil), // 192: hyapp.activity.v1.SetBadgeDisplayRequest - (*SetBadgeDisplayResponse)(nil), // 193: hyapp.activity.v1.SetBadgeDisplayResponse - (*UpsertAchievementDefinitionRequest)(nil), // 194: hyapp.activity.v1.UpsertAchievementDefinitionRequest - (*UpsertAchievementDefinitionResponse)(nil), // 195: hyapp.activity.v1.UpsertAchievementDefinitionResponse - (*DeleteAchievementDefinitionRequest)(nil), // 196: hyapp.activity.v1.DeleteAchievementDefinitionRequest - (*DeleteAchievementDefinitionResponse)(nil), // 197: hyapp.activity.v1.DeleteAchievementDefinitionResponse - (*WheelPrizeTier)(nil), // 198: hyapp.activity.v1.WheelPrizeTier - (*WheelRuleConfig)(nil), // 199: hyapp.activity.v1.WheelRuleConfig - (*WheelDrawMeta)(nil), // 200: hyapp.activity.v1.WheelDrawMeta - (*WheelDrawResult)(nil), // 201: hyapp.activity.v1.WheelDrawResult - (*WheelDrawReward)(nil), // 202: hyapp.activity.v1.WheelDrawReward - (*ExecuteWheelDrawRequest)(nil), // 203: hyapp.activity.v1.ExecuteWheelDrawRequest - (*ExecuteWheelDrawResponse)(nil), // 204: hyapp.activity.v1.ExecuteWheelDrawResponse - (*GetWheelConfigRequest)(nil), // 205: hyapp.activity.v1.GetWheelConfigRequest - (*GetWheelConfigResponse)(nil), // 206: hyapp.activity.v1.GetWheelConfigResponse - (*UpsertWheelConfigRequest)(nil), // 207: hyapp.activity.v1.UpsertWheelConfigRequest - (*UpsertWheelConfigResponse)(nil), // 208: hyapp.activity.v1.UpsertWheelConfigResponse - (*ListWheelDrawsRequest)(nil), // 209: hyapp.activity.v1.ListWheelDrawsRequest - (*ListWheelDrawsResponse)(nil), // 210: hyapp.activity.v1.ListWheelDrawsResponse - (*WheelDrawSummary)(nil), // 211: hyapp.activity.v1.WheelDrawSummary - (*GetWheelDrawSummaryRequest)(nil), // 212: hyapp.activity.v1.GetWheelDrawSummaryRequest - (*GetWheelDrawSummaryResponse)(nil), // 213: hyapp.activity.v1.GetWheelDrawSummaryResponse - (*WeeklyStarGift)(nil), // 214: hyapp.activity.v1.WeeklyStarGift - (*WeeklyStarReward)(nil), // 215: hyapp.activity.v1.WeeklyStarReward - (*WeeklyStarCycle)(nil), // 216: hyapp.activity.v1.WeeklyStarCycle - (*WeeklyStarLeaderboardEntry)(nil), // 217: hyapp.activity.v1.WeeklyStarLeaderboardEntry - (*WeeklyStarSettlement)(nil), // 218: hyapp.activity.v1.WeeklyStarSettlement - (*ListWeeklyStarCyclesRequest)(nil), // 219: hyapp.activity.v1.ListWeeklyStarCyclesRequest - (*ListWeeklyStarCyclesResponse)(nil), // 220: hyapp.activity.v1.ListWeeklyStarCyclesResponse - (*GetWeeklyStarCycleRequest)(nil), // 221: hyapp.activity.v1.GetWeeklyStarCycleRequest - (*GetWeeklyStarCycleResponse)(nil), // 222: hyapp.activity.v1.GetWeeklyStarCycleResponse - (*UpsertWeeklyStarCycleRequest)(nil), // 223: hyapp.activity.v1.UpsertWeeklyStarCycleRequest - (*UpsertWeeklyStarCycleResponse)(nil), // 224: hyapp.activity.v1.UpsertWeeklyStarCycleResponse - (*SetWeeklyStarCycleStatusRequest)(nil), // 225: hyapp.activity.v1.SetWeeklyStarCycleStatusRequest - (*SetWeeklyStarCycleStatusResponse)(nil), // 226: hyapp.activity.v1.SetWeeklyStarCycleStatusResponse - (*ListWeeklyStarLeaderboardRequest)(nil), // 227: hyapp.activity.v1.ListWeeklyStarLeaderboardRequest - (*ListWeeklyStarLeaderboardResponse)(nil), // 228: hyapp.activity.v1.ListWeeklyStarLeaderboardResponse - (*ListWeeklyStarSettlementsRequest)(nil), // 229: hyapp.activity.v1.ListWeeklyStarSettlementsRequest - (*ListWeeklyStarSettlementsResponse)(nil), // 230: hyapp.activity.v1.ListWeeklyStarSettlementsResponse - (*GetWeeklyStarCurrentRequest)(nil), // 231: hyapp.activity.v1.GetWeeklyStarCurrentRequest - (*GetWeeklyStarCurrentResponse)(nil), // 232: hyapp.activity.v1.GetWeeklyStarCurrentResponse - (*ListWeeklyStarHistoryRequest)(nil), // 233: hyapp.activity.v1.ListWeeklyStarHistoryRequest - (*WeeklyStarHistoryCycle)(nil), // 234: hyapp.activity.v1.WeeklyStarHistoryCycle - (*ListWeeklyStarHistoryResponse)(nil), // 235: hyapp.activity.v1.ListWeeklyStarHistoryResponse - (*CPWeeklyRankReward)(nil), // 236: hyapp.activity.v1.CPWeeklyRankReward - (*CPWeeklyRankConfig)(nil), // 237: hyapp.activity.v1.CPWeeklyRankConfig - (*CPWeeklyRankUser)(nil), // 238: hyapp.activity.v1.CPWeeklyRankUser - (*CPWeeklyRankEntry)(nil), // 239: hyapp.activity.v1.CPWeeklyRankEntry - (*CPWeeklyRankSettlement)(nil), // 240: hyapp.activity.v1.CPWeeklyRankSettlement - (*GetCPWeeklyRankStatusRequest)(nil), // 241: hyapp.activity.v1.GetCPWeeklyRankStatusRequest - (*GetCPWeeklyRankStatusResponse)(nil), // 242: hyapp.activity.v1.GetCPWeeklyRankStatusResponse - (*GetCPWeeklyRankConfigRequest)(nil), // 243: hyapp.activity.v1.GetCPWeeklyRankConfigRequest - (*GetCPWeeklyRankConfigResponse)(nil), // 244: hyapp.activity.v1.GetCPWeeklyRankConfigResponse - (*UpdateCPWeeklyRankConfigRequest)(nil), // 245: hyapp.activity.v1.UpdateCPWeeklyRankConfigRequest - (*UpdateCPWeeklyRankConfigResponse)(nil), // 246: hyapp.activity.v1.UpdateCPWeeklyRankConfigResponse - (*ListCPWeeklyRankSettlementsRequest)(nil), // 247: hyapp.activity.v1.ListCPWeeklyRankSettlementsRequest - (*ListCPWeeklyRankSettlementsResponse)(nil), // 248: hyapp.activity.v1.ListCPWeeklyRankSettlementsResponse - (*AgencyOpeningReward)(nil), // 249: hyapp.activity.v1.AgencyOpeningReward - (*AgencyOpeningCycle)(nil), // 250: hyapp.activity.v1.AgencyOpeningCycle - (*AgencyOpeningApplication)(nil), // 251: hyapp.activity.v1.AgencyOpeningApplication - (*AgencyOpeningAgencySnapshot)(nil), // 252: hyapp.activity.v1.AgencyOpeningAgencySnapshot - (*ListAgencyOpeningCyclesRequest)(nil), // 253: hyapp.activity.v1.ListAgencyOpeningCyclesRequest - (*ListAgencyOpeningCyclesResponse)(nil), // 254: hyapp.activity.v1.ListAgencyOpeningCyclesResponse - (*GetAgencyOpeningCycleRequest)(nil), // 255: hyapp.activity.v1.GetAgencyOpeningCycleRequest - (*GetAgencyOpeningCycleResponse)(nil), // 256: hyapp.activity.v1.GetAgencyOpeningCycleResponse - (*UpsertAgencyOpeningCycleRequest)(nil), // 257: hyapp.activity.v1.UpsertAgencyOpeningCycleRequest - (*UpsertAgencyOpeningCycleResponse)(nil), // 258: hyapp.activity.v1.UpsertAgencyOpeningCycleResponse - (*SetAgencyOpeningCycleStatusRequest)(nil), // 259: hyapp.activity.v1.SetAgencyOpeningCycleStatusRequest - (*SetAgencyOpeningCycleStatusResponse)(nil), // 260: hyapp.activity.v1.SetAgencyOpeningCycleStatusResponse - (*ListAgencyOpeningApplicationsRequest)(nil), // 261: hyapp.activity.v1.ListAgencyOpeningApplicationsRequest - (*ListAgencyOpeningApplicationsResponse)(nil), // 262: hyapp.activity.v1.ListAgencyOpeningApplicationsResponse - (*ReviewAgencyOpeningApplicationRequest)(nil), // 263: hyapp.activity.v1.ReviewAgencyOpeningApplicationRequest - (*ReviewAgencyOpeningApplicationResponse)(nil), // 264: hyapp.activity.v1.ReviewAgencyOpeningApplicationResponse - (*GetAgencyOpeningStatusRequest)(nil), // 265: hyapp.activity.v1.GetAgencyOpeningStatusRequest - (*GetAgencyOpeningStatusResponse)(nil), // 266: hyapp.activity.v1.GetAgencyOpeningStatusResponse - (*ApplyAgencyOpeningRequest)(nil), // 267: hyapp.activity.v1.ApplyAgencyOpeningRequest - (*ApplyAgencyOpeningResponse)(nil), // 268: hyapp.activity.v1.ApplyAgencyOpeningResponse - (*v1.EventEnvelope)(nil), // 269: hyapp.events.room.v1.EventEnvelope + (*AdminLevelTrackProfile)(nil), // 171: hyapp.activity.v1.AdminLevelTrackProfile + (*AdminUserLevelProfile)(nil), // 172: hyapp.activity.v1.AdminUserLevelProfile + (*BatchGetUserLevelAdminProfilesRequest)(nil), // 173: hyapp.activity.v1.BatchGetUserLevelAdminProfilesRequest + (*BatchGetUserLevelAdminProfilesResponse)(nil), // 174: hyapp.activity.v1.BatchGetUserLevelAdminProfilesResponse + (*TemporaryLevelAdjustment)(nil), // 175: hyapp.activity.v1.TemporaryLevelAdjustment + (*AdjustTemporaryUserLevelsRequest)(nil), // 176: hyapp.activity.v1.AdjustTemporaryUserLevelsRequest + (*AdjustTemporaryUserLevelsResponse)(nil), // 177: hyapp.activity.v1.AdjustTemporaryUserLevelsResponse + (*RegistrationLevelBadgeGrant)(nil), // 178: hyapp.activity.v1.RegistrationLevelBadgeGrant + (*IssueRegistrationLevelBadgesRequest)(nil), // 179: hyapp.activity.v1.IssueRegistrationLevelBadgesRequest + (*IssueRegistrationLevelBadgesResponse)(nil), // 180: hyapp.activity.v1.IssueRegistrationLevelBadgesResponse + (*UpsertLevelTrackRequest)(nil), // 181: hyapp.activity.v1.UpsertLevelTrackRequest + (*UpsertLevelTrackResponse)(nil), // 182: hyapp.activity.v1.UpsertLevelTrackResponse + (*UpsertLevelRuleRequest)(nil), // 183: hyapp.activity.v1.UpsertLevelRuleRequest + (*UpsertLevelRuleResponse)(nil), // 184: hyapp.activity.v1.UpsertLevelRuleResponse + (*UpsertLevelTierRequest)(nil), // 185: hyapp.activity.v1.UpsertLevelTierRequest + (*UpsertLevelTierResponse)(nil), // 186: hyapp.activity.v1.UpsertLevelTierResponse + (*ListLevelConfigRequest)(nil), // 187: hyapp.activity.v1.ListLevelConfigRequest + (*ListLevelConfigResponse)(nil), // 188: hyapp.activity.v1.ListLevelConfigResponse + (*AchievementCondition)(nil), // 189: hyapp.activity.v1.AchievementCondition + (*AchievementDefinition)(nil), // 190: hyapp.activity.v1.AchievementDefinition + (*UserAchievement)(nil), // 191: hyapp.activity.v1.UserAchievement + (*ListAchievementsRequest)(nil), // 192: hyapp.activity.v1.ListAchievementsRequest + (*ListAchievementsResponse)(nil), // 193: hyapp.activity.v1.ListAchievementsResponse + (*ConsumeAchievementEventRequest)(nil), // 194: hyapp.activity.v1.ConsumeAchievementEventRequest + (*ConsumeAchievementEventResponse)(nil), // 195: hyapp.activity.v1.ConsumeAchievementEventResponse + (*BadgeDisplayItem)(nil), // 196: hyapp.activity.v1.BadgeDisplayItem + (*ListMyBadgesRequest)(nil), // 197: hyapp.activity.v1.ListMyBadgesRequest + (*ListMyBadgesResponse)(nil), // 198: hyapp.activity.v1.ListMyBadgesResponse + (*SetBadgeDisplayRequest)(nil), // 199: hyapp.activity.v1.SetBadgeDisplayRequest + (*SetBadgeDisplayResponse)(nil), // 200: hyapp.activity.v1.SetBadgeDisplayResponse + (*UpsertAchievementDefinitionRequest)(nil), // 201: hyapp.activity.v1.UpsertAchievementDefinitionRequest + (*UpsertAchievementDefinitionResponse)(nil), // 202: hyapp.activity.v1.UpsertAchievementDefinitionResponse + (*DeleteAchievementDefinitionRequest)(nil), // 203: hyapp.activity.v1.DeleteAchievementDefinitionRequest + (*DeleteAchievementDefinitionResponse)(nil), // 204: hyapp.activity.v1.DeleteAchievementDefinitionResponse + (*WheelPrizeTier)(nil), // 205: hyapp.activity.v1.WheelPrizeTier + (*WheelRuleConfig)(nil), // 206: hyapp.activity.v1.WheelRuleConfig + (*WheelDrawMeta)(nil), // 207: hyapp.activity.v1.WheelDrawMeta + (*WheelDrawResult)(nil), // 208: hyapp.activity.v1.WheelDrawResult + (*WheelDrawReward)(nil), // 209: hyapp.activity.v1.WheelDrawReward + (*ExecuteWheelDrawRequest)(nil), // 210: hyapp.activity.v1.ExecuteWheelDrawRequest + (*ExecuteWheelDrawResponse)(nil), // 211: hyapp.activity.v1.ExecuteWheelDrawResponse + (*GetWheelConfigRequest)(nil), // 212: hyapp.activity.v1.GetWheelConfigRequest + (*GetWheelConfigResponse)(nil), // 213: hyapp.activity.v1.GetWheelConfigResponse + (*UpsertWheelConfigRequest)(nil), // 214: hyapp.activity.v1.UpsertWheelConfigRequest + (*UpsertWheelConfigResponse)(nil), // 215: hyapp.activity.v1.UpsertWheelConfigResponse + (*ListWheelDrawsRequest)(nil), // 216: hyapp.activity.v1.ListWheelDrawsRequest + (*ListWheelDrawsResponse)(nil), // 217: hyapp.activity.v1.ListWheelDrawsResponse + (*WheelDrawSummary)(nil), // 218: hyapp.activity.v1.WheelDrawSummary + (*GetWheelDrawSummaryRequest)(nil), // 219: hyapp.activity.v1.GetWheelDrawSummaryRequest + (*GetWheelDrawSummaryResponse)(nil), // 220: hyapp.activity.v1.GetWheelDrawSummaryResponse + (*WeeklyStarGift)(nil), // 221: hyapp.activity.v1.WeeklyStarGift + (*WeeklyStarReward)(nil), // 222: hyapp.activity.v1.WeeklyStarReward + (*WeeklyStarCycle)(nil), // 223: hyapp.activity.v1.WeeklyStarCycle + (*WeeklyStarLeaderboardEntry)(nil), // 224: hyapp.activity.v1.WeeklyStarLeaderboardEntry + (*WeeklyStarSettlement)(nil), // 225: hyapp.activity.v1.WeeklyStarSettlement + (*ListWeeklyStarCyclesRequest)(nil), // 226: hyapp.activity.v1.ListWeeklyStarCyclesRequest + (*ListWeeklyStarCyclesResponse)(nil), // 227: hyapp.activity.v1.ListWeeklyStarCyclesResponse + (*GetWeeklyStarCycleRequest)(nil), // 228: hyapp.activity.v1.GetWeeklyStarCycleRequest + (*GetWeeklyStarCycleResponse)(nil), // 229: hyapp.activity.v1.GetWeeklyStarCycleResponse + (*UpsertWeeklyStarCycleRequest)(nil), // 230: hyapp.activity.v1.UpsertWeeklyStarCycleRequest + (*UpsertWeeklyStarCycleResponse)(nil), // 231: hyapp.activity.v1.UpsertWeeklyStarCycleResponse + (*SetWeeklyStarCycleStatusRequest)(nil), // 232: hyapp.activity.v1.SetWeeklyStarCycleStatusRequest + (*SetWeeklyStarCycleStatusResponse)(nil), // 233: hyapp.activity.v1.SetWeeklyStarCycleStatusResponse + (*ListWeeklyStarLeaderboardRequest)(nil), // 234: hyapp.activity.v1.ListWeeklyStarLeaderboardRequest + (*ListWeeklyStarLeaderboardResponse)(nil), // 235: hyapp.activity.v1.ListWeeklyStarLeaderboardResponse + (*ListWeeklyStarSettlementsRequest)(nil), // 236: hyapp.activity.v1.ListWeeklyStarSettlementsRequest + (*ListWeeklyStarSettlementsResponse)(nil), // 237: hyapp.activity.v1.ListWeeklyStarSettlementsResponse + (*GetWeeklyStarCurrentRequest)(nil), // 238: hyapp.activity.v1.GetWeeklyStarCurrentRequest + (*GetWeeklyStarCurrentResponse)(nil), // 239: hyapp.activity.v1.GetWeeklyStarCurrentResponse + (*ListWeeklyStarHistoryRequest)(nil), // 240: hyapp.activity.v1.ListWeeklyStarHistoryRequest + (*WeeklyStarHistoryCycle)(nil), // 241: hyapp.activity.v1.WeeklyStarHistoryCycle + (*ListWeeklyStarHistoryResponse)(nil), // 242: hyapp.activity.v1.ListWeeklyStarHistoryResponse + (*CPWeeklyRankReward)(nil), // 243: hyapp.activity.v1.CPWeeklyRankReward + (*CPWeeklyRankConfig)(nil), // 244: hyapp.activity.v1.CPWeeklyRankConfig + (*CPWeeklyRankUser)(nil), // 245: hyapp.activity.v1.CPWeeklyRankUser + (*CPWeeklyRankEntry)(nil), // 246: hyapp.activity.v1.CPWeeklyRankEntry + (*CPWeeklyRankSettlement)(nil), // 247: hyapp.activity.v1.CPWeeklyRankSettlement + (*GetCPWeeklyRankStatusRequest)(nil), // 248: hyapp.activity.v1.GetCPWeeklyRankStatusRequest + (*GetCPWeeklyRankStatusResponse)(nil), // 249: hyapp.activity.v1.GetCPWeeklyRankStatusResponse + (*GetCPWeeklyRankConfigRequest)(nil), // 250: hyapp.activity.v1.GetCPWeeklyRankConfigRequest + (*GetCPWeeklyRankConfigResponse)(nil), // 251: hyapp.activity.v1.GetCPWeeklyRankConfigResponse + (*UpdateCPWeeklyRankConfigRequest)(nil), // 252: hyapp.activity.v1.UpdateCPWeeklyRankConfigRequest + (*UpdateCPWeeklyRankConfigResponse)(nil), // 253: hyapp.activity.v1.UpdateCPWeeklyRankConfigResponse + (*ListCPWeeklyRankSettlementsRequest)(nil), // 254: hyapp.activity.v1.ListCPWeeklyRankSettlementsRequest + (*ListCPWeeklyRankSettlementsResponse)(nil), // 255: hyapp.activity.v1.ListCPWeeklyRankSettlementsResponse + (*AgencyOpeningReward)(nil), // 256: hyapp.activity.v1.AgencyOpeningReward + (*AgencyOpeningCycle)(nil), // 257: hyapp.activity.v1.AgencyOpeningCycle + (*AgencyOpeningApplication)(nil), // 258: hyapp.activity.v1.AgencyOpeningApplication + (*AgencyOpeningAgencySnapshot)(nil), // 259: hyapp.activity.v1.AgencyOpeningAgencySnapshot + (*ListAgencyOpeningCyclesRequest)(nil), // 260: hyapp.activity.v1.ListAgencyOpeningCyclesRequest + (*ListAgencyOpeningCyclesResponse)(nil), // 261: hyapp.activity.v1.ListAgencyOpeningCyclesResponse + (*GetAgencyOpeningCycleRequest)(nil), // 262: hyapp.activity.v1.GetAgencyOpeningCycleRequest + (*GetAgencyOpeningCycleResponse)(nil), // 263: hyapp.activity.v1.GetAgencyOpeningCycleResponse + (*UpsertAgencyOpeningCycleRequest)(nil), // 264: hyapp.activity.v1.UpsertAgencyOpeningCycleRequest + (*UpsertAgencyOpeningCycleResponse)(nil), // 265: hyapp.activity.v1.UpsertAgencyOpeningCycleResponse + (*SetAgencyOpeningCycleStatusRequest)(nil), // 266: hyapp.activity.v1.SetAgencyOpeningCycleStatusRequest + (*SetAgencyOpeningCycleStatusResponse)(nil), // 267: hyapp.activity.v1.SetAgencyOpeningCycleStatusResponse + (*ListAgencyOpeningApplicationsRequest)(nil), // 268: hyapp.activity.v1.ListAgencyOpeningApplicationsRequest + (*ListAgencyOpeningApplicationsResponse)(nil), // 269: hyapp.activity.v1.ListAgencyOpeningApplicationsResponse + (*ReviewAgencyOpeningApplicationRequest)(nil), // 270: hyapp.activity.v1.ReviewAgencyOpeningApplicationRequest + (*ReviewAgencyOpeningApplicationResponse)(nil), // 271: hyapp.activity.v1.ReviewAgencyOpeningApplicationResponse + (*GetAgencyOpeningStatusRequest)(nil), // 272: hyapp.activity.v1.GetAgencyOpeningStatusRequest + (*GetAgencyOpeningStatusResponse)(nil), // 273: hyapp.activity.v1.GetAgencyOpeningStatusResponse + (*ApplyAgencyOpeningRequest)(nil), // 274: hyapp.activity.v1.ApplyAgencyOpeningRequest + (*ApplyAgencyOpeningResponse)(nil), // 275: hyapp.activity.v1.ApplyAgencyOpeningResponse + (*v1.EventEnvelope)(nil), // 276: hyapp.events.room.v1.EventEnvelope } var file_proto_activity_v1_activity_proto_depIdxs = []int32{ 0, // 0: hyapp.activity.v1.PingActivityRequest.meta:type_name -> hyapp.activity.v1.RequestMeta @@ -26427,7 +27083,7 @@ var file_proto_activity_v1_activity_proto_depIdxs = []int32{ 0, // 27: hyapp.activity.v1.PublishGlobalBroadcastRequest.meta:type_name -> hyapp.activity.v1.RequestMeta 0, // 28: hyapp.activity.v1.RemoveRegionBroadcastMemberRequest.meta:type_name -> hyapp.activity.v1.RequestMeta 0, // 29: hyapp.activity.v1.ConsumeRoomEventRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 269, // 30: hyapp.activity.v1.ConsumeRoomEventRequest.envelope:type_name -> hyapp.events.room.v1.EventEnvelope + 276, // 30: hyapp.activity.v1.ConsumeRoomEventRequest.envelope:type_name -> hyapp.events.room.v1.EventEnvelope 0, // 31: hyapp.activity.v1.ListTaskDefinitionsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta 51, // 32: hyapp.activity.v1.ListTaskDefinitionsResponse.tasks:type_name -> hyapp.activity.v1.TaskDefinition 0, // 33: hyapp.activity.v1.UpsertTaskDefinitionRequest.meta:type_name -> hyapp.activity.v1.RequestMeta @@ -26538,336 +27194,348 @@ var file_proto_activity_v1_activity_proto_depIdxs = []int32{ 164, // 138: hyapp.activity.v1.ListLevelRewardsResponse.rewards:type_name -> hyapp.activity.v1.LevelRewardJob 0, // 139: hyapp.activity.v1.ConsumeLevelEventRequest.meta:type_name -> hyapp.activity.v1.RequestMeta 0, // 140: hyapp.activity.v1.SetUserLevelRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 0, // 141: hyapp.activity.v1.IssueRegistrationLevelBadgesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 171, // 142: hyapp.activity.v1.IssueRegistrationLevelBadgesResponse.grants:type_name -> hyapp.activity.v1.RegistrationLevelBadgeGrant - 0, // 143: hyapp.activity.v1.UpsertLevelTrackRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 152, // 144: hyapp.activity.v1.UpsertLevelTrackResponse.track:type_name -> hyapp.activity.v1.LevelTrack - 0, // 145: hyapp.activity.v1.UpsertLevelRuleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 153, // 146: hyapp.activity.v1.UpsertLevelRuleResponse.rule:type_name -> hyapp.activity.v1.LevelRule - 0, // 147: hyapp.activity.v1.UpsertLevelTierRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 154, // 148: hyapp.activity.v1.UpsertLevelTierResponse.tier:type_name -> hyapp.activity.v1.LevelTier - 0, // 149: hyapp.activity.v1.ListLevelConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 152, // 150: hyapp.activity.v1.ListLevelConfigResponse.tracks:type_name -> hyapp.activity.v1.LevelTrack - 153, // 151: hyapp.activity.v1.ListLevelConfigResponse.rules:type_name -> hyapp.activity.v1.LevelRule - 154, // 152: hyapp.activity.v1.ListLevelConfigResponse.tiers:type_name -> hyapp.activity.v1.LevelTier - 182, // 153: hyapp.activity.v1.AchievementDefinition.conditions:type_name -> hyapp.activity.v1.AchievementCondition - 183, // 154: hyapp.activity.v1.UserAchievement.definition:type_name -> hyapp.activity.v1.AchievementDefinition - 0, // 155: hyapp.activity.v1.ListAchievementsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 184, // 156: hyapp.activity.v1.ListAchievementsResponse.achievements:type_name -> hyapp.activity.v1.UserAchievement - 0, // 157: hyapp.activity.v1.ConsumeAchievementEventRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 0, // 158: hyapp.activity.v1.ListMyBadgesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 189, // 159: hyapp.activity.v1.ListMyBadgesResponse.strip_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem - 189, // 160: hyapp.activity.v1.ListMyBadgesResponse.profile_tile_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem - 189, // 161: hyapp.activity.v1.ListMyBadgesResponse.honor_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem - 0, // 162: hyapp.activity.v1.SetBadgeDisplayRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 189, // 163: hyapp.activity.v1.SetBadgeDisplayRequest.items:type_name -> hyapp.activity.v1.BadgeDisplayItem - 191, // 164: hyapp.activity.v1.SetBadgeDisplayResponse.profile:type_name -> hyapp.activity.v1.ListMyBadgesResponse - 0, // 165: hyapp.activity.v1.UpsertAchievementDefinitionRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 182, // 166: hyapp.activity.v1.UpsertAchievementDefinitionRequest.conditions:type_name -> hyapp.activity.v1.AchievementCondition - 183, // 167: hyapp.activity.v1.UpsertAchievementDefinitionResponse.achievement:type_name -> hyapp.activity.v1.AchievementDefinition - 0, // 168: hyapp.activity.v1.DeleteAchievementDefinitionRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 183, // 169: hyapp.activity.v1.DeleteAchievementDefinitionResponse.achievement:type_name -> hyapp.activity.v1.AchievementDefinition - 198, // 170: hyapp.activity.v1.WheelRuleConfig.tiers:type_name -> hyapp.activity.v1.WheelPrizeTier - 0, // 171: hyapp.activity.v1.WheelDrawMeta.meta:type_name -> hyapp.activity.v1.RequestMeta - 202, // 172: hyapp.activity.v1.WheelDrawResult.rewards:type_name -> hyapp.activity.v1.WheelDrawReward - 200, // 173: hyapp.activity.v1.ExecuteWheelDrawRequest.wheel:type_name -> hyapp.activity.v1.WheelDrawMeta - 201, // 174: hyapp.activity.v1.ExecuteWheelDrawResponse.result:type_name -> hyapp.activity.v1.WheelDrawResult - 0, // 175: hyapp.activity.v1.GetWheelConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 199, // 176: hyapp.activity.v1.GetWheelConfigResponse.config:type_name -> hyapp.activity.v1.WheelRuleConfig - 0, // 177: hyapp.activity.v1.UpsertWheelConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 199, // 178: hyapp.activity.v1.UpsertWheelConfigRequest.config:type_name -> hyapp.activity.v1.WheelRuleConfig - 199, // 179: hyapp.activity.v1.UpsertWheelConfigResponse.config:type_name -> hyapp.activity.v1.WheelRuleConfig - 0, // 180: hyapp.activity.v1.ListWheelDrawsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 201, // 181: hyapp.activity.v1.ListWheelDrawsResponse.draws:type_name -> hyapp.activity.v1.WheelDrawResult - 0, // 182: hyapp.activity.v1.GetWheelDrawSummaryRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 211, // 183: hyapp.activity.v1.GetWheelDrawSummaryResponse.summary:type_name -> hyapp.activity.v1.WheelDrawSummary - 214, // 184: hyapp.activity.v1.WeeklyStarCycle.gifts:type_name -> hyapp.activity.v1.WeeklyStarGift - 215, // 185: hyapp.activity.v1.WeeklyStarCycle.rewards:type_name -> hyapp.activity.v1.WeeklyStarReward - 0, // 186: hyapp.activity.v1.ListWeeklyStarCyclesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 216, // 187: hyapp.activity.v1.ListWeeklyStarCyclesResponse.cycles:type_name -> hyapp.activity.v1.WeeklyStarCycle - 0, // 188: hyapp.activity.v1.GetWeeklyStarCycleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 216, // 189: hyapp.activity.v1.GetWeeklyStarCycleResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle - 0, // 190: hyapp.activity.v1.UpsertWeeklyStarCycleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 216, // 191: hyapp.activity.v1.UpsertWeeklyStarCycleRequest.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle - 216, // 192: hyapp.activity.v1.UpsertWeeklyStarCycleResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle - 0, // 193: hyapp.activity.v1.SetWeeklyStarCycleStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 216, // 194: hyapp.activity.v1.SetWeeklyStarCycleStatusResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle - 0, // 195: hyapp.activity.v1.ListWeeklyStarLeaderboardRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 216, // 196: hyapp.activity.v1.ListWeeklyStarLeaderboardResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle - 217, // 197: hyapp.activity.v1.ListWeeklyStarLeaderboardResponse.entries:type_name -> hyapp.activity.v1.WeeklyStarLeaderboardEntry - 0, // 198: hyapp.activity.v1.ListWeeklyStarSettlementsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 218, // 199: hyapp.activity.v1.ListWeeklyStarSettlementsResponse.settlements:type_name -> hyapp.activity.v1.WeeklyStarSettlement - 0, // 200: hyapp.activity.v1.GetWeeklyStarCurrentRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 216, // 201: hyapp.activity.v1.GetWeeklyStarCurrentResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle - 217, // 202: hyapp.activity.v1.GetWeeklyStarCurrentResponse.top_entries:type_name -> hyapp.activity.v1.WeeklyStarLeaderboardEntry - 217, // 203: hyapp.activity.v1.GetWeeklyStarCurrentResponse.my_entry:type_name -> hyapp.activity.v1.WeeklyStarLeaderboardEntry - 0, // 204: hyapp.activity.v1.ListWeeklyStarHistoryRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 216, // 205: hyapp.activity.v1.WeeklyStarHistoryCycle.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle - 217, // 206: hyapp.activity.v1.WeeklyStarHistoryCycle.top_entries:type_name -> hyapp.activity.v1.WeeklyStarLeaderboardEntry - 234, // 207: hyapp.activity.v1.ListWeeklyStarHistoryResponse.cycles:type_name -> hyapp.activity.v1.WeeklyStarHistoryCycle - 236, // 208: hyapp.activity.v1.CPWeeklyRankConfig.rewards:type_name -> hyapp.activity.v1.CPWeeklyRankReward - 238, // 209: hyapp.activity.v1.CPWeeklyRankEntry.user_a:type_name -> hyapp.activity.v1.CPWeeklyRankUser - 238, // 210: hyapp.activity.v1.CPWeeklyRankEntry.user_b:type_name -> hyapp.activity.v1.CPWeeklyRankUser - 0, // 211: hyapp.activity.v1.GetCPWeeklyRankStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 237, // 212: hyapp.activity.v1.GetCPWeeklyRankStatusResponse.config:type_name -> hyapp.activity.v1.CPWeeklyRankConfig - 239, // 213: hyapp.activity.v1.GetCPWeeklyRankStatusResponse.entries:type_name -> hyapp.activity.v1.CPWeeklyRankEntry - 239, // 214: hyapp.activity.v1.GetCPWeeklyRankStatusResponse.previous_entries:type_name -> hyapp.activity.v1.CPWeeklyRankEntry - 0, // 215: hyapp.activity.v1.GetCPWeeklyRankConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 237, // 216: hyapp.activity.v1.GetCPWeeklyRankConfigResponse.config:type_name -> hyapp.activity.v1.CPWeeklyRankConfig - 0, // 217: hyapp.activity.v1.UpdateCPWeeklyRankConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 237, // 218: hyapp.activity.v1.UpdateCPWeeklyRankConfigRequest.config:type_name -> hyapp.activity.v1.CPWeeklyRankConfig - 237, // 219: hyapp.activity.v1.UpdateCPWeeklyRankConfigResponse.config:type_name -> hyapp.activity.v1.CPWeeklyRankConfig - 0, // 220: hyapp.activity.v1.ListCPWeeklyRankSettlementsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 240, // 221: hyapp.activity.v1.ListCPWeeklyRankSettlementsResponse.settlements:type_name -> hyapp.activity.v1.CPWeeklyRankSettlement - 249, // 222: hyapp.activity.v1.AgencyOpeningCycle.rewards:type_name -> hyapp.activity.v1.AgencyOpeningReward - 0, // 223: hyapp.activity.v1.ListAgencyOpeningCyclesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 250, // 224: hyapp.activity.v1.ListAgencyOpeningCyclesResponse.cycles:type_name -> hyapp.activity.v1.AgencyOpeningCycle - 0, // 225: hyapp.activity.v1.GetAgencyOpeningCycleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 250, // 226: hyapp.activity.v1.GetAgencyOpeningCycleResponse.cycle:type_name -> hyapp.activity.v1.AgencyOpeningCycle - 0, // 227: hyapp.activity.v1.UpsertAgencyOpeningCycleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 250, // 228: hyapp.activity.v1.UpsertAgencyOpeningCycleRequest.cycle:type_name -> hyapp.activity.v1.AgencyOpeningCycle - 250, // 229: hyapp.activity.v1.UpsertAgencyOpeningCycleResponse.cycle:type_name -> hyapp.activity.v1.AgencyOpeningCycle - 0, // 230: hyapp.activity.v1.SetAgencyOpeningCycleStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 250, // 231: hyapp.activity.v1.SetAgencyOpeningCycleStatusResponse.cycle:type_name -> hyapp.activity.v1.AgencyOpeningCycle - 0, // 232: hyapp.activity.v1.ListAgencyOpeningApplicationsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 251, // 233: hyapp.activity.v1.ListAgencyOpeningApplicationsResponse.applications:type_name -> hyapp.activity.v1.AgencyOpeningApplication - 0, // 234: hyapp.activity.v1.ReviewAgencyOpeningApplicationRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 251, // 235: hyapp.activity.v1.ReviewAgencyOpeningApplicationResponse.application:type_name -> hyapp.activity.v1.AgencyOpeningApplication - 0, // 236: hyapp.activity.v1.GetAgencyOpeningStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 250, // 237: hyapp.activity.v1.GetAgencyOpeningStatusResponse.cycle:type_name -> hyapp.activity.v1.AgencyOpeningCycle - 251, // 238: hyapp.activity.v1.GetAgencyOpeningStatusResponse.application:type_name -> hyapp.activity.v1.AgencyOpeningApplication - 252, // 239: hyapp.activity.v1.GetAgencyOpeningStatusResponse.agency:type_name -> hyapp.activity.v1.AgencyOpeningAgencySnapshot - 0, // 240: hyapp.activity.v1.ApplyAgencyOpeningRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 251, // 241: hyapp.activity.v1.ApplyAgencyOpeningResponse.application:type_name -> hyapp.activity.v1.AgencyOpeningApplication - 1, // 242: hyapp.activity.v1.ActivityService.PingActivity:input_type -> hyapp.activity.v1.PingActivityRequest - 3, // 243: hyapp.activity.v1.ActivityService.GetActivityStatus:input_type -> hyapp.activity.v1.GetActivityStatusRequest - 6, // 244: hyapp.activity.v1.MessageInboxService.ListMessageTabs:input_type -> hyapp.activity.v1.ListMessageTabsRequest - 9, // 245: hyapp.activity.v1.MessageInboxService.ListInboxMessages:input_type -> hyapp.activity.v1.ListInboxMessagesRequest - 11, // 246: hyapp.activity.v1.MessageInboxService.MarkInboxMessageRead:input_type -> hyapp.activity.v1.MarkInboxMessageReadRequest - 13, // 247: hyapp.activity.v1.MessageInboxService.MarkInboxSectionRead:input_type -> hyapp.activity.v1.MarkInboxSectionReadRequest - 15, // 248: hyapp.activity.v1.MessageInboxService.DeleteInboxMessage:input_type -> hyapp.activity.v1.DeleteInboxMessageRequest - 17, // 249: hyapp.activity.v1.MessageInboxService.CreateInboxMessage:input_type -> hyapp.activity.v1.CreateInboxMessageRequest - 19, // 250: hyapp.activity.v1.MessageInboxService.CreateFanoutJob:input_type -> hyapp.activity.v1.CreateFanoutJobRequest - 22, // 251: hyapp.activity.v1.MessageActionConfirmService.AcceptActionConfirm:input_type -> hyapp.activity.v1.AcceptActionConfirmRequest - 24, // 252: hyapp.activity.v1.MessageActionConfirmService.RejectActionConfirm:input_type -> hyapp.activity.v1.RejectActionConfirmRequest - 26, // 253: hyapp.activity.v1.MessageActionConfirmService.BatchGetActionConfirmStatus:input_type -> hyapp.activity.v1.BatchGetActionConfirmStatusRequest - 28, // 254: hyapp.activity.v1.MessageActionConfirmService.ListConversationActionConfirms:input_type -> hyapp.activity.v1.ListConversationActionConfirmsRequest - 30, // 255: hyapp.activity.v1.ActivityCronService.ProcessMessageFanoutBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 30, // 256: hyapp.activity.v1.ActivityCronService.ProcessLevelRewardBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 30, // 257: hyapp.activity.v1.ActivityCronService.ProcessAchievementRewardBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 30, // 258: hyapp.activity.v1.ActivityCronService.ProcessRoomTurnoverRewardSettlementBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 30, // 259: hyapp.activity.v1.ActivityCronService.ProcessWeeklyStarSettlementBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 30, // 260: hyapp.activity.v1.ActivityCronService.ProcessCPWeeklyRankSettlementBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 30, // 261: hyapp.activity.v1.ActivityCronService.ProcessAgencyOpeningSettlementBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 34, // 262: hyapp.activity.v1.TaskService.ListUserTasks:input_type -> hyapp.activity.v1.ListUserTasksRequest - 36, // 263: hyapp.activity.v1.TaskService.ClaimTaskReward:input_type -> hyapp.activity.v1.ClaimTaskRewardRequest - 38, // 264: hyapp.activity.v1.TaskService.ConsumeTaskEvent:input_type -> hyapp.activity.v1.ConsumeTaskEventRequest - 156, // 265: hyapp.activity.v1.GrowthLevelService.GetMyLevelOverview:input_type -> hyapp.activity.v1.GetMyLevelOverviewRequest - 158, // 266: hyapp.activity.v1.GrowthLevelService.GetLevelTrack:input_type -> hyapp.activity.v1.GetLevelTrackRequest - 162, // 267: hyapp.activity.v1.GrowthLevelService.BatchGetUserLevelDisplayProfiles:input_type -> hyapp.activity.v1.BatchGetUserLevelDisplayProfilesRequest - 165, // 268: hyapp.activity.v1.GrowthLevelService.ListLevelRewards:input_type -> hyapp.activity.v1.ListLevelRewardsRequest - 167, // 269: hyapp.activity.v1.GrowthLevelService.ConsumeLevelEvent:input_type -> hyapp.activity.v1.ConsumeLevelEventRequest - 169, // 270: hyapp.activity.v1.GrowthLevelService.SetUserLevel:input_type -> hyapp.activity.v1.SetUserLevelRequest - 172, // 271: hyapp.activity.v1.GrowthLevelService.IssueRegistrationLevelBadges:input_type -> hyapp.activity.v1.IssueRegistrationLevelBadgesRequest - 185, // 272: hyapp.activity.v1.AchievementService.ListAchievements:input_type -> hyapp.activity.v1.ListAchievementsRequest - 187, // 273: hyapp.activity.v1.AchievementService.ConsumeAchievementEvent:input_type -> hyapp.activity.v1.ConsumeAchievementEventRequest - 190, // 274: hyapp.activity.v1.AchievementService.ListMyBadges:input_type -> hyapp.activity.v1.ListMyBadgesRequest - 192, // 275: hyapp.activity.v1.AchievementService.SetBadgeDisplay:input_type -> hyapp.activity.v1.SetBadgeDisplayRequest - 203, // 276: hyapp.activity.v1.WheelService.ExecuteWheelDraw:input_type -> hyapp.activity.v1.ExecuteWheelDrawRequest - 128, // 277: hyapp.activity.v1.RoomTurnoverRewardService.GetRoomTurnoverRewardStatus:input_type -> hyapp.activity.v1.GetRoomTurnoverRewardStatusRequest - 231, // 278: hyapp.activity.v1.WeeklyStarService.GetWeeklyStarCurrent:input_type -> hyapp.activity.v1.GetWeeklyStarCurrentRequest - 227, // 279: hyapp.activity.v1.WeeklyStarService.ListWeeklyStarLeaderboard:input_type -> hyapp.activity.v1.ListWeeklyStarLeaderboardRequest - 233, // 280: hyapp.activity.v1.WeeklyStarService.ListWeeklyStarHistory:input_type -> hyapp.activity.v1.ListWeeklyStarHistoryRequest - 241, // 281: hyapp.activity.v1.CPWeeklyRankService.GetCPWeeklyRankStatus:input_type -> hyapp.activity.v1.GetCPWeeklyRankStatusRequest - 265, // 282: hyapp.activity.v1.AgencyOpeningService.GetAgencyOpeningStatus:input_type -> hyapp.activity.v1.GetAgencyOpeningStatusRequest - 267, // 283: hyapp.activity.v1.AgencyOpeningService.ApplyAgencyOpening:input_type -> hyapp.activity.v1.ApplyAgencyOpeningRequest - 261, // 284: hyapp.activity.v1.AgencyOpeningService.ListAgencyOpeningLeaderboard:input_type -> hyapp.activity.v1.ListAgencyOpeningApplicationsRequest - 41, // 285: hyapp.activity.v1.BroadcastService.EnsureBroadcastGroups:input_type -> hyapp.activity.v1.EnsureBroadcastGroupsRequest - 43, // 286: hyapp.activity.v1.BroadcastService.PublishRegionBroadcast:input_type -> hyapp.activity.v1.PublishRegionBroadcastRequest - 44, // 287: hyapp.activity.v1.BroadcastService.PublishGlobalBroadcast:input_type -> hyapp.activity.v1.PublishGlobalBroadcastRequest - 46, // 288: hyapp.activity.v1.BroadcastService.RemoveRegionBroadcastMember:input_type -> hyapp.activity.v1.RemoveRegionBroadcastMemberRequest - 30, // 289: hyapp.activity.v1.BroadcastService.ProcessBroadcastOutboxBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 49, // 290: hyapp.activity.v1.RoomEventConsumerService.ConsumeRoomEvent:input_type -> hyapp.activity.v1.ConsumeRoomEventRequest - 52, // 291: hyapp.activity.v1.AdminTaskService.ListTaskDefinitions:input_type -> hyapp.activity.v1.ListTaskDefinitionsRequest - 54, // 292: hyapp.activity.v1.AdminTaskService.UpsertTaskDefinition:input_type -> hyapp.activity.v1.UpsertTaskDefinitionRequest - 56, // 293: hyapp.activity.v1.AdminTaskService.SetTaskDefinitionStatus:input_type -> hyapp.activity.v1.SetTaskDefinitionStatusRequest - 58, // 294: hyapp.activity.v1.AdminTaskService.PublishTaskRewardPolicy:input_type -> hyapp.activity.v1.PublishTaskRewardPolicyRequest - 63, // 295: hyapp.activity.v1.RegistrationRewardService.GetRegistrationRewardEligibility:input_type -> hyapp.activity.v1.GetRegistrationRewardEligibilityRequest - 65, // 296: hyapp.activity.v1.RegistrationRewardService.IssueRegistrationReward:input_type -> hyapp.activity.v1.IssueRegistrationRewardRequest - 67, // 297: hyapp.activity.v1.AdminRegistrationRewardService.GetRegistrationRewardConfig:input_type -> hyapp.activity.v1.GetRegistrationRewardConfigRequest - 69, // 298: hyapp.activity.v1.AdminRegistrationRewardService.UpdateRegistrationRewardConfig:input_type -> hyapp.activity.v1.UpdateRegistrationRewardConfigRequest - 71, // 299: hyapp.activity.v1.AdminRegistrationRewardService.ListRegistrationRewardClaims:input_type -> hyapp.activity.v1.ListRegistrationRewardClaimsRequest - 77, // 300: hyapp.activity.v1.FirstRechargeRewardService.GetFirstRechargeRewardStatus:input_type -> hyapp.activity.v1.GetFirstRechargeRewardStatusRequest - 79, // 301: hyapp.activity.v1.FirstRechargeRewardService.ConsumeFirstRechargeReward:input_type -> hyapp.activity.v1.ConsumeFirstRechargeRewardRequest - 81, // 302: hyapp.activity.v1.AdminFirstRechargeRewardService.GetFirstRechargeRewardConfig:input_type -> hyapp.activity.v1.GetFirstRechargeRewardConfigRequest - 83, // 303: hyapp.activity.v1.AdminFirstRechargeRewardService.UpdateFirstRechargeRewardConfig:input_type -> hyapp.activity.v1.UpdateFirstRechargeRewardConfigRequest - 85, // 304: hyapp.activity.v1.AdminFirstRechargeRewardService.ListFirstRechargeRewardClaims:input_type -> hyapp.activity.v1.ListFirstRechargeRewardClaimsRequest - 92, // 305: hyapp.activity.v1.CumulativeRechargeRewardService.GetCumulativeRechargeRewardStatus:input_type -> hyapp.activity.v1.GetCumulativeRechargeRewardStatusRequest - 94, // 306: hyapp.activity.v1.CumulativeRechargeRewardService.ConsumeCumulativeRechargeReward:input_type -> hyapp.activity.v1.ConsumeCumulativeRechargeRewardRequest - 107, // 307: hyapp.activity.v1.InviteActivityRewardService.GetInviteActivityRewardStatus:input_type -> hyapp.activity.v1.GetInviteActivityRewardStatusRequest - 109, // 308: hyapp.activity.v1.InviteActivityRewardService.ClaimInviteActivityReward:input_type -> hyapp.activity.v1.ClaimInviteActivityRewardRequest - 112, // 309: hyapp.activity.v1.InviteActivityRewardService.ListInviteActivityLeaderboard:input_type -> hyapp.activity.v1.ListInviteActivityLeaderboardRequest - 96, // 310: hyapp.activity.v1.AdminCumulativeRechargeRewardService.GetCumulativeRechargeRewardConfig:input_type -> hyapp.activity.v1.GetCumulativeRechargeRewardConfigRequest - 98, // 311: hyapp.activity.v1.AdminCumulativeRechargeRewardService.UpdateCumulativeRechargeRewardConfig:input_type -> hyapp.activity.v1.UpdateCumulativeRechargeRewardConfigRequest - 100, // 312: hyapp.activity.v1.AdminCumulativeRechargeRewardService.ListCumulativeRechargeRewardGrants:input_type -> hyapp.activity.v1.ListCumulativeRechargeRewardGrantsRequest - 114, // 313: hyapp.activity.v1.AdminInviteActivityRewardService.GetInviteActivityRewardConfig:input_type -> hyapp.activity.v1.GetInviteActivityRewardConfigRequest - 116, // 314: hyapp.activity.v1.AdminInviteActivityRewardService.UpdateInviteActivityRewardConfig:input_type -> hyapp.activity.v1.UpdateInviteActivityRewardConfigRequest - 118, // 315: hyapp.activity.v1.AdminInviteActivityRewardService.ListInviteActivityRewardClaims:input_type -> hyapp.activity.v1.ListInviteActivityRewardClaimsRequest - 122, // 316: hyapp.activity.v1.AdminInviteActivityRewardService.ListInviteActivityRewardSummaries:input_type -> hyapp.activity.v1.ListInviteActivityRewardSummariesRequest - 130, // 317: hyapp.activity.v1.AdminRoomTurnoverRewardService.GetRoomTurnoverRewardConfig:input_type -> hyapp.activity.v1.GetRoomTurnoverRewardConfigRequest - 132, // 318: hyapp.activity.v1.AdminRoomTurnoverRewardService.UpdateRoomTurnoverRewardConfig:input_type -> hyapp.activity.v1.UpdateRoomTurnoverRewardConfigRequest - 134, // 319: hyapp.activity.v1.AdminRoomTurnoverRewardService.ListRoomTurnoverRewardSettlements:input_type -> hyapp.activity.v1.ListRoomTurnoverRewardSettlementsRequest - 136, // 320: hyapp.activity.v1.AdminRoomTurnoverRewardService.RetryRoomTurnoverRewardSettlement:input_type -> hyapp.activity.v1.RetryRoomTurnoverRewardSettlementRequest - 219, // 321: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarCycles:input_type -> hyapp.activity.v1.ListWeeklyStarCyclesRequest - 223, // 322: hyapp.activity.v1.AdminWeeklyStarService.CreateWeeklyStarCycle:input_type -> hyapp.activity.v1.UpsertWeeklyStarCycleRequest - 221, // 323: hyapp.activity.v1.AdminWeeklyStarService.GetWeeklyStarCycle:input_type -> hyapp.activity.v1.GetWeeklyStarCycleRequest - 223, // 324: hyapp.activity.v1.AdminWeeklyStarService.UpdateWeeklyStarCycle:input_type -> hyapp.activity.v1.UpsertWeeklyStarCycleRequest - 225, // 325: hyapp.activity.v1.AdminWeeklyStarService.SetWeeklyStarCycleStatus:input_type -> hyapp.activity.v1.SetWeeklyStarCycleStatusRequest - 227, // 326: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarLeaderboard:input_type -> hyapp.activity.v1.ListWeeklyStarLeaderboardRequest - 229, // 327: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarSettlements:input_type -> hyapp.activity.v1.ListWeeklyStarSettlementsRequest - 243, // 328: hyapp.activity.v1.AdminCPWeeklyRankService.GetCPWeeklyRankConfig:input_type -> hyapp.activity.v1.GetCPWeeklyRankConfigRequest - 245, // 329: hyapp.activity.v1.AdminCPWeeklyRankService.UpdateCPWeeklyRankConfig:input_type -> hyapp.activity.v1.UpdateCPWeeklyRankConfigRequest - 247, // 330: hyapp.activity.v1.AdminCPWeeklyRankService.ListCPWeeklyRankSettlements:input_type -> hyapp.activity.v1.ListCPWeeklyRankSettlementsRequest - 253, // 331: hyapp.activity.v1.AdminAgencyOpeningService.ListAgencyOpeningCycles:input_type -> hyapp.activity.v1.ListAgencyOpeningCyclesRequest - 257, // 332: hyapp.activity.v1.AdminAgencyOpeningService.CreateAgencyOpeningCycle:input_type -> hyapp.activity.v1.UpsertAgencyOpeningCycleRequest - 255, // 333: hyapp.activity.v1.AdminAgencyOpeningService.GetAgencyOpeningCycle:input_type -> hyapp.activity.v1.GetAgencyOpeningCycleRequest - 257, // 334: hyapp.activity.v1.AdminAgencyOpeningService.UpdateAgencyOpeningCycle:input_type -> hyapp.activity.v1.UpsertAgencyOpeningCycleRequest - 259, // 335: hyapp.activity.v1.AdminAgencyOpeningService.SetAgencyOpeningCycleStatus:input_type -> hyapp.activity.v1.SetAgencyOpeningCycleStatusRequest - 261, // 336: hyapp.activity.v1.AdminAgencyOpeningService.ListAgencyOpeningApplications:input_type -> hyapp.activity.v1.ListAgencyOpeningApplicationsRequest - 263, // 337: hyapp.activity.v1.AdminAgencyOpeningService.ReviewAgencyOpeningApplication:input_type -> hyapp.activity.v1.ReviewAgencyOpeningApplicationRequest - 141, // 338: hyapp.activity.v1.SevenDayCheckInService.GetSevenDayCheckInStatus:input_type -> hyapp.activity.v1.GetSevenDayCheckInStatusRequest - 143, // 339: hyapp.activity.v1.SevenDayCheckInService.SignSevenDayCheckIn:input_type -> hyapp.activity.v1.SignSevenDayCheckInRequest - 145, // 340: hyapp.activity.v1.AdminSevenDayCheckInService.GetSevenDayCheckInConfig:input_type -> hyapp.activity.v1.GetSevenDayCheckInConfigRequest - 147, // 341: hyapp.activity.v1.AdminSevenDayCheckInService.UpdateSevenDayCheckInConfig:input_type -> hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest - 150, // 342: hyapp.activity.v1.AdminSevenDayCheckInService.ListSevenDayCheckInClaims:input_type -> hyapp.activity.v1.ListSevenDayCheckInClaimsRequest - 180, // 343: hyapp.activity.v1.AdminGrowthLevelService.ListLevelConfig:input_type -> hyapp.activity.v1.ListLevelConfigRequest - 174, // 344: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTrack:input_type -> hyapp.activity.v1.UpsertLevelTrackRequest - 176, // 345: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelRule:input_type -> hyapp.activity.v1.UpsertLevelRuleRequest - 178, // 346: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTier:input_type -> hyapp.activity.v1.UpsertLevelTierRequest - 185, // 347: hyapp.activity.v1.AdminAchievementService.ListAchievementDefinitions:input_type -> hyapp.activity.v1.ListAchievementsRequest - 194, // 348: hyapp.activity.v1.AdminAchievementService.UpsertAchievementDefinition:input_type -> hyapp.activity.v1.UpsertAchievementDefinitionRequest - 196, // 349: hyapp.activity.v1.AdminAchievementService.DeleteAchievementDefinition:input_type -> hyapp.activity.v1.DeleteAchievementDefinitionRequest - 205, // 350: hyapp.activity.v1.AdminWheelService.GetWheelConfig:input_type -> hyapp.activity.v1.GetWheelConfigRequest - 207, // 351: hyapp.activity.v1.AdminWheelService.UpsertWheelConfig:input_type -> hyapp.activity.v1.UpsertWheelConfigRequest - 209, // 352: hyapp.activity.v1.AdminWheelService.ListWheelDraws:input_type -> hyapp.activity.v1.ListWheelDrawsRequest - 212, // 353: hyapp.activity.v1.AdminWheelService.GetWheelDrawSummary:input_type -> hyapp.activity.v1.GetWheelDrawSummaryRequest - 2, // 354: hyapp.activity.v1.ActivityService.PingActivity:output_type -> hyapp.activity.v1.PingActivityResponse - 4, // 355: hyapp.activity.v1.ActivityService.GetActivityStatus:output_type -> hyapp.activity.v1.GetActivityStatusResponse - 7, // 356: hyapp.activity.v1.MessageInboxService.ListMessageTabs:output_type -> hyapp.activity.v1.ListMessageTabsResponse - 10, // 357: hyapp.activity.v1.MessageInboxService.ListInboxMessages:output_type -> hyapp.activity.v1.ListInboxMessagesResponse - 12, // 358: hyapp.activity.v1.MessageInboxService.MarkInboxMessageRead:output_type -> hyapp.activity.v1.MarkInboxMessageReadResponse - 14, // 359: hyapp.activity.v1.MessageInboxService.MarkInboxSectionRead:output_type -> hyapp.activity.v1.MarkInboxSectionReadResponse - 16, // 360: hyapp.activity.v1.MessageInboxService.DeleteInboxMessage:output_type -> hyapp.activity.v1.DeleteInboxMessageResponse - 18, // 361: hyapp.activity.v1.MessageInboxService.CreateInboxMessage:output_type -> hyapp.activity.v1.CreateInboxMessageResponse - 20, // 362: hyapp.activity.v1.MessageInboxService.CreateFanoutJob:output_type -> hyapp.activity.v1.CreateFanoutJobResponse - 23, // 363: hyapp.activity.v1.MessageActionConfirmService.AcceptActionConfirm:output_type -> hyapp.activity.v1.AcceptActionConfirmResponse - 25, // 364: hyapp.activity.v1.MessageActionConfirmService.RejectActionConfirm:output_type -> hyapp.activity.v1.RejectActionConfirmResponse - 27, // 365: hyapp.activity.v1.MessageActionConfirmService.BatchGetActionConfirmStatus:output_type -> hyapp.activity.v1.BatchGetActionConfirmStatusResponse - 29, // 366: hyapp.activity.v1.MessageActionConfirmService.ListConversationActionConfirms:output_type -> hyapp.activity.v1.ListConversationActionConfirmsResponse - 31, // 367: hyapp.activity.v1.ActivityCronService.ProcessMessageFanoutBatch:output_type -> hyapp.activity.v1.CronBatchResponse - 31, // 368: hyapp.activity.v1.ActivityCronService.ProcessLevelRewardBatch:output_type -> hyapp.activity.v1.CronBatchResponse - 31, // 369: hyapp.activity.v1.ActivityCronService.ProcessAchievementRewardBatch:output_type -> hyapp.activity.v1.CronBatchResponse - 31, // 370: hyapp.activity.v1.ActivityCronService.ProcessRoomTurnoverRewardSettlementBatch:output_type -> hyapp.activity.v1.CronBatchResponse - 31, // 371: hyapp.activity.v1.ActivityCronService.ProcessWeeklyStarSettlementBatch:output_type -> hyapp.activity.v1.CronBatchResponse - 31, // 372: hyapp.activity.v1.ActivityCronService.ProcessCPWeeklyRankSettlementBatch:output_type -> hyapp.activity.v1.CronBatchResponse - 31, // 373: hyapp.activity.v1.ActivityCronService.ProcessAgencyOpeningSettlementBatch:output_type -> hyapp.activity.v1.CronBatchResponse - 35, // 374: hyapp.activity.v1.TaskService.ListUserTasks:output_type -> hyapp.activity.v1.ListUserTasksResponse - 37, // 375: hyapp.activity.v1.TaskService.ClaimTaskReward:output_type -> hyapp.activity.v1.ClaimTaskRewardResponse - 39, // 376: hyapp.activity.v1.TaskService.ConsumeTaskEvent:output_type -> hyapp.activity.v1.ConsumeTaskEventResponse - 157, // 377: hyapp.activity.v1.GrowthLevelService.GetMyLevelOverview:output_type -> hyapp.activity.v1.GetMyLevelOverviewResponse - 159, // 378: hyapp.activity.v1.GrowthLevelService.GetLevelTrack:output_type -> hyapp.activity.v1.GetLevelTrackResponse - 163, // 379: hyapp.activity.v1.GrowthLevelService.BatchGetUserLevelDisplayProfiles:output_type -> hyapp.activity.v1.BatchGetUserLevelDisplayProfilesResponse - 166, // 380: hyapp.activity.v1.GrowthLevelService.ListLevelRewards:output_type -> hyapp.activity.v1.ListLevelRewardsResponse - 168, // 381: hyapp.activity.v1.GrowthLevelService.ConsumeLevelEvent:output_type -> hyapp.activity.v1.ConsumeLevelEventResponse - 170, // 382: hyapp.activity.v1.GrowthLevelService.SetUserLevel:output_type -> hyapp.activity.v1.SetUserLevelResponse - 173, // 383: hyapp.activity.v1.GrowthLevelService.IssueRegistrationLevelBadges:output_type -> hyapp.activity.v1.IssueRegistrationLevelBadgesResponse - 186, // 384: hyapp.activity.v1.AchievementService.ListAchievements:output_type -> hyapp.activity.v1.ListAchievementsResponse - 188, // 385: hyapp.activity.v1.AchievementService.ConsumeAchievementEvent:output_type -> hyapp.activity.v1.ConsumeAchievementEventResponse - 191, // 386: hyapp.activity.v1.AchievementService.ListMyBadges:output_type -> hyapp.activity.v1.ListMyBadgesResponse - 193, // 387: hyapp.activity.v1.AchievementService.SetBadgeDisplay:output_type -> hyapp.activity.v1.SetBadgeDisplayResponse - 204, // 388: hyapp.activity.v1.WheelService.ExecuteWheelDraw:output_type -> hyapp.activity.v1.ExecuteWheelDrawResponse - 129, // 389: hyapp.activity.v1.RoomTurnoverRewardService.GetRoomTurnoverRewardStatus:output_type -> hyapp.activity.v1.GetRoomTurnoverRewardStatusResponse - 232, // 390: hyapp.activity.v1.WeeklyStarService.GetWeeklyStarCurrent:output_type -> hyapp.activity.v1.GetWeeklyStarCurrentResponse - 228, // 391: hyapp.activity.v1.WeeklyStarService.ListWeeklyStarLeaderboard:output_type -> hyapp.activity.v1.ListWeeklyStarLeaderboardResponse - 235, // 392: hyapp.activity.v1.WeeklyStarService.ListWeeklyStarHistory:output_type -> hyapp.activity.v1.ListWeeklyStarHistoryResponse - 242, // 393: hyapp.activity.v1.CPWeeklyRankService.GetCPWeeklyRankStatus:output_type -> hyapp.activity.v1.GetCPWeeklyRankStatusResponse - 266, // 394: hyapp.activity.v1.AgencyOpeningService.GetAgencyOpeningStatus:output_type -> hyapp.activity.v1.GetAgencyOpeningStatusResponse - 268, // 395: hyapp.activity.v1.AgencyOpeningService.ApplyAgencyOpening:output_type -> hyapp.activity.v1.ApplyAgencyOpeningResponse - 262, // 396: hyapp.activity.v1.AgencyOpeningService.ListAgencyOpeningLeaderboard:output_type -> hyapp.activity.v1.ListAgencyOpeningApplicationsResponse - 42, // 397: hyapp.activity.v1.BroadcastService.EnsureBroadcastGroups:output_type -> hyapp.activity.v1.EnsureBroadcastGroupsResponse - 45, // 398: hyapp.activity.v1.BroadcastService.PublishRegionBroadcast:output_type -> hyapp.activity.v1.PublishBroadcastResponse - 45, // 399: hyapp.activity.v1.BroadcastService.PublishGlobalBroadcast:output_type -> hyapp.activity.v1.PublishBroadcastResponse - 47, // 400: hyapp.activity.v1.BroadcastService.RemoveRegionBroadcastMember:output_type -> hyapp.activity.v1.RemoveRegionBroadcastMemberResponse - 48, // 401: hyapp.activity.v1.BroadcastService.ProcessBroadcastOutboxBatch:output_type -> hyapp.activity.v1.ProcessBroadcastOutboxBatchResponse - 50, // 402: hyapp.activity.v1.RoomEventConsumerService.ConsumeRoomEvent:output_type -> hyapp.activity.v1.ConsumeRoomEventResponse - 53, // 403: hyapp.activity.v1.AdminTaskService.ListTaskDefinitions:output_type -> hyapp.activity.v1.ListTaskDefinitionsResponse - 55, // 404: hyapp.activity.v1.AdminTaskService.UpsertTaskDefinition:output_type -> hyapp.activity.v1.UpsertTaskDefinitionResponse - 57, // 405: hyapp.activity.v1.AdminTaskService.SetTaskDefinitionStatus:output_type -> hyapp.activity.v1.SetTaskDefinitionStatusResponse - 59, // 406: hyapp.activity.v1.AdminTaskService.PublishTaskRewardPolicy:output_type -> hyapp.activity.v1.PublishTaskRewardPolicyResponse - 64, // 407: hyapp.activity.v1.RegistrationRewardService.GetRegistrationRewardEligibility:output_type -> hyapp.activity.v1.GetRegistrationRewardEligibilityResponse - 66, // 408: hyapp.activity.v1.RegistrationRewardService.IssueRegistrationReward:output_type -> hyapp.activity.v1.IssueRegistrationRewardResponse - 68, // 409: hyapp.activity.v1.AdminRegistrationRewardService.GetRegistrationRewardConfig:output_type -> hyapp.activity.v1.GetRegistrationRewardConfigResponse - 70, // 410: hyapp.activity.v1.AdminRegistrationRewardService.UpdateRegistrationRewardConfig:output_type -> hyapp.activity.v1.UpdateRegistrationRewardConfigResponse - 72, // 411: hyapp.activity.v1.AdminRegistrationRewardService.ListRegistrationRewardClaims:output_type -> hyapp.activity.v1.ListRegistrationRewardClaimsResponse - 78, // 412: hyapp.activity.v1.FirstRechargeRewardService.GetFirstRechargeRewardStatus:output_type -> hyapp.activity.v1.GetFirstRechargeRewardStatusResponse - 80, // 413: hyapp.activity.v1.FirstRechargeRewardService.ConsumeFirstRechargeReward:output_type -> hyapp.activity.v1.ConsumeFirstRechargeRewardResponse - 82, // 414: hyapp.activity.v1.AdminFirstRechargeRewardService.GetFirstRechargeRewardConfig:output_type -> hyapp.activity.v1.GetFirstRechargeRewardConfigResponse - 84, // 415: hyapp.activity.v1.AdminFirstRechargeRewardService.UpdateFirstRechargeRewardConfig:output_type -> hyapp.activity.v1.UpdateFirstRechargeRewardConfigResponse - 86, // 416: hyapp.activity.v1.AdminFirstRechargeRewardService.ListFirstRechargeRewardClaims:output_type -> hyapp.activity.v1.ListFirstRechargeRewardClaimsResponse - 93, // 417: hyapp.activity.v1.CumulativeRechargeRewardService.GetCumulativeRechargeRewardStatus:output_type -> hyapp.activity.v1.GetCumulativeRechargeRewardStatusResponse - 95, // 418: hyapp.activity.v1.CumulativeRechargeRewardService.ConsumeCumulativeRechargeReward:output_type -> hyapp.activity.v1.ConsumeCumulativeRechargeRewardResponse - 108, // 419: hyapp.activity.v1.InviteActivityRewardService.GetInviteActivityRewardStatus:output_type -> hyapp.activity.v1.GetInviteActivityRewardStatusResponse - 110, // 420: hyapp.activity.v1.InviteActivityRewardService.ClaimInviteActivityReward:output_type -> hyapp.activity.v1.ClaimInviteActivityRewardResponse - 113, // 421: hyapp.activity.v1.InviteActivityRewardService.ListInviteActivityLeaderboard:output_type -> hyapp.activity.v1.ListInviteActivityLeaderboardResponse - 97, // 422: hyapp.activity.v1.AdminCumulativeRechargeRewardService.GetCumulativeRechargeRewardConfig:output_type -> hyapp.activity.v1.GetCumulativeRechargeRewardConfigResponse - 99, // 423: hyapp.activity.v1.AdminCumulativeRechargeRewardService.UpdateCumulativeRechargeRewardConfig:output_type -> hyapp.activity.v1.UpdateCumulativeRechargeRewardConfigResponse - 101, // 424: hyapp.activity.v1.AdminCumulativeRechargeRewardService.ListCumulativeRechargeRewardGrants:output_type -> hyapp.activity.v1.ListCumulativeRechargeRewardGrantsResponse - 115, // 425: hyapp.activity.v1.AdminInviteActivityRewardService.GetInviteActivityRewardConfig:output_type -> hyapp.activity.v1.GetInviteActivityRewardConfigResponse - 117, // 426: hyapp.activity.v1.AdminInviteActivityRewardService.UpdateInviteActivityRewardConfig:output_type -> hyapp.activity.v1.UpdateInviteActivityRewardConfigResponse - 119, // 427: hyapp.activity.v1.AdminInviteActivityRewardService.ListInviteActivityRewardClaims:output_type -> hyapp.activity.v1.ListInviteActivityRewardClaimsResponse - 123, // 428: hyapp.activity.v1.AdminInviteActivityRewardService.ListInviteActivityRewardSummaries:output_type -> hyapp.activity.v1.ListInviteActivityRewardSummariesResponse - 131, // 429: hyapp.activity.v1.AdminRoomTurnoverRewardService.GetRoomTurnoverRewardConfig:output_type -> hyapp.activity.v1.GetRoomTurnoverRewardConfigResponse - 133, // 430: hyapp.activity.v1.AdminRoomTurnoverRewardService.UpdateRoomTurnoverRewardConfig:output_type -> hyapp.activity.v1.UpdateRoomTurnoverRewardConfigResponse - 135, // 431: hyapp.activity.v1.AdminRoomTurnoverRewardService.ListRoomTurnoverRewardSettlements:output_type -> hyapp.activity.v1.ListRoomTurnoverRewardSettlementsResponse - 137, // 432: hyapp.activity.v1.AdminRoomTurnoverRewardService.RetryRoomTurnoverRewardSettlement:output_type -> hyapp.activity.v1.RetryRoomTurnoverRewardSettlementResponse - 220, // 433: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarCycles:output_type -> hyapp.activity.v1.ListWeeklyStarCyclesResponse - 224, // 434: hyapp.activity.v1.AdminWeeklyStarService.CreateWeeklyStarCycle:output_type -> hyapp.activity.v1.UpsertWeeklyStarCycleResponse - 222, // 435: hyapp.activity.v1.AdminWeeklyStarService.GetWeeklyStarCycle:output_type -> hyapp.activity.v1.GetWeeklyStarCycleResponse - 224, // 436: hyapp.activity.v1.AdminWeeklyStarService.UpdateWeeklyStarCycle:output_type -> hyapp.activity.v1.UpsertWeeklyStarCycleResponse - 226, // 437: hyapp.activity.v1.AdminWeeklyStarService.SetWeeklyStarCycleStatus:output_type -> hyapp.activity.v1.SetWeeklyStarCycleStatusResponse - 228, // 438: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarLeaderboard:output_type -> hyapp.activity.v1.ListWeeklyStarLeaderboardResponse - 230, // 439: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarSettlements:output_type -> hyapp.activity.v1.ListWeeklyStarSettlementsResponse - 244, // 440: hyapp.activity.v1.AdminCPWeeklyRankService.GetCPWeeklyRankConfig:output_type -> hyapp.activity.v1.GetCPWeeklyRankConfigResponse - 246, // 441: hyapp.activity.v1.AdminCPWeeklyRankService.UpdateCPWeeklyRankConfig:output_type -> hyapp.activity.v1.UpdateCPWeeklyRankConfigResponse - 248, // 442: hyapp.activity.v1.AdminCPWeeklyRankService.ListCPWeeklyRankSettlements:output_type -> hyapp.activity.v1.ListCPWeeklyRankSettlementsResponse - 254, // 443: hyapp.activity.v1.AdminAgencyOpeningService.ListAgencyOpeningCycles:output_type -> hyapp.activity.v1.ListAgencyOpeningCyclesResponse - 258, // 444: hyapp.activity.v1.AdminAgencyOpeningService.CreateAgencyOpeningCycle:output_type -> hyapp.activity.v1.UpsertAgencyOpeningCycleResponse - 256, // 445: hyapp.activity.v1.AdminAgencyOpeningService.GetAgencyOpeningCycle:output_type -> hyapp.activity.v1.GetAgencyOpeningCycleResponse - 258, // 446: hyapp.activity.v1.AdminAgencyOpeningService.UpdateAgencyOpeningCycle:output_type -> hyapp.activity.v1.UpsertAgencyOpeningCycleResponse - 260, // 447: hyapp.activity.v1.AdminAgencyOpeningService.SetAgencyOpeningCycleStatus:output_type -> hyapp.activity.v1.SetAgencyOpeningCycleStatusResponse - 262, // 448: hyapp.activity.v1.AdminAgencyOpeningService.ListAgencyOpeningApplications:output_type -> hyapp.activity.v1.ListAgencyOpeningApplicationsResponse - 264, // 449: hyapp.activity.v1.AdminAgencyOpeningService.ReviewAgencyOpeningApplication:output_type -> hyapp.activity.v1.ReviewAgencyOpeningApplicationResponse - 142, // 450: hyapp.activity.v1.SevenDayCheckInService.GetSevenDayCheckInStatus:output_type -> hyapp.activity.v1.GetSevenDayCheckInStatusResponse - 144, // 451: hyapp.activity.v1.SevenDayCheckInService.SignSevenDayCheckIn:output_type -> hyapp.activity.v1.SignSevenDayCheckInResponse - 146, // 452: hyapp.activity.v1.AdminSevenDayCheckInService.GetSevenDayCheckInConfig:output_type -> hyapp.activity.v1.GetSevenDayCheckInConfigResponse - 148, // 453: hyapp.activity.v1.AdminSevenDayCheckInService.UpdateSevenDayCheckInConfig:output_type -> hyapp.activity.v1.UpdateSevenDayCheckInConfigResponse - 151, // 454: hyapp.activity.v1.AdminSevenDayCheckInService.ListSevenDayCheckInClaims:output_type -> hyapp.activity.v1.ListSevenDayCheckInClaimsResponse - 181, // 455: hyapp.activity.v1.AdminGrowthLevelService.ListLevelConfig:output_type -> hyapp.activity.v1.ListLevelConfigResponse - 175, // 456: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTrack:output_type -> hyapp.activity.v1.UpsertLevelTrackResponse - 177, // 457: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelRule:output_type -> hyapp.activity.v1.UpsertLevelRuleResponse - 179, // 458: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTier:output_type -> hyapp.activity.v1.UpsertLevelTierResponse - 186, // 459: hyapp.activity.v1.AdminAchievementService.ListAchievementDefinitions:output_type -> hyapp.activity.v1.ListAchievementsResponse - 195, // 460: hyapp.activity.v1.AdminAchievementService.UpsertAchievementDefinition:output_type -> hyapp.activity.v1.UpsertAchievementDefinitionResponse - 197, // 461: hyapp.activity.v1.AdminAchievementService.DeleteAchievementDefinition:output_type -> hyapp.activity.v1.DeleteAchievementDefinitionResponse - 206, // 462: hyapp.activity.v1.AdminWheelService.GetWheelConfig:output_type -> hyapp.activity.v1.GetWheelConfigResponse - 208, // 463: hyapp.activity.v1.AdminWheelService.UpsertWheelConfig:output_type -> hyapp.activity.v1.UpsertWheelConfigResponse - 210, // 464: hyapp.activity.v1.AdminWheelService.ListWheelDraws:output_type -> hyapp.activity.v1.ListWheelDrawsResponse - 213, // 465: hyapp.activity.v1.AdminWheelService.GetWheelDrawSummary:output_type -> hyapp.activity.v1.GetWheelDrawSummaryResponse - 354, // [354:466] is the sub-list for method output_type - 242, // [242:354] is the sub-list for method input_type - 242, // [242:242] is the sub-list for extension type_name - 242, // [242:242] is the sub-list for extension extendee - 0, // [0:242] is the sub-list for field type_name + 171, // 141: hyapp.activity.v1.AdminUserLevelProfile.tracks:type_name -> hyapp.activity.v1.AdminLevelTrackProfile + 0, // 142: hyapp.activity.v1.BatchGetUserLevelAdminProfilesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 172, // 143: hyapp.activity.v1.BatchGetUserLevelAdminProfilesResponse.profiles:type_name -> hyapp.activity.v1.AdminUserLevelProfile + 0, // 144: hyapp.activity.v1.AdjustTemporaryUserLevelsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 175, // 145: hyapp.activity.v1.AdjustTemporaryUserLevelsRequest.adjustments:type_name -> hyapp.activity.v1.TemporaryLevelAdjustment + 172, // 146: hyapp.activity.v1.AdjustTemporaryUserLevelsResponse.profile:type_name -> hyapp.activity.v1.AdminUserLevelProfile + 0, // 147: hyapp.activity.v1.IssueRegistrationLevelBadgesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 178, // 148: hyapp.activity.v1.IssueRegistrationLevelBadgesResponse.grants:type_name -> hyapp.activity.v1.RegistrationLevelBadgeGrant + 0, // 149: hyapp.activity.v1.UpsertLevelTrackRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 152, // 150: hyapp.activity.v1.UpsertLevelTrackResponse.track:type_name -> hyapp.activity.v1.LevelTrack + 0, // 151: hyapp.activity.v1.UpsertLevelRuleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 153, // 152: hyapp.activity.v1.UpsertLevelRuleResponse.rule:type_name -> hyapp.activity.v1.LevelRule + 0, // 153: hyapp.activity.v1.UpsertLevelTierRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 154, // 154: hyapp.activity.v1.UpsertLevelTierResponse.tier:type_name -> hyapp.activity.v1.LevelTier + 0, // 155: hyapp.activity.v1.ListLevelConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 152, // 156: hyapp.activity.v1.ListLevelConfigResponse.tracks:type_name -> hyapp.activity.v1.LevelTrack + 153, // 157: hyapp.activity.v1.ListLevelConfigResponse.rules:type_name -> hyapp.activity.v1.LevelRule + 154, // 158: hyapp.activity.v1.ListLevelConfigResponse.tiers:type_name -> hyapp.activity.v1.LevelTier + 189, // 159: hyapp.activity.v1.AchievementDefinition.conditions:type_name -> hyapp.activity.v1.AchievementCondition + 190, // 160: hyapp.activity.v1.UserAchievement.definition:type_name -> hyapp.activity.v1.AchievementDefinition + 0, // 161: hyapp.activity.v1.ListAchievementsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 191, // 162: hyapp.activity.v1.ListAchievementsResponse.achievements:type_name -> hyapp.activity.v1.UserAchievement + 0, // 163: hyapp.activity.v1.ConsumeAchievementEventRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 0, // 164: hyapp.activity.v1.ListMyBadgesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 196, // 165: hyapp.activity.v1.ListMyBadgesResponse.strip_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem + 196, // 166: hyapp.activity.v1.ListMyBadgesResponse.profile_tile_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem + 196, // 167: hyapp.activity.v1.ListMyBadgesResponse.honor_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem + 0, // 168: hyapp.activity.v1.SetBadgeDisplayRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 196, // 169: hyapp.activity.v1.SetBadgeDisplayRequest.items:type_name -> hyapp.activity.v1.BadgeDisplayItem + 198, // 170: hyapp.activity.v1.SetBadgeDisplayResponse.profile:type_name -> hyapp.activity.v1.ListMyBadgesResponse + 0, // 171: hyapp.activity.v1.UpsertAchievementDefinitionRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 189, // 172: hyapp.activity.v1.UpsertAchievementDefinitionRequest.conditions:type_name -> hyapp.activity.v1.AchievementCondition + 190, // 173: hyapp.activity.v1.UpsertAchievementDefinitionResponse.achievement:type_name -> hyapp.activity.v1.AchievementDefinition + 0, // 174: hyapp.activity.v1.DeleteAchievementDefinitionRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 190, // 175: hyapp.activity.v1.DeleteAchievementDefinitionResponse.achievement:type_name -> hyapp.activity.v1.AchievementDefinition + 205, // 176: hyapp.activity.v1.WheelRuleConfig.tiers:type_name -> hyapp.activity.v1.WheelPrizeTier + 0, // 177: hyapp.activity.v1.WheelDrawMeta.meta:type_name -> hyapp.activity.v1.RequestMeta + 209, // 178: hyapp.activity.v1.WheelDrawResult.rewards:type_name -> hyapp.activity.v1.WheelDrawReward + 207, // 179: hyapp.activity.v1.ExecuteWheelDrawRequest.wheel:type_name -> hyapp.activity.v1.WheelDrawMeta + 208, // 180: hyapp.activity.v1.ExecuteWheelDrawResponse.result:type_name -> hyapp.activity.v1.WheelDrawResult + 0, // 181: hyapp.activity.v1.GetWheelConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 206, // 182: hyapp.activity.v1.GetWheelConfigResponse.config:type_name -> hyapp.activity.v1.WheelRuleConfig + 0, // 183: hyapp.activity.v1.UpsertWheelConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 206, // 184: hyapp.activity.v1.UpsertWheelConfigRequest.config:type_name -> hyapp.activity.v1.WheelRuleConfig + 206, // 185: hyapp.activity.v1.UpsertWheelConfigResponse.config:type_name -> hyapp.activity.v1.WheelRuleConfig + 0, // 186: hyapp.activity.v1.ListWheelDrawsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 208, // 187: hyapp.activity.v1.ListWheelDrawsResponse.draws:type_name -> hyapp.activity.v1.WheelDrawResult + 0, // 188: hyapp.activity.v1.GetWheelDrawSummaryRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 218, // 189: hyapp.activity.v1.GetWheelDrawSummaryResponse.summary:type_name -> hyapp.activity.v1.WheelDrawSummary + 221, // 190: hyapp.activity.v1.WeeklyStarCycle.gifts:type_name -> hyapp.activity.v1.WeeklyStarGift + 222, // 191: hyapp.activity.v1.WeeklyStarCycle.rewards:type_name -> hyapp.activity.v1.WeeklyStarReward + 0, // 192: hyapp.activity.v1.ListWeeklyStarCyclesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 223, // 193: hyapp.activity.v1.ListWeeklyStarCyclesResponse.cycles:type_name -> hyapp.activity.v1.WeeklyStarCycle + 0, // 194: hyapp.activity.v1.GetWeeklyStarCycleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 223, // 195: hyapp.activity.v1.GetWeeklyStarCycleResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle + 0, // 196: hyapp.activity.v1.UpsertWeeklyStarCycleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 223, // 197: hyapp.activity.v1.UpsertWeeklyStarCycleRequest.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle + 223, // 198: hyapp.activity.v1.UpsertWeeklyStarCycleResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle + 0, // 199: hyapp.activity.v1.SetWeeklyStarCycleStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 223, // 200: hyapp.activity.v1.SetWeeklyStarCycleStatusResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle + 0, // 201: hyapp.activity.v1.ListWeeklyStarLeaderboardRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 223, // 202: hyapp.activity.v1.ListWeeklyStarLeaderboardResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle + 224, // 203: hyapp.activity.v1.ListWeeklyStarLeaderboardResponse.entries:type_name -> hyapp.activity.v1.WeeklyStarLeaderboardEntry + 0, // 204: hyapp.activity.v1.ListWeeklyStarSettlementsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 225, // 205: hyapp.activity.v1.ListWeeklyStarSettlementsResponse.settlements:type_name -> hyapp.activity.v1.WeeklyStarSettlement + 0, // 206: hyapp.activity.v1.GetWeeklyStarCurrentRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 223, // 207: hyapp.activity.v1.GetWeeklyStarCurrentResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle + 224, // 208: hyapp.activity.v1.GetWeeklyStarCurrentResponse.top_entries:type_name -> hyapp.activity.v1.WeeklyStarLeaderboardEntry + 224, // 209: hyapp.activity.v1.GetWeeklyStarCurrentResponse.my_entry:type_name -> hyapp.activity.v1.WeeklyStarLeaderboardEntry + 0, // 210: hyapp.activity.v1.ListWeeklyStarHistoryRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 223, // 211: hyapp.activity.v1.WeeklyStarHistoryCycle.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle + 224, // 212: hyapp.activity.v1.WeeklyStarHistoryCycle.top_entries:type_name -> hyapp.activity.v1.WeeklyStarLeaderboardEntry + 241, // 213: hyapp.activity.v1.ListWeeklyStarHistoryResponse.cycles:type_name -> hyapp.activity.v1.WeeklyStarHistoryCycle + 243, // 214: hyapp.activity.v1.CPWeeklyRankConfig.rewards:type_name -> hyapp.activity.v1.CPWeeklyRankReward + 245, // 215: hyapp.activity.v1.CPWeeklyRankEntry.user_a:type_name -> hyapp.activity.v1.CPWeeklyRankUser + 245, // 216: hyapp.activity.v1.CPWeeklyRankEntry.user_b:type_name -> hyapp.activity.v1.CPWeeklyRankUser + 0, // 217: hyapp.activity.v1.GetCPWeeklyRankStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 244, // 218: hyapp.activity.v1.GetCPWeeklyRankStatusResponse.config:type_name -> hyapp.activity.v1.CPWeeklyRankConfig + 246, // 219: hyapp.activity.v1.GetCPWeeklyRankStatusResponse.entries:type_name -> hyapp.activity.v1.CPWeeklyRankEntry + 246, // 220: hyapp.activity.v1.GetCPWeeklyRankStatusResponse.previous_entries:type_name -> hyapp.activity.v1.CPWeeklyRankEntry + 0, // 221: hyapp.activity.v1.GetCPWeeklyRankConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 244, // 222: hyapp.activity.v1.GetCPWeeklyRankConfigResponse.config:type_name -> hyapp.activity.v1.CPWeeklyRankConfig + 0, // 223: hyapp.activity.v1.UpdateCPWeeklyRankConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 244, // 224: hyapp.activity.v1.UpdateCPWeeklyRankConfigRequest.config:type_name -> hyapp.activity.v1.CPWeeklyRankConfig + 244, // 225: hyapp.activity.v1.UpdateCPWeeklyRankConfigResponse.config:type_name -> hyapp.activity.v1.CPWeeklyRankConfig + 0, // 226: hyapp.activity.v1.ListCPWeeklyRankSettlementsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 247, // 227: hyapp.activity.v1.ListCPWeeklyRankSettlementsResponse.settlements:type_name -> hyapp.activity.v1.CPWeeklyRankSettlement + 256, // 228: hyapp.activity.v1.AgencyOpeningCycle.rewards:type_name -> hyapp.activity.v1.AgencyOpeningReward + 0, // 229: hyapp.activity.v1.ListAgencyOpeningCyclesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 257, // 230: hyapp.activity.v1.ListAgencyOpeningCyclesResponse.cycles:type_name -> hyapp.activity.v1.AgencyOpeningCycle + 0, // 231: hyapp.activity.v1.GetAgencyOpeningCycleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 257, // 232: hyapp.activity.v1.GetAgencyOpeningCycleResponse.cycle:type_name -> hyapp.activity.v1.AgencyOpeningCycle + 0, // 233: hyapp.activity.v1.UpsertAgencyOpeningCycleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 257, // 234: hyapp.activity.v1.UpsertAgencyOpeningCycleRequest.cycle:type_name -> hyapp.activity.v1.AgencyOpeningCycle + 257, // 235: hyapp.activity.v1.UpsertAgencyOpeningCycleResponse.cycle:type_name -> hyapp.activity.v1.AgencyOpeningCycle + 0, // 236: hyapp.activity.v1.SetAgencyOpeningCycleStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 257, // 237: hyapp.activity.v1.SetAgencyOpeningCycleStatusResponse.cycle:type_name -> hyapp.activity.v1.AgencyOpeningCycle + 0, // 238: hyapp.activity.v1.ListAgencyOpeningApplicationsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 258, // 239: hyapp.activity.v1.ListAgencyOpeningApplicationsResponse.applications:type_name -> hyapp.activity.v1.AgencyOpeningApplication + 0, // 240: hyapp.activity.v1.ReviewAgencyOpeningApplicationRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 258, // 241: hyapp.activity.v1.ReviewAgencyOpeningApplicationResponse.application:type_name -> hyapp.activity.v1.AgencyOpeningApplication + 0, // 242: hyapp.activity.v1.GetAgencyOpeningStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 257, // 243: hyapp.activity.v1.GetAgencyOpeningStatusResponse.cycle:type_name -> hyapp.activity.v1.AgencyOpeningCycle + 258, // 244: hyapp.activity.v1.GetAgencyOpeningStatusResponse.application:type_name -> hyapp.activity.v1.AgencyOpeningApplication + 259, // 245: hyapp.activity.v1.GetAgencyOpeningStatusResponse.agency:type_name -> hyapp.activity.v1.AgencyOpeningAgencySnapshot + 0, // 246: hyapp.activity.v1.ApplyAgencyOpeningRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 258, // 247: hyapp.activity.v1.ApplyAgencyOpeningResponse.application:type_name -> hyapp.activity.v1.AgencyOpeningApplication + 1, // 248: hyapp.activity.v1.ActivityService.PingActivity:input_type -> hyapp.activity.v1.PingActivityRequest + 3, // 249: hyapp.activity.v1.ActivityService.GetActivityStatus:input_type -> hyapp.activity.v1.GetActivityStatusRequest + 6, // 250: hyapp.activity.v1.MessageInboxService.ListMessageTabs:input_type -> hyapp.activity.v1.ListMessageTabsRequest + 9, // 251: hyapp.activity.v1.MessageInboxService.ListInboxMessages:input_type -> hyapp.activity.v1.ListInboxMessagesRequest + 11, // 252: hyapp.activity.v1.MessageInboxService.MarkInboxMessageRead:input_type -> hyapp.activity.v1.MarkInboxMessageReadRequest + 13, // 253: hyapp.activity.v1.MessageInboxService.MarkInboxSectionRead:input_type -> hyapp.activity.v1.MarkInboxSectionReadRequest + 15, // 254: hyapp.activity.v1.MessageInboxService.DeleteInboxMessage:input_type -> hyapp.activity.v1.DeleteInboxMessageRequest + 17, // 255: hyapp.activity.v1.MessageInboxService.CreateInboxMessage:input_type -> hyapp.activity.v1.CreateInboxMessageRequest + 19, // 256: hyapp.activity.v1.MessageInboxService.CreateFanoutJob:input_type -> hyapp.activity.v1.CreateFanoutJobRequest + 22, // 257: hyapp.activity.v1.MessageActionConfirmService.AcceptActionConfirm:input_type -> hyapp.activity.v1.AcceptActionConfirmRequest + 24, // 258: hyapp.activity.v1.MessageActionConfirmService.RejectActionConfirm:input_type -> hyapp.activity.v1.RejectActionConfirmRequest + 26, // 259: hyapp.activity.v1.MessageActionConfirmService.BatchGetActionConfirmStatus:input_type -> hyapp.activity.v1.BatchGetActionConfirmStatusRequest + 28, // 260: hyapp.activity.v1.MessageActionConfirmService.ListConversationActionConfirms:input_type -> hyapp.activity.v1.ListConversationActionConfirmsRequest + 30, // 261: hyapp.activity.v1.ActivityCronService.ProcessMessageFanoutBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 30, // 262: hyapp.activity.v1.ActivityCronService.ProcessLevelRewardBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 30, // 263: hyapp.activity.v1.ActivityCronService.ProcessTemporaryLevelBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 30, // 264: hyapp.activity.v1.ActivityCronService.ProcessAchievementRewardBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 30, // 265: hyapp.activity.v1.ActivityCronService.ProcessRoomTurnoverRewardSettlementBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 30, // 266: hyapp.activity.v1.ActivityCronService.ProcessWeeklyStarSettlementBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 30, // 267: hyapp.activity.v1.ActivityCronService.ProcessCPWeeklyRankSettlementBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 30, // 268: hyapp.activity.v1.ActivityCronService.ProcessAgencyOpeningSettlementBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 34, // 269: hyapp.activity.v1.TaskService.ListUserTasks:input_type -> hyapp.activity.v1.ListUserTasksRequest + 36, // 270: hyapp.activity.v1.TaskService.ClaimTaskReward:input_type -> hyapp.activity.v1.ClaimTaskRewardRequest + 38, // 271: hyapp.activity.v1.TaskService.ConsumeTaskEvent:input_type -> hyapp.activity.v1.ConsumeTaskEventRequest + 156, // 272: hyapp.activity.v1.GrowthLevelService.GetMyLevelOverview:input_type -> hyapp.activity.v1.GetMyLevelOverviewRequest + 158, // 273: hyapp.activity.v1.GrowthLevelService.GetLevelTrack:input_type -> hyapp.activity.v1.GetLevelTrackRequest + 162, // 274: hyapp.activity.v1.GrowthLevelService.BatchGetUserLevelDisplayProfiles:input_type -> hyapp.activity.v1.BatchGetUserLevelDisplayProfilesRequest + 165, // 275: hyapp.activity.v1.GrowthLevelService.ListLevelRewards:input_type -> hyapp.activity.v1.ListLevelRewardsRequest + 167, // 276: hyapp.activity.v1.GrowthLevelService.ConsumeLevelEvent:input_type -> hyapp.activity.v1.ConsumeLevelEventRequest + 169, // 277: hyapp.activity.v1.GrowthLevelService.SetUserLevel:input_type -> hyapp.activity.v1.SetUserLevelRequest + 179, // 278: hyapp.activity.v1.GrowthLevelService.IssueRegistrationLevelBadges:input_type -> hyapp.activity.v1.IssueRegistrationLevelBadgesRequest + 192, // 279: hyapp.activity.v1.AchievementService.ListAchievements:input_type -> hyapp.activity.v1.ListAchievementsRequest + 194, // 280: hyapp.activity.v1.AchievementService.ConsumeAchievementEvent:input_type -> hyapp.activity.v1.ConsumeAchievementEventRequest + 197, // 281: hyapp.activity.v1.AchievementService.ListMyBadges:input_type -> hyapp.activity.v1.ListMyBadgesRequest + 199, // 282: hyapp.activity.v1.AchievementService.SetBadgeDisplay:input_type -> hyapp.activity.v1.SetBadgeDisplayRequest + 210, // 283: hyapp.activity.v1.WheelService.ExecuteWheelDraw:input_type -> hyapp.activity.v1.ExecuteWheelDrawRequest + 128, // 284: hyapp.activity.v1.RoomTurnoverRewardService.GetRoomTurnoverRewardStatus:input_type -> hyapp.activity.v1.GetRoomTurnoverRewardStatusRequest + 238, // 285: hyapp.activity.v1.WeeklyStarService.GetWeeklyStarCurrent:input_type -> hyapp.activity.v1.GetWeeklyStarCurrentRequest + 234, // 286: hyapp.activity.v1.WeeklyStarService.ListWeeklyStarLeaderboard:input_type -> hyapp.activity.v1.ListWeeklyStarLeaderboardRequest + 240, // 287: hyapp.activity.v1.WeeklyStarService.ListWeeklyStarHistory:input_type -> hyapp.activity.v1.ListWeeklyStarHistoryRequest + 248, // 288: hyapp.activity.v1.CPWeeklyRankService.GetCPWeeklyRankStatus:input_type -> hyapp.activity.v1.GetCPWeeklyRankStatusRequest + 272, // 289: hyapp.activity.v1.AgencyOpeningService.GetAgencyOpeningStatus:input_type -> hyapp.activity.v1.GetAgencyOpeningStatusRequest + 274, // 290: hyapp.activity.v1.AgencyOpeningService.ApplyAgencyOpening:input_type -> hyapp.activity.v1.ApplyAgencyOpeningRequest + 268, // 291: hyapp.activity.v1.AgencyOpeningService.ListAgencyOpeningLeaderboard:input_type -> hyapp.activity.v1.ListAgencyOpeningApplicationsRequest + 41, // 292: hyapp.activity.v1.BroadcastService.EnsureBroadcastGroups:input_type -> hyapp.activity.v1.EnsureBroadcastGroupsRequest + 43, // 293: hyapp.activity.v1.BroadcastService.PublishRegionBroadcast:input_type -> hyapp.activity.v1.PublishRegionBroadcastRequest + 44, // 294: hyapp.activity.v1.BroadcastService.PublishGlobalBroadcast:input_type -> hyapp.activity.v1.PublishGlobalBroadcastRequest + 46, // 295: hyapp.activity.v1.BroadcastService.RemoveRegionBroadcastMember:input_type -> hyapp.activity.v1.RemoveRegionBroadcastMemberRequest + 30, // 296: hyapp.activity.v1.BroadcastService.ProcessBroadcastOutboxBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 49, // 297: hyapp.activity.v1.RoomEventConsumerService.ConsumeRoomEvent:input_type -> hyapp.activity.v1.ConsumeRoomEventRequest + 52, // 298: hyapp.activity.v1.AdminTaskService.ListTaskDefinitions:input_type -> hyapp.activity.v1.ListTaskDefinitionsRequest + 54, // 299: hyapp.activity.v1.AdminTaskService.UpsertTaskDefinition:input_type -> hyapp.activity.v1.UpsertTaskDefinitionRequest + 56, // 300: hyapp.activity.v1.AdminTaskService.SetTaskDefinitionStatus:input_type -> hyapp.activity.v1.SetTaskDefinitionStatusRequest + 58, // 301: hyapp.activity.v1.AdminTaskService.PublishTaskRewardPolicy:input_type -> hyapp.activity.v1.PublishTaskRewardPolicyRequest + 63, // 302: hyapp.activity.v1.RegistrationRewardService.GetRegistrationRewardEligibility:input_type -> hyapp.activity.v1.GetRegistrationRewardEligibilityRequest + 65, // 303: hyapp.activity.v1.RegistrationRewardService.IssueRegistrationReward:input_type -> hyapp.activity.v1.IssueRegistrationRewardRequest + 67, // 304: hyapp.activity.v1.AdminRegistrationRewardService.GetRegistrationRewardConfig:input_type -> hyapp.activity.v1.GetRegistrationRewardConfigRequest + 69, // 305: hyapp.activity.v1.AdminRegistrationRewardService.UpdateRegistrationRewardConfig:input_type -> hyapp.activity.v1.UpdateRegistrationRewardConfigRequest + 71, // 306: hyapp.activity.v1.AdminRegistrationRewardService.ListRegistrationRewardClaims:input_type -> hyapp.activity.v1.ListRegistrationRewardClaimsRequest + 77, // 307: hyapp.activity.v1.FirstRechargeRewardService.GetFirstRechargeRewardStatus:input_type -> hyapp.activity.v1.GetFirstRechargeRewardStatusRequest + 79, // 308: hyapp.activity.v1.FirstRechargeRewardService.ConsumeFirstRechargeReward:input_type -> hyapp.activity.v1.ConsumeFirstRechargeRewardRequest + 81, // 309: hyapp.activity.v1.AdminFirstRechargeRewardService.GetFirstRechargeRewardConfig:input_type -> hyapp.activity.v1.GetFirstRechargeRewardConfigRequest + 83, // 310: hyapp.activity.v1.AdminFirstRechargeRewardService.UpdateFirstRechargeRewardConfig:input_type -> hyapp.activity.v1.UpdateFirstRechargeRewardConfigRequest + 85, // 311: hyapp.activity.v1.AdminFirstRechargeRewardService.ListFirstRechargeRewardClaims:input_type -> hyapp.activity.v1.ListFirstRechargeRewardClaimsRequest + 92, // 312: hyapp.activity.v1.CumulativeRechargeRewardService.GetCumulativeRechargeRewardStatus:input_type -> hyapp.activity.v1.GetCumulativeRechargeRewardStatusRequest + 94, // 313: hyapp.activity.v1.CumulativeRechargeRewardService.ConsumeCumulativeRechargeReward:input_type -> hyapp.activity.v1.ConsumeCumulativeRechargeRewardRequest + 107, // 314: hyapp.activity.v1.InviteActivityRewardService.GetInviteActivityRewardStatus:input_type -> hyapp.activity.v1.GetInviteActivityRewardStatusRequest + 109, // 315: hyapp.activity.v1.InviteActivityRewardService.ClaimInviteActivityReward:input_type -> hyapp.activity.v1.ClaimInviteActivityRewardRequest + 112, // 316: hyapp.activity.v1.InviteActivityRewardService.ListInviteActivityLeaderboard:input_type -> hyapp.activity.v1.ListInviteActivityLeaderboardRequest + 96, // 317: hyapp.activity.v1.AdminCumulativeRechargeRewardService.GetCumulativeRechargeRewardConfig:input_type -> hyapp.activity.v1.GetCumulativeRechargeRewardConfigRequest + 98, // 318: hyapp.activity.v1.AdminCumulativeRechargeRewardService.UpdateCumulativeRechargeRewardConfig:input_type -> hyapp.activity.v1.UpdateCumulativeRechargeRewardConfigRequest + 100, // 319: hyapp.activity.v1.AdminCumulativeRechargeRewardService.ListCumulativeRechargeRewardGrants:input_type -> hyapp.activity.v1.ListCumulativeRechargeRewardGrantsRequest + 114, // 320: hyapp.activity.v1.AdminInviteActivityRewardService.GetInviteActivityRewardConfig:input_type -> hyapp.activity.v1.GetInviteActivityRewardConfigRequest + 116, // 321: hyapp.activity.v1.AdminInviteActivityRewardService.UpdateInviteActivityRewardConfig:input_type -> hyapp.activity.v1.UpdateInviteActivityRewardConfigRequest + 118, // 322: hyapp.activity.v1.AdminInviteActivityRewardService.ListInviteActivityRewardClaims:input_type -> hyapp.activity.v1.ListInviteActivityRewardClaimsRequest + 122, // 323: hyapp.activity.v1.AdminInviteActivityRewardService.ListInviteActivityRewardSummaries:input_type -> hyapp.activity.v1.ListInviteActivityRewardSummariesRequest + 130, // 324: hyapp.activity.v1.AdminRoomTurnoverRewardService.GetRoomTurnoverRewardConfig:input_type -> hyapp.activity.v1.GetRoomTurnoverRewardConfigRequest + 132, // 325: hyapp.activity.v1.AdminRoomTurnoverRewardService.UpdateRoomTurnoverRewardConfig:input_type -> hyapp.activity.v1.UpdateRoomTurnoverRewardConfigRequest + 134, // 326: hyapp.activity.v1.AdminRoomTurnoverRewardService.ListRoomTurnoverRewardSettlements:input_type -> hyapp.activity.v1.ListRoomTurnoverRewardSettlementsRequest + 136, // 327: hyapp.activity.v1.AdminRoomTurnoverRewardService.RetryRoomTurnoverRewardSettlement:input_type -> hyapp.activity.v1.RetryRoomTurnoverRewardSettlementRequest + 226, // 328: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarCycles:input_type -> hyapp.activity.v1.ListWeeklyStarCyclesRequest + 230, // 329: hyapp.activity.v1.AdminWeeklyStarService.CreateWeeklyStarCycle:input_type -> hyapp.activity.v1.UpsertWeeklyStarCycleRequest + 228, // 330: hyapp.activity.v1.AdminWeeklyStarService.GetWeeklyStarCycle:input_type -> hyapp.activity.v1.GetWeeklyStarCycleRequest + 230, // 331: hyapp.activity.v1.AdminWeeklyStarService.UpdateWeeklyStarCycle:input_type -> hyapp.activity.v1.UpsertWeeklyStarCycleRequest + 232, // 332: hyapp.activity.v1.AdminWeeklyStarService.SetWeeklyStarCycleStatus:input_type -> hyapp.activity.v1.SetWeeklyStarCycleStatusRequest + 234, // 333: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarLeaderboard:input_type -> hyapp.activity.v1.ListWeeklyStarLeaderboardRequest + 236, // 334: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarSettlements:input_type -> hyapp.activity.v1.ListWeeklyStarSettlementsRequest + 250, // 335: hyapp.activity.v1.AdminCPWeeklyRankService.GetCPWeeklyRankConfig:input_type -> hyapp.activity.v1.GetCPWeeklyRankConfigRequest + 252, // 336: hyapp.activity.v1.AdminCPWeeklyRankService.UpdateCPWeeklyRankConfig:input_type -> hyapp.activity.v1.UpdateCPWeeklyRankConfigRequest + 254, // 337: hyapp.activity.v1.AdminCPWeeklyRankService.ListCPWeeklyRankSettlements:input_type -> hyapp.activity.v1.ListCPWeeklyRankSettlementsRequest + 260, // 338: hyapp.activity.v1.AdminAgencyOpeningService.ListAgencyOpeningCycles:input_type -> hyapp.activity.v1.ListAgencyOpeningCyclesRequest + 264, // 339: hyapp.activity.v1.AdminAgencyOpeningService.CreateAgencyOpeningCycle:input_type -> hyapp.activity.v1.UpsertAgencyOpeningCycleRequest + 262, // 340: hyapp.activity.v1.AdminAgencyOpeningService.GetAgencyOpeningCycle:input_type -> hyapp.activity.v1.GetAgencyOpeningCycleRequest + 264, // 341: hyapp.activity.v1.AdminAgencyOpeningService.UpdateAgencyOpeningCycle:input_type -> hyapp.activity.v1.UpsertAgencyOpeningCycleRequest + 266, // 342: hyapp.activity.v1.AdminAgencyOpeningService.SetAgencyOpeningCycleStatus:input_type -> hyapp.activity.v1.SetAgencyOpeningCycleStatusRequest + 268, // 343: hyapp.activity.v1.AdminAgencyOpeningService.ListAgencyOpeningApplications:input_type -> hyapp.activity.v1.ListAgencyOpeningApplicationsRequest + 270, // 344: hyapp.activity.v1.AdminAgencyOpeningService.ReviewAgencyOpeningApplication:input_type -> hyapp.activity.v1.ReviewAgencyOpeningApplicationRequest + 141, // 345: hyapp.activity.v1.SevenDayCheckInService.GetSevenDayCheckInStatus:input_type -> hyapp.activity.v1.GetSevenDayCheckInStatusRequest + 143, // 346: hyapp.activity.v1.SevenDayCheckInService.SignSevenDayCheckIn:input_type -> hyapp.activity.v1.SignSevenDayCheckInRequest + 145, // 347: hyapp.activity.v1.AdminSevenDayCheckInService.GetSevenDayCheckInConfig:input_type -> hyapp.activity.v1.GetSevenDayCheckInConfigRequest + 147, // 348: hyapp.activity.v1.AdminSevenDayCheckInService.UpdateSevenDayCheckInConfig:input_type -> hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest + 150, // 349: hyapp.activity.v1.AdminSevenDayCheckInService.ListSevenDayCheckInClaims:input_type -> hyapp.activity.v1.ListSevenDayCheckInClaimsRequest + 187, // 350: hyapp.activity.v1.AdminGrowthLevelService.ListLevelConfig:input_type -> hyapp.activity.v1.ListLevelConfigRequest + 181, // 351: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTrack:input_type -> hyapp.activity.v1.UpsertLevelTrackRequest + 183, // 352: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelRule:input_type -> hyapp.activity.v1.UpsertLevelRuleRequest + 185, // 353: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTier:input_type -> hyapp.activity.v1.UpsertLevelTierRequest + 173, // 354: hyapp.activity.v1.AdminGrowthLevelService.BatchGetUserLevelAdminProfiles:input_type -> hyapp.activity.v1.BatchGetUserLevelAdminProfilesRequest + 176, // 355: hyapp.activity.v1.AdminGrowthLevelService.AdjustTemporaryUserLevels:input_type -> hyapp.activity.v1.AdjustTemporaryUserLevelsRequest + 192, // 356: hyapp.activity.v1.AdminAchievementService.ListAchievementDefinitions:input_type -> hyapp.activity.v1.ListAchievementsRequest + 201, // 357: hyapp.activity.v1.AdminAchievementService.UpsertAchievementDefinition:input_type -> hyapp.activity.v1.UpsertAchievementDefinitionRequest + 203, // 358: hyapp.activity.v1.AdminAchievementService.DeleteAchievementDefinition:input_type -> hyapp.activity.v1.DeleteAchievementDefinitionRequest + 212, // 359: hyapp.activity.v1.AdminWheelService.GetWheelConfig:input_type -> hyapp.activity.v1.GetWheelConfigRequest + 214, // 360: hyapp.activity.v1.AdminWheelService.UpsertWheelConfig:input_type -> hyapp.activity.v1.UpsertWheelConfigRequest + 216, // 361: hyapp.activity.v1.AdminWheelService.ListWheelDraws:input_type -> hyapp.activity.v1.ListWheelDrawsRequest + 219, // 362: hyapp.activity.v1.AdminWheelService.GetWheelDrawSummary:input_type -> hyapp.activity.v1.GetWheelDrawSummaryRequest + 2, // 363: hyapp.activity.v1.ActivityService.PingActivity:output_type -> hyapp.activity.v1.PingActivityResponse + 4, // 364: hyapp.activity.v1.ActivityService.GetActivityStatus:output_type -> hyapp.activity.v1.GetActivityStatusResponse + 7, // 365: hyapp.activity.v1.MessageInboxService.ListMessageTabs:output_type -> hyapp.activity.v1.ListMessageTabsResponse + 10, // 366: hyapp.activity.v1.MessageInboxService.ListInboxMessages:output_type -> hyapp.activity.v1.ListInboxMessagesResponse + 12, // 367: hyapp.activity.v1.MessageInboxService.MarkInboxMessageRead:output_type -> hyapp.activity.v1.MarkInboxMessageReadResponse + 14, // 368: hyapp.activity.v1.MessageInboxService.MarkInboxSectionRead:output_type -> hyapp.activity.v1.MarkInboxSectionReadResponse + 16, // 369: hyapp.activity.v1.MessageInboxService.DeleteInboxMessage:output_type -> hyapp.activity.v1.DeleteInboxMessageResponse + 18, // 370: hyapp.activity.v1.MessageInboxService.CreateInboxMessage:output_type -> hyapp.activity.v1.CreateInboxMessageResponse + 20, // 371: hyapp.activity.v1.MessageInboxService.CreateFanoutJob:output_type -> hyapp.activity.v1.CreateFanoutJobResponse + 23, // 372: hyapp.activity.v1.MessageActionConfirmService.AcceptActionConfirm:output_type -> hyapp.activity.v1.AcceptActionConfirmResponse + 25, // 373: hyapp.activity.v1.MessageActionConfirmService.RejectActionConfirm:output_type -> hyapp.activity.v1.RejectActionConfirmResponse + 27, // 374: hyapp.activity.v1.MessageActionConfirmService.BatchGetActionConfirmStatus:output_type -> hyapp.activity.v1.BatchGetActionConfirmStatusResponse + 29, // 375: hyapp.activity.v1.MessageActionConfirmService.ListConversationActionConfirms:output_type -> hyapp.activity.v1.ListConversationActionConfirmsResponse + 31, // 376: hyapp.activity.v1.ActivityCronService.ProcessMessageFanoutBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 31, // 377: hyapp.activity.v1.ActivityCronService.ProcessLevelRewardBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 31, // 378: hyapp.activity.v1.ActivityCronService.ProcessTemporaryLevelBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 31, // 379: hyapp.activity.v1.ActivityCronService.ProcessAchievementRewardBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 31, // 380: hyapp.activity.v1.ActivityCronService.ProcessRoomTurnoverRewardSettlementBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 31, // 381: hyapp.activity.v1.ActivityCronService.ProcessWeeklyStarSettlementBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 31, // 382: hyapp.activity.v1.ActivityCronService.ProcessCPWeeklyRankSettlementBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 31, // 383: hyapp.activity.v1.ActivityCronService.ProcessAgencyOpeningSettlementBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 35, // 384: hyapp.activity.v1.TaskService.ListUserTasks:output_type -> hyapp.activity.v1.ListUserTasksResponse + 37, // 385: hyapp.activity.v1.TaskService.ClaimTaskReward:output_type -> hyapp.activity.v1.ClaimTaskRewardResponse + 39, // 386: hyapp.activity.v1.TaskService.ConsumeTaskEvent:output_type -> hyapp.activity.v1.ConsumeTaskEventResponse + 157, // 387: hyapp.activity.v1.GrowthLevelService.GetMyLevelOverview:output_type -> hyapp.activity.v1.GetMyLevelOverviewResponse + 159, // 388: hyapp.activity.v1.GrowthLevelService.GetLevelTrack:output_type -> hyapp.activity.v1.GetLevelTrackResponse + 163, // 389: hyapp.activity.v1.GrowthLevelService.BatchGetUserLevelDisplayProfiles:output_type -> hyapp.activity.v1.BatchGetUserLevelDisplayProfilesResponse + 166, // 390: hyapp.activity.v1.GrowthLevelService.ListLevelRewards:output_type -> hyapp.activity.v1.ListLevelRewardsResponse + 168, // 391: hyapp.activity.v1.GrowthLevelService.ConsumeLevelEvent:output_type -> hyapp.activity.v1.ConsumeLevelEventResponse + 170, // 392: hyapp.activity.v1.GrowthLevelService.SetUserLevel:output_type -> hyapp.activity.v1.SetUserLevelResponse + 180, // 393: hyapp.activity.v1.GrowthLevelService.IssueRegistrationLevelBadges:output_type -> hyapp.activity.v1.IssueRegistrationLevelBadgesResponse + 193, // 394: hyapp.activity.v1.AchievementService.ListAchievements:output_type -> hyapp.activity.v1.ListAchievementsResponse + 195, // 395: hyapp.activity.v1.AchievementService.ConsumeAchievementEvent:output_type -> hyapp.activity.v1.ConsumeAchievementEventResponse + 198, // 396: hyapp.activity.v1.AchievementService.ListMyBadges:output_type -> hyapp.activity.v1.ListMyBadgesResponse + 200, // 397: hyapp.activity.v1.AchievementService.SetBadgeDisplay:output_type -> hyapp.activity.v1.SetBadgeDisplayResponse + 211, // 398: hyapp.activity.v1.WheelService.ExecuteWheelDraw:output_type -> hyapp.activity.v1.ExecuteWheelDrawResponse + 129, // 399: hyapp.activity.v1.RoomTurnoverRewardService.GetRoomTurnoverRewardStatus:output_type -> hyapp.activity.v1.GetRoomTurnoverRewardStatusResponse + 239, // 400: hyapp.activity.v1.WeeklyStarService.GetWeeklyStarCurrent:output_type -> hyapp.activity.v1.GetWeeklyStarCurrentResponse + 235, // 401: hyapp.activity.v1.WeeklyStarService.ListWeeklyStarLeaderboard:output_type -> hyapp.activity.v1.ListWeeklyStarLeaderboardResponse + 242, // 402: hyapp.activity.v1.WeeklyStarService.ListWeeklyStarHistory:output_type -> hyapp.activity.v1.ListWeeklyStarHistoryResponse + 249, // 403: hyapp.activity.v1.CPWeeklyRankService.GetCPWeeklyRankStatus:output_type -> hyapp.activity.v1.GetCPWeeklyRankStatusResponse + 273, // 404: hyapp.activity.v1.AgencyOpeningService.GetAgencyOpeningStatus:output_type -> hyapp.activity.v1.GetAgencyOpeningStatusResponse + 275, // 405: hyapp.activity.v1.AgencyOpeningService.ApplyAgencyOpening:output_type -> hyapp.activity.v1.ApplyAgencyOpeningResponse + 269, // 406: hyapp.activity.v1.AgencyOpeningService.ListAgencyOpeningLeaderboard:output_type -> hyapp.activity.v1.ListAgencyOpeningApplicationsResponse + 42, // 407: hyapp.activity.v1.BroadcastService.EnsureBroadcastGroups:output_type -> hyapp.activity.v1.EnsureBroadcastGroupsResponse + 45, // 408: hyapp.activity.v1.BroadcastService.PublishRegionBroadcast:output_type -> hyapp.activity.v1.PublishBroadcastResponse + 45, // 409: hyapp.activity.v1.BroadcastService.PublishGlobalBroadcast:output_type -> hyapp.activity.v1.PublishBroadcastResponse + 47, // 410: hyapp.activity.v1.BroadcastService.RemoveRegionBroadcastMember:output_type -> hyapp.activity.v1.RemoveRegionBroadcastMemberResponse + 48, // 411: hyapp.activity.v1.BroadcastService.ProcessBroadcastOutboxBatch:output_type -> hyapp.activity.v1.ProcessBroadcastOutboxBatchResponse + 50, // 412: hyapp.activity.v1.RoomEventConsumerService.ConsumeRoomEvent:output_type -> hyapp.activity.v1.ConsumeRoomEventResponse + 53, // 413: hyapp.activity.v1.AdminTaskService.ListTaskDefinitions:output_type -> hyapp.activity.v1.ListTaskDefinitionsResponse + 55, // 414: hyapp.activity.v1.AdminTaskService.UpsertTaskDefinition:output_type -> hyapp.activity.v1.UpsertTaskDefinitionResponse + 57, // 415: hyapp.activity.v1.AdminTaskService.SetTaskDefinitionStatus:output_type -> hyapp.activity.v1.SetTaskDefinitionStatusResponse + 59, // 416: hyapp.activity.v1.AdminTaskService.PublishTaskRewardPolicy:output_type -> hyapp.activity.v1.PublishTaskRewardPolicyResponse + 64, // 417: hyapp.activity.v1.RegistrationRewardService.GetRegistrationRewardEligibility:output_type -> hyapp.activity.v1.GetRegistrationRewardEligibilityResponse + 66, // 418: hyapp.activity.v1.RegistrationRewardService.IssueRegistrationReward:output_type -> hyapp.activity.v1.IssueRegistrationRewardResponse + 68, // 419: hyapp.activity.v1.AdminRegistrationRewardService.GetRegistrationRewardConfig:output_type -> hyapp.activity.v1.GetRegistrationRewardConfigResponse + 70, // 420: hyapp.activity.v1.AdminRegistrationRewardService.UpdateRegistrationRewardConfig:output_type -> hyapp.activity.v1.UpdateRegistrationRewardConfigResponse + 72, // 421: hyapp.activity.v1.AdminRegistrationRewardService.ListRegistrationRewardClaims:output_type -> hyapp.activity.v1.ListRegistrationRewardClaimsResponse + 78, // 422: hyapp.activity.v1.FirstRechargeRewardService.GetFirstRechargeRewardStatus:output_type -> hyapp.activity.v1.GetFirstRechargeRewardStatusResponse + 80, // 423: hyapp.activity.v1.FirstRechargeRewardService.ConsumeFirstRechargeReward:output_type -> hyapp.activity.v1.ConsumeFirstRechargeRewardResponse + 82, // 424: hyapp.activity.v1.AdminFirstRechargeRewardService.GetFirstRechargeRewardConfig:output_type -> hyapp.activity.v1.GetFirstRechargeRewardConfigResponse + 84, // 425: hyapp.activity.v1.AdminFirstRechargeRewardService.UpdateFirstRechargeRewardConfig:output_type -> hyapp.activity.v1.UpdateFirstRechargeRewardConfigResponse + 86, // 426: hyapp.activity.v1.AdminFirstRechargeRewardService.ListFirstRechargeRewardClaims:output_type -> hyapp.activity.v1.ListFirstRechargeRewardClaimsResponse + 93, // 427: hyapp.activity.v1.CumulativeRechargeRewardService.GetCumulativeRechargeRewardStatus:output_type -> hyapp.activity.v1.GetCumulativeRechargeRewardStatusResponse + 95, // 428: hyapp.activity.v1.CumulativeRechargeRewardService.ConsumeCumulativeRechargeReward:output_type -> hyapp.activity.v1.ConsumeCumulativeRechargeRewardResponse + 108, // 429: hyapp.activity.v1.InviteActivityRewardService.GetInviteActivityRewardStatus:output_type -> hyapp.activity.v1.GetInviteActivityRewardStatusResponse + 110, // 430: hyapp.activity.v1.InviteActivityRewardService.ClaimInviteActivityReward:output_type -> hyapp.activity.v1.ClaimInviteActivityRewardResponse + 113, // 431: hyapp.activity.v1.InviteActivityRewardService.ListInviteActivityLeaderboard:output_type -> hyapp.activity.v1.ListInviteActivityLeaderboardResponse + 97, // 432: hyapp.activity.v1.AdminCumulativeRechargeRewardService.GetCumulativeRechargeRewardConfig:output_type -> hyapp.activity.v1.GetCumulativeRechargeRewardConfigResponse + 99, // 433: hyapp.activity.v1.AdminCumulativeRechargeRewardService.UpdateCumulativeRechargeRewardConfig:output_type -> hyapp.activity.v1.UpdateCumulativeRechargeRewardConfigResponse + 101, // 434: hyapp.activity.v1.AdminCumulativeRechargeRewardService.ListCumulativeRechargeRewardGrants:output_type -> hyapp.activity.v1.ListCumulativeRechargeRewardGrantsResponse + 115, // 435: hyapp.activity.v1.AdminInviteActivityRewardService.GetInviteActivityRewardConfig:output_type -> hyapp.activity.v1.GetInviteActivityRewardConfigResponse + 117, // 436: hyapp.activity.v1.AdminInviteActivityRewardService.UpdateInviteActivityRewardConfig:output_type -> hyapp.activity.v1.UpdateInviteActivityRewardConfigResponse + 119, // 437: hyapp.activity.v1.AdminInviteActivityRewardService.ListInviteActivityRewardClaims:output_type -> hyapp.activity.v1.ListInviteActivityRewardClaimsResponse + 123, // 438: hyapp.activity.v1.AdminInviteActivityRewardService.ListInviteActivityRewardSummaries:output_type -> hyapp.activity.v1.ListInviteActivityRewardSummariesResponse + 131, // 439: hyapp.activity.v1.AdminRoomTurnoverRewardService.GetRoomTurnoverRewardConfig:output_type -> hyapp.activity.v1.GetRoomTurnoverRewardConfigResponse + 133, // 440: hyapp.activity.v1.AdminRoomTurnoverRewardService.UpdateRoomTurnoverRewardConfig:output_type -> hyapp.activity.v1.UpdateRoomTurnoverRewardConfigResponse + 135, // 441: hyapp.activity.v1.AdminRoomTurnoverRewardService.ListRoomTurnoverRewardSettlements:output_type -> hyapp.activity.v1.ListRoomTurnoverRewardSettlementsResponse + 137, // 442: hyapp.activity.v1.AdminRoomTurnoverRewardService.RetryRoomTurnoverRewardSettlement:output_type -> hyapp.activity.v1.RetryRoomTurnoverRewardSettlementResponse + 227, // 443: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarCycles:output_type -> hyapp.activity.v1.ListWeeklyStarCyclesResponse + 231, // 444: hyapp.activity.v1.AdminWeeklyStarService.CreateWeeklyStarCycle:output_type -> hyapp.activity.v1.UpsertWeeklyStarCycleResponse + 229, // 445: hyapp.activity.v1.AdminWeeklyStarService.GetWeeklyStarCycle:output_type -> hyapp.activity.v1.GetWeeklyStarCycleResponse + 231, // 446: hyapp.activity.v1.AdminWeeklyStarService.UpdateWeeklyStarCycle:output_type -> hyapp.activity.v1.UpsertWeeklyStarCycleResponse + 233, // 447: hyapp.activity.v1.AdminWeeklyStarService.SetWeeklyStarCycleStatus:output_type -> hyapp.activity.v1.SetWeeklyStarCycleStatusResponse + 235, // 448: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarLeaderboard:output_type -> hyapp.activity.v1.ListWeeklyStarLeaderboardResponse + 237, // 449: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarSettlements:output_type -> hyapp.activity.v1.ListWeeklyStarSettlementsResponse + 251, // 450: hyapp.activity.v1.AdminCPWeeklyRankService.GetCPWeeklyRankConfig:output_type -> hyapp.activity.v1.GetCPWeeklyRankConfigResponse + 253, // 451: hyapp.activity.v1.AdminCPWeeklyRankService.UpdateCPWeeklyRankConfig:output_type -> hyapp.activity.v1.UpdateCPWeeklyRankConfigResponse + 255, // 452: hyapp.activity.v1.AdminCPWeeklyRankService.ListCPWeeklyRankSettlements:output_type -> hyapp.activity.v1.ListCPWeeklyRankSettlementsResponse + 261, // 453: hyapp.activity.v1.AdminAgencyOpeningService.ListAgencyOpeningCycles:output_type -> hyapp.activity.v1.ListAgencyOpeningCyclesResponse + 265, // 454: hyapp.activity.v1.AdminAgencyOpeningService.CreateAgencyOpeningCycle:output_type -> hyapp.activity.v1.UpsertAgencyOpeningCycleResponse + 263, // 455: hyapp.activity.v1.AdminAgencyOpeningService.GetAgencyOpeningCycle:output_type -> hyapp.activity.v1.GetAgencyOpeningCycleResponse + 265, // 456: hyapp.activity.v1.AdminAgencyOpeningService.UpdateAgencyOpeningCycle:output_type -> hyapp.activity.v1.UpsertAgencyOpeningCycleResponse + 267, // 457: hyapp.activity.v1.AdminAgencyOpeningService.SetAgencyOpeningCycleStatus:output_type -> hyapp.activity.v1.SetAgencyOpeningCycleStatusResponse + 269, // 458: hyapp.activity.v1.AdminAgencyOpeningService.ListAgencyOpeningApplications:output_type -> hyapp.activity.v1.ListAgencyOpeningApplicationsResponse + 271, // 459: hyapp.activity.v1.AdminAgencyOpeningService.ReviewAgencyOpeningApplication:output_type -> hyapp.activity.v1.ReviewAgencyOpeningApplicationResponse + 142, // 460: hyapp.activity.v1.SevenDayCheckInService.GetSevenDayCheckInStatus:output_type -> hyapp.activity.v1.GetSevenDayCheckInStatusResponse + 144, // 461: hyapp.activity.v1.SevenDayCheckInService.SignSevenDayCheckIn:output_type -> hyapp.activity.v1.SignSevenDayCheckInResponse + 146, // 462: hyapp.activity.v1.AdminSevenDayCheckInService.GetSevenDayCheckInConfig:output_type -> hyapp.activity.v1.GetSevenDayCheckInConfigResponse + 148, // 463: hyapp.activity.v1.AdminSevenDayCheckInService.UpdateSevenDayCheckInConfig:output_type -> hyapp.activity.v1.UpdateSevenDayCheckInConfigResponse + 151, // 464: hyapp.activity.v1.AdminSevenDayCheckInService.ListSevenDayCheckInClaims:output_type -> hyapp.activity.v1.ListSevenDayCheckInClaimsResponse + 188, // 465: hyapp.activity.v1.AdminGrowthLevelService.ListLevelConfig:output_type -> hyapp.activity.v1.ListLevelConfigResponse + 182, // 466: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTrack:output_type -> hyapp.activity.v1.UpsertLevelTrackResponse + 184, // 467: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelRule:output_type -> hyapp.activity.v1.UpsertLevelRuleResponse + 186, // 468: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTier:output_type -> hyapp.activity.v1.UpsertLevelTierResponse + 174, // 469: hyapp.activity.v1.AdminGrowthLevelService.BatchGetUserLevelAdminProfiles:output_type -> hyapp.activity.v1.BatchGetUserLevelAdminProfilesResponse + 177, // 470: hyapp.activity.v1.AdminGrowthLevelService.AdjustTemporaryUserLevels:output_type -> hyapp.activity.v1.AdjustTemporaryUserLevelsResponse + 193, // 471: hyapp.activity.v1.AdminAchievementService.ListAchievementDefinitions:output_type -> hyapp.activity.v1.ListAchievementsResponse + 202, // 472: hyapp.activity.v1.AdminAchievementService.UpsertAchievementDefinition:output_type -> hyapp.activity.v1.UpsertAchievementDefinitionResponse + 204, // 473: hyapp.activity.v1.AdminAchievementService.DeleteAchievementDefinition:output_type -> hyapp.activity.v1.DeleteAchievementDefinitionResponse + 213, // 474: hyapp.activity.v1.AdminWheelService.GetWheelConfig:output_type -> hyapp.activity.v1.GetWheelConfigResponse + 215, // 475: hyapp.activity.v1.AdminWheelService.UpsertWheelConfig:output_type -> hyapp.activity.v1.UpsertWheelConfigResponse + 217, // 476: hyapp.activity.v1.AdminWheelService.ListWheelDraws:output_type -> hyapp.activity.v1.ListWheelDrawsResponse + 220, // 477: hyapp.activity.v1.AdminWheelService.GetWheelDrawSummary:output_type -> hyapp.activity.v1.GetWheelDrawSummaryResponse + 363, // [363:478] is the sub-list for method output_type + 248, // [248:363] is the sub-list for method input_type + 248, // [248:248] is the sub-list for extension type_name + 248, // [248:248] is the sub-list for extension extendee + 0, // [0:248] is the sub-list for field type_name } func init() { file_proto_activity_v1_activity_proto_init() } @@ -26881,7 +27549,7 @@ func file_proto_activity_v1_activity_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_activity_v1_activity_proto_rawDesc, NumEnums: 0, - NumMessages: 269, + NumMessages: 276, NumExtensions: 0, NumServices: 32, }, diff --git a/api/proto/activity/v1/activity.proto b/api/proto/activity/v1/activity.proto index 905bc189..c451e65a 100644 --- a/api/proto/activity/v1/activity.proto +++ b/api/proto/activity/v1/activity.proto @@ -1450,6 +1450,13 @@ message LevelRewardJob { string failure_reason = 11; int64 created_at_ms = 12; int64 updated_at_ms = 13; + string reward_origin = 14; + string temporary_level_id = 15; + int32 grant_generation = 16; + int32 reward_level = 17; + bool permanent = 18; + int64 temporary_expires_at_ms = 19; + string revoke_status = 20; } message ListLevelRewardsRequest { @@ -1511,6 +1518,55 @@ message SetUserLevelResponse { int64 server_time_ms = 8; } +// AdminLevelTrackProfile keeps the permanent account and the currently effective display overlay separate. +message AdminLevelTrackProfile { + string track = 1; + int32 real_level = 2; + int64 real_total_value = 3; + int32 display_level = 4; + int64 display_value = 5; + string temporary_level_id = 6; + int32 temporary_target_level = 7; + int64 started_at_ms = 8; + int64 expires_at_ms = 9; +} + +message AdminUserLevelProfile { + int64 user_id = 1; + repeated AdminLevelTrackProfile tracks = 2; +} + +message BatchGetUserLevelAdminProfilesRequest { + RequestMeta meta = 1; + repeated int64 user_ids = 2; +} + +message BatchGetUserLevelAdminProfilesResponse { + repeated AdminUserLevelProfile profiles = 1; + int64 server_time_ms = 2; +} + +// TemporaryLevelAdjustment is limited to wealth/charm; duration_days must be positive and level is 1..50. +message TemporaryLevelAdjustment { + string track = 1; + int32 level = 2; + int32 duration_days = 3; +} + +message AdjustTemporaryUserLevelsRequest { + RequestMeta meta = 1; + string command_id = 2; + int64 user_id = 3; + repeated TemporaryLevelAdjustment adjustments = 4; + int64 operator_admin_id = 5; + string reason = 6; +} + +message AdjustTemporaryUserLevelsResponse { + AdminUserLevelProfile profile = 1; + int64 server_time_ms = 2; +} + message RegistrationLevelBadgeGrant { string track = 1; int32 level = 2; @@ -2335,6 +2391,7 @@ service MessageActionConfirmService { service ActivityCronService { rpc ProcessMessageFanoutBatch(CronBatchRequest) returns (CronBatchResponse); rpc ProcessLevelRewardBatch(CronBatchRequest) returns (CronBatchResponse); + rpc ProcessTemporaryLevelBatch(CronBatchRequest) returns (CronBatchResponse); rpc ProcessAchievementRewardBatch(CronBatchRequest) returns (CronBatchResponse); rpc ProcessRoomTurnoverRewardSettlementBatch(CronBatchRequest) returns (CronBatchResponse); rpc ProcessWeeklyStarSettlementBatch(CronBatchRequest) returns (CronBatchResponse); @@ -2529,6 +2586,8 @@ service AdminGrowthLevelService { rpc UpsertLevelTrack(UpsertLevelTrackRequest) returns (UpsertLevelTrackResponse); rpc UpsertLevelRule(UpsertLevelRuleRequest) returns (UpsertLevelRuleResponse); rpc UpsertLevelTier(UpsertLevelTierRequest) returns (UpsertLevelTierResponse); + rpc BatchGetUserLevelAdminProfiles(BatchGetUserLevelAdminProfilesRequest) returns (BatchGetUserLevelAdminProfilesResponse); + rpc AdjustTemporaryUserLevels(AdjustTemporaryUserLevelsRequest) returns (AdjustTemporaryUserLevelsResponse); } // AdminAchievementService is the admin entry for achievement definitions. diff --git a/api/proto/activity/v1/activity_grpc.pb.go b/api/proto/activity/v1/activity_grpc.pb.go index eb5e6f8b..930cc6df 100644 --- a/api/proto/activity/v1/activity_grpc.pb.go +++ b/api/proto/activity/v1/activity_grpc.pb.go @@ -720,6 +720,7 @@ var MessageActionConfirmService_ServiceDesc = grpc.ServiceDesc{ const ( ActivityCronService_ProcessMessageFanoutBatch_FullMethodName = "/hyapp.activity.v1.ActivityCronService/ProcessMessageFanoutBatch" ActivityCronService_ProcessLevelRewardBatch_FullMethodName = "/hyapp.activity.v1.ActivityCronService/ProcessLevelRewardBatch" + ActivityCronService_ProcessTemporaryLevelBatch_FullMethodName = "/hyapp.activity.v1.ActivityCronService/ProcessTemporaryLevelBatch" ActivityCronService_ProcessAchievementRewardBatch_FullMethodName = "/hyapp.activity.v1.ActivityCronService/ProcessAchievementRewardBatch" ActivityCronService_ProcessRoomTurnoverRewardSettlementBatch_FullMethodName = "/hyapp.activity.v1.ActivityCronService/ProcessRoomTurnoverRewardSettlementBatch" ActivityCronService_ProcessWeeklyStarSettlementBatch_FullMethodName = "/hyapp.activity.v1.ActivityCronService/ProcessWeeklyStarSettlementBatch" @@ -735,6 +736,7 @@ const ( type ActivityCronServiceClient interface { ProcessMessageFanoutBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) ProcessLevelRewardBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) + ProcessTemporaryLevelBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) ProcessAchievementRewardBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) ProcessRoomTurnoverRewardSettlementBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) ProcessWeeklyStarSettlementBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) @@ -770,6 +772,16 @@ func (c *activityCronServiceClient) ProcessLevelRewardBatch(ctx context.Context, return out, nil } +func (c *activityCronServiceClient) ProcessTemporaryLevelBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CronBatchResponse) + err := c.cc.Invoke(ctx, ActivityCronService_ProcessTemporaryLevelBatch_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *activityCronServiceClient) ProcessAchievementRewardBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(CronBatchResponse) @@ -828,6 +840,7 @@ func (c *activityCronServiceClient) ProcessAgencyOpeningSettlementBatch(ctx cont type ActivityCronServiceServer interface { ProcessMessageFanoutBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) ProcessLevelRewardBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) + ProcessTemporaryLevelBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) ProcessAchievementRewardBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) ProcessRoomTurnoverRewardSettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) ProcessWeeklyStarSettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) @@ -849,6 +862,9 @@ func (UnimplementedActivityCronServiceServer) ProcessMessageFanoutBatch(context. func (UnimplementedActivityCronServiceServer) ProcessLevelRewardBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ProcessLevelRewardBatch not implemented") } +func (UnimplementedActivityCronServiceServer) ProcessTemporaryLevelBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ProcessTemporaryLevelBatch not implemented") +} func (UnimplementedActivityCronServiceServer) ProcessAchievementRewardBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ProcessAchievementRewardBatch not implemented") } @@ -921,6 +937,24 @@ func _ActivityCronService_ProcessLevelRewardBatch_Handler(srv interface{}, ctx c return interceptor(ctx, in, info, handler) } +func _ActivityCronService_ProcessTemporaryLevelBatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CronBatchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ActivityCronServiceServer).ProcessTemporaryLevelBatch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ActivityCronService_ProcessTemporaryLevelBatch_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ActivityCronServiceServer).ProcessTemporaryLevelBatch(ctx, req.(*CronBatchRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _ActivityCronService_ProcessAchievementRewardBatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CronBatchRequest) if err := dec(in); err != nil { @@ -1026,6 +1060,10 @@ var ActivityCronService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ProcessLevelRewardBatch", Handler: _ActivityCronService_ProcessLevelRewardBatch_Handler, }, + { + MethodName: "ProcessTemporaryLevelBatch", + Handler: _ActivityCronService_ProcessTemporaryLevelBatch_Handler, + }, { MethodName: "ProcessAchievementRewardBatch", Handler: _ActivityCronService_ProcessAchievementRewardBatch_Handler, @@ -5846,10 +5884,12 @@ var AdminSevenDayCheckInService_ServiceDesc = grpc.ServiceDesc{ } const ( - AdminGrowthLevelService_ListLevelConfig_FullMethodName = "/hyapp.activity.v1.AdminGrowthLevelService/ListLevelConfig" - AdminGrowthLevelService_UpsertLevelTrack_FullMethodName = "/hyapp.activity.v1.AdminGrowthLevelService/UpsertLevelTrack" - AdminGrowthLevelService_UpsertLevelRule_FullMethodName = "/hyapp.activity.v1.AdminGrowthLevelService/UpsertLevelRule" - AdminGrowthLevelService_UpsertLevelTier_FullMethodName = "/hyapp.activity.v1.AdminGrowthLevelService/UpsertLevelTier" + AdminGrowthLevelService_ListLevelConfig_FullMethodName = "/hyapp.activity.v1.AdminGrowthLevelService/ListLevelConfig" + AdminGrowthLevelService_UpsertLevelTrack_FullMethodName = "/hyapp.activity.v1.AdminGrowthLevelService/UpsertLevelTrack" + AdminGrowthLevelService_UpsertLevelRule_FullMethodName = "/hyapp.activity.v1.AdminGrowthLevelService/UpsertLevelRule" + AdminGrowthLevelService_UpsertLevelTier_FullMethodName = "/hyapp.activity.v1.AdminGrowthLevelService/UpsertLevelTier" + AdminGrowthLevelService_BatchGetUserLevelAdminProfiles_FullMethodName = "/hyapp.activity.v1.AdminGrowthLevelService/BatchGetUserLevelAdminProfiles" + AdminGrowthLevelService_AdjustTemporaryUserLevels_FullMethodName = "/hyapp.activity.v1.AdminGrowthLevelService/AdjustTemporaryUserLevels" ) // AdminGrowthLevelServiceClient is the client API for AdminGrowthLevelService service. @@ -5862,6 +5902,8 @@ type AdminGrowthLevelServiceClient interface { UpsertLevelTrack(ctx context.Context, in *UpsertLevelTrackRequest, opts ...grpc.CallOption) (*UpsertLevelTrackResponse, error) UpsertLevelRule(ctx context.Context, in *UpsertLevelRuleRequest, opts ...grpc.CallOption) (*UpsertLevelRuleResponse, error) UpsertLevelTier(ctx context.Context, in *UpsertLevelTierRequest, opts ...grpc.CallOption) (*UpsertLevelTierResponse, error) + BatchGetUserLevelAdminProfiles(ctx context.Context, in *BatchGetUserLevelAdminProfilesRequest, opts ...grpc.CallOption) (*BatchGetUserLevelAdminProfilesResponse, error) + AdjustTemporaryUserLevels(ctx context.Context, in *AdjustTemporaryUserLevelsRequest, opts ...grpc.CallOption) (*AdjustTemporaryUserLevelsResponse, error) } type adminGrowthLevelServiceClient struct { @@ -5912,6 +5954,26 @@ func (c *adminGrowthLevelServiceClient) UpsertLevelTier(ctx context.Context, in return out, nil } +func (c *adminGrowthLevelServiceClient) BatchGetUserLevelAdminProfiles(ctx context.Context, in *BatchGetUserLevelAdminProfilesRequest, opts ...grpc.CallOption) (*BatchGetUserLevelAdminProfilesResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(BatchGetUserLevelAdminProfilesResponse) + err := c.cc.Invoke(ctx, AdminGrowthLevelService_BatchGetUserLevelAdminProfiles_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminGrowthLevelServiceClient) AdjustTemporaryUserLevels(ctx context.Context, in *AdjustTemporaryUserLevelsRequest, opts ...grpc.CallOption) (*AdjustTemporaryUserLevelsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(AdjustTemporaryUserLevelsResponse) + err := c.cc.Invoke(ctx, AdminGrowthLevelService_AdjustTemporaryUserLevels_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // AdminGrowthLevelServiceServer is the server API for AdminGrowthLevelService service. // All implementations must embed UnimplementedAdminGrowthLevelServiceServer // for forward compatibility. @@ -5922,6 +5984,8 @@ type AdminGrowthLevelServiceServer interface { UpsertLevelTrack(context.Context, *UpsertLevelTrackRequest) (*UpsertLevelTrackResponse, error) UpsertLevelRule(context.Context, *UpsertLevelRuleRequest) (*UpsertLevelRuleResponse, error) UpsertLevelTier(context.Context, *UpsertLevelTierRequest) (*UpsertLevelTierResponse, error) + BatchGetUserLevelAdminProfiles(context.Context, *BatchGetUserLevelAdminProfilesRequest) (*BatchGetUserLevelAdminProfilesResponse, error) + AdjustTemporaryUserLevels(context.Context, *AdjustTemporaryUserLevelsRequest) (*AdjustTemporaryUserLevelsResponse, error) mustEmbedUnimplementedAdminGrowthLevelServiceServer() } @@ -5944,6 +6008,12 @@ func (UnimplementedAdminGrowthLevelServiceServer) UpsertLevelRule(context.Contex func (UnimplementedAdminGrowthLevelServiceServer) UpsertLevelTier(context.Context, *UpsertLevelTierRequest) (*UpsertLevelTierResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpsertLevelTier not implemented") } +func (UnimplementedAdminGrowthLevelServiceServer) BatchGetUserLevelAdminProfiles(context.Context, *BatchGetUserLevelAdminProfilesRequest) (*BatchGetUserLevelAdminProfilesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method BatchGetUserLevelAdminProfiles not implemented") +} +func (UnimplementedAdminGrowthLevelServiceServer) AdjustTemporaryUserLevels(context.Context, *AdjustTemporaryUserLevelsRequest) (*AdjustTemporaryUserLevelsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AdjustTemporaryUserLevels not implemented") +} func (UnimplementedAdminGrowthLevelServiceServer) mustEmbedUnimplementedAdminGrowthLevelServiceServer() { } func (UnimplementedAdminGrowthLevelServiceServer) testEmbeddedByValue() {} @@ -6038,6 +6108,42 @@ func _AdminGrowthLevelService_UpsertLevelTier_Handler(srv interface{}, ctx conte return interceptor(ctx, in, info, handler) } +func _AdminGrowthLevelService_BatchGetUserLevelAdminProfiles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BatchGetUserLevelAdminProfilesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminGrowthLevelServiceServer).BatchGetUserLevelAdminProfiles(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminGrowthLevelService_BatchGetUserLevelAdminProfiles_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminGrowthLevelServiceServer).BatchGetUserLevelAdminProfiles(ctx, req.(*BatchGetUserLevelAdminProfilesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminGrowthLevelService_AdjustTemporaryUserLevels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AdjustTemporaryUserLevelsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminGrowthLevelServiceServer).AdjustTemporaryUserLevels(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminGrowthLevelService_AdjustTemporaryUserLevels_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminGrowthLevelServiceServer).AdjustTemporaryUserLevels(ctx, req.(*AdjustTemporaryUserLevelsRequest)) + } + return interceptor(ctx, in, info, handler) +} + // AdminGrowthLevelService_ServiceDesc is the grpc.ServiceDesc for AdminGrowthLevelService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -6061,6 +6167,14 @@ var AdminGrowthLevelService_ServiceDesc = grpc.ServiceDesc{ MethodName: "UpsertLevelTier", Handler: _AdminGrowthLevelService_UpsertLevelTier_Handler, }, + { + MethodName: "BatchGetUserLevelAdminProfiles", + Handler: _AdminGrowthLevelService_BatchGetUserLevelAdminProfiles_Handler, + }, + { + MethodName: "AdjustTemporaryUserLevels", + Handler: _AdminGrowthLevelService_AdjustTemporaryUserLevels_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "proto/activity/v1/activity.proto", diff --git a/api/proto/events/room/v1/events.pb.go b/api/proto/events/room/v1/events.pb.go index 6aa66187..ff4bf3cd 100644 --- a/api/proto/events/room/v1/events.pb.go +++ b/api/proto/events/room/v1/events.pb.go @@ -479,6 +479,11 @@ type RoomUserJoined struct { Avatar string `protobuf:"bytes,9,opt,name=avatar,proto3" json:"avatar,omitempty"` DisplayUserId string `protobuf:"bytes,10,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"` PrettyDisplayUserId string `protobuf:"bytes,11,opt,name=pretty_display_user_id,json=prettyDisplayUserId,proto3" json:"pretty_display_user_id,omitempty"` + // VIP 字段来自同一次 GetMyVip effective state,首次进房 outbox 与重复进房 direct IM 必须保持同一语义。 + VipProgramType string `protobuf:"bytes,12,opt,name=vip_program_type,json=vipProgramType,proto3" json:"vip_program_type,omitempty"` + EffectiveVipLevel int32 `protobuf:"varint,13,opt,name=effective_vip_level,json=effectiveVipLevel,proto3" json:"effective_vip_level,omitempty"` + EffectiveVipName string `protobuf:"bytes,14,opt,name=effective_vip_name,json=effectiveVipName,proto3" json:"effective_vip_name,omitempty"` + RoomEntryNoticeEnabled bool `protobuf:"varint,15,opt,name=room_entry_notice_enabled,json=roomEntryNoticeEnabled,proto3" json:"room_entry_notice_enabled,omitempty"` } func (x *RoomUserJoined) Reset() { @@ -588,6 +593,34 @@ func (x *RoomUserJoined) GetPrettyDisplayUserId() string { return "" } +func (x *RoomUserJoined) GetVipProgramType() string { + if x != nil { + return x.VipProgramType + } + return "" +} + +func (x *RoomUserJoined) GetEffectiveVipLevel() int32 { + if x != nil { + return x.EffectiveVipLevel + } + return 0 +} + +func (x *RoomUserJoined) GetEffectiveVipName() string { + if x != nil { + return x.EffectiveVipName + } + return "" +} + +func (x *RoomUserJoined) GetRoomEntryNoticeEnabled() bool { + if x != nil { + return x.RoomEntryNoticeEnabled + } + return false +} + // RoomUserLeft 表达用户离房成功。 type RoomUserLeft struct { state protoimpl.MessageState @@ -2996,7 +3029,7 @@ var file_proto_events_room_v1_events_proto_rawDesc = []byte{ 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, 0xa6, 0x03, 0x0a, 0x0e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, + 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xe9, 0x04, 0x0a, 0x0e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x65, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, @@ -3022,470 +3055,482 @@ var file_proto_events_room_v1_events_proto_rawDesc = []byte{ 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, 0x0b, 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, - 0x27, 0x0a, 0x0c, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x66, 0x74, 0x12, - 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x48, 0x0a, 0x0a, 0x52, 0x6f, 0x6f, 0x6d, - 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, - 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 0x22, 0x9d, 0x05, 0x0a, 0x0e, 0x52, 0x6f, 0x6f, 0x6d, 0x4d, 0x69, 0x63, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, - 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x1b, 0x0a, 0x09, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x73, 0x65, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x08, 0x66, 0x72, 0x6f, 0x6d, 0x53, 0x65, 0x61, 0x74, 0x12, 0x17, 0x0a, 0x07, - 0x74, 0x6f, 0x5f, 0x73, 0x65, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x74, - 0x6f, 0x53, 0x65, 0x61, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, - 0x0e, 0x6d, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x69, 0x63, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x12, 0x2e, 0x0a, 0x13, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x64, 0x65, 0x61, 0x64, - 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x73, - 0x12, 0x31, 0x0a, 0x15, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x12, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, - 0x65, 0x4d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x63, 0x5f, 0x6d, 0x75, 0x74, 0x65, 0x64, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x69, 0x63, 0x4d, 0x75, 0x74, 0x65, 0x64, - 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x61, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x67, 0x69, 0x66, 0x74, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x47, 0x69, 0x66, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a, - 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x69, - 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x5f, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 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, 0x10, 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, 0x40, 0x0a, 0x1d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x74, 0x74, - 0x79, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, - 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, - 0x49, 0x64, 0x22, 0x68, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x4d, 0x69, 0x63, 0x53, 0x65, 0x61, - 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, - 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, - 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x73, - 0x65, 0x61, 0x74, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x65, - 0x61, 0x74, 0x4e, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x22, 0x56, 0x0a, 0x16, - 0x52, 0x6f, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, - 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x22, 0x7d, 0x0a, 0x13, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, - 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, - 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x22, 0x76, 0x0a, 0x10, 0x52, 0x6f, 0x6f, 0x6d, 0x41, 0x64, 0x6d, 0x69, 0x6e, - 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, - 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, - 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x6f, 0x0a, 0x0d, 0x52, - 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, - 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, - 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x22, 0x5a, 0x0a, 0x0e, - 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x4b, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x22, + 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x28, 0x0a, 0x10, 0x76, 0x69, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x76, 0x69, 0x70, 0x50, 0x72, + 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x66, 0x66, + 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x69, 0x70, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, + 0x65, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x65, 0x66, 0x66, + 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x69, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x56, 0x69, 0x70, 0x4e, 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, 0x0f, 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, 0x27, 0x0a, 0x0c, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x65, + 0x66, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x48, 0x0a, 0x0a, 0x52, + 0x6f, 0x6f, 0x6d, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, + 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, + 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x9d, 0x05, 0x0a, 0x0e, 0x52, 0x6f, 0x6f, 0x6d, 0x4d, 0x69, + 0x63, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, + 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x73, 0x65, 0x61, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x66, 0x72, 0x6f, 0x6d, 0x53, 0x65, 0x61, 0x74, 0x12, + 0x17, 0x0a, 0x07, 0x74, 0x6f, 0x5f, 0x73, 0x65, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x06, 0x74, 0x6f, 0x53, 0x65, 0x61, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x69, 0x63, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, + 0x68, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, + 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x64, + 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x11, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, + 0x65, 0x4d, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x12, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x63, 0x5f, 0x6d, 0x75, + 0x74, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x69, 0x63, 0x4d, 0x75, + 0x74, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x61, 0x74, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x67, + 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x47, 0x69, 0x66, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x69, 0x63, 0x6b, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x4e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x5f, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 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, 0x10, 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, 0x40, 0x0a, 0x1d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x70, 0x72, + 0x65, 0x74, 0x74, 0x79, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x50, 0x72, 0x65, 0x74, 0x74, 0x79, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x68, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x4d, 0x69, 0x63, + 0x53, 0x65, 0x61, 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, + 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, + 0x0a, 0x07, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x06, 0x73, 0x65, 0x61, 0x74, 0x4e, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x22, + 0x56, 0x0a, 0x16, 0x52, 0x6f, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, + 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x18, 0x0a, + 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x7d, 0x0a, 0x13, 0x52, 0x6f, 0x6f, 0x6d, 0x50, + 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x5c, 0x0a, 0x10, 0x52, 0x6f, 0x6f, 0x6d, - 0x55, 0x73, 0x65, 0x72, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, - 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, + 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, + 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x76, 0x0a, 0x10, 0x52, 0x6f, 0x6f, 0x6d, 0x41, 0x64, + 0x6d, 0x69, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, + 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, + 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x6f, + 0x0a, 0x0d, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x65, 0x64, 0x12, + 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x75, 0x74, + 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x22, + 0x5a, 0x0a, 0x0e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x4b, 0x69, 0x63, 0x6b, 0x65, + 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x5c, 0x0a, 0x10, 0x52, + 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x12, + 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xf1, 0x09, 0x0a, 0x0c, 0x52, 0x6f, + 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x53, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, + 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xf1, 0x09, 0x0a, 0x0c, 0x52, 0x6f, 0x6f, 0x6d, 0x47, - 0x69, 0x66, 0x74, 0x53, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, - 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, - 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, - 0x67, 0x69, 0x66, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x67, - 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x09, 0x67, 0x69, 0x66, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x62, 0x69, - 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x5f, 0x69, 0x64, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, - 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, - 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, - 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, - 0x64, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, - 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x09, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, - 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, - 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x67, 0x69, 0x66, 0x74, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0d, 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, 0x0e, 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, 0x0f, 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, 0x10, 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, 0x11, - 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, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x5f, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x47, 0x69, 0x66, 0x74, 0x56, 0x61, 0x6c, - 0x75, 0x65, 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, 0x22, - 0x0a, 0x0d, 0x69, 0x73, 0x5f, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x18, - 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x47, 0x69, - 0x66, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x79, 0x6e, 0x74, 0x68, 0x65, 0x74, 0x69, 0x63, 0x5f, - 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x18, 0x15, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x12, 0x73, 0x79, 0x6e, 0x74, 0x68, 0x65, 0x74, 0x69, 0x63, 0x4c, 0x75, 0x63, 0x6b, 0x79, - 0x47, 0x69, 0x66, 0x74, 0x12, 0x2f, 0x0a, 0x14, 0x72, 0x65, 0x61, 0x6c, 0x5f, 0x72, 0x6f, 0x6f, - 0x6d, 0x5f, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x18, 0x16, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x11, 0x72, 0x65, 0x61, 0x6c, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, - 0x74, 0x47, 0x69, 0x66, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x17, 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, 0x18, 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, 0x19, 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, 0x1a, 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, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x6e, - 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x1b, 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, 0x1c, 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, 0x1d, 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, + 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, 0x64, 0x12, + 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, + 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, + 0x12, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x62, 0x69, 0x6c, 0x6c, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x76, + 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, + 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, + 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x1d, + 0x0a, 0x0a, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, 0x12, 0x1b, 0x0a, + 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x67, 0x69, + 0x66, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0d, 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, 0x0e, 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, 0x0f, 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, 0x10, 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, 0x11, 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, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x12, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x47, 0x69, 0x66, 0x74, + 0x56, 0x61, 0x6c, 0x75, 0x65, 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, 0x22, 0x0a, 0x0d, 0x69, 0x73, 0x5f, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x67, 0x69, + 0x66, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x52, 0x6f, 0x62, 0x6f, + 0x74, 0x47, 0x69, 0x66, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x79, 0x6e, 0x74, 0x68, 0x65, 0x74, + 0x69, 0x63, 0x5f, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x18, 0x15, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x12, 0x73, 0x79, 0x6e, 0x74, 0x68, 0x65, 0x74, 0x69, 0x63, 0x4c, 0x75, + 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x12, 0x2f, 0x0a, 0x14, 0x72, 0x65, 0x61, 0x6c, 0x5f, + 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x18, + 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x72, 0x65, 0x61, 0x6c, 0x52, 0x6f, 0x6f, 0x6d, 0x52, + 0x6f, 0x62, 0x6f, 0x74, 0x47, 0x69, 0x66, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x6e, 0x64, + 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x17, 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, 0x18, 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, 0x19, 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, 0x1e, 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, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0xdc, 0x04, 0x0a, 0x18, 0x52, - 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x75, 0x63, 0x6b, - 0x79, 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, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x96, 0x04, 0x0a, 0x13, 0x52, 0x6f, - 0x6f, 0x6d, 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, 0x4d, 0x0a, 0x0a, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x67, 0x69, 0x66, - 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x75, 0x63, 0x6b, - 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x09, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, - 0x66, 0x74, 0x22, 0x89, 0x07, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x42, - 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1f, - 0x0a, 0x0b, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 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, 0x03, 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, 0x04, - 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, 0x05, 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, 0x06, 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, 0x07, 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, 0x08, 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, 0x09, 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, 0x0a, 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, 0x0b, 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, 0x0c, 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, 0x0d, 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, 0x0e, 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, 0x0f, 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, 0x10, 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, 0x11, 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, - 0x12, 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, 0x13, 0x20, 0x03, 0x28, 0x03, 0x52, - 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x43, - 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x72, - 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 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, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, - 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x16, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, - 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x80, - 0x04, 0x0a, 0x17, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x4c, 0x75, 0x63, 0x6b, - 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x6e, 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, 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, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x1a, 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, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, + 0x72, 0x5f, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x1b, 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, 0x1c, 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, 0x1d, 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, 0x1e, 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, 0x21, 0x0a, 0x0c, 0x64, 0x69, + 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0xdc, 0x04, + 0x0a, 0x18, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4c, + 0x75, 0x63, 0x6b, 0x79, 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, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x96, 0x04, 0x0a, + 0x13, 0x52, 0x6f, 0x6f, 0x6d, 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, 0x4d, 0x0a, 0x0a, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, + 0x67, 0x69, 0x66, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4c, + 0x75, 0x63, 0x6b, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x09, 0x6c, 0x75, 0x63, 0x6b, + 0x79, 0x47, 0x69, 0x66, 0x74, 0x22, 0x89, 0x07, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x69, + 0x66, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x73, + 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 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, 0x03, 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, 0x04, 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, 0x05, 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, 0x06, 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, 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, - 0x25, 0x0a, 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x70, 0x70, - 0x6d, 0x18, 0x08, 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, 0x09, 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, 0x0a, 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, 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, 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, 0x69, 0x73, 0x5f, 0x72, - 0x6f, 0x62, 0x6f, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x52, 0x6f, - 0x62, 0x6f, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x79, 0x6e, 0x74, 0x68, 0x65, 0x74, 0x69, 0x63, - 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x79, 0x6e, 0x74, 0x68, 0x65, 0x74, 0x69, - 0x63, 0x22, 0x4a, 0x0a, 0x0f, 0x52, 0x6f, 0x6f, 0x6d, 0x48, 0x65, 0x61, 0x74, 0x43, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x74, 0x22, 0x5f, 0x0a, - 0x0f, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x61, 0x6e, 0x6b, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, - 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, - 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x12, - 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x94, - 0x02, 0x0a, 0x15, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x77, - 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x77, 0x61, - 0x72, 0x64, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x74, 0x65, - 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x77, 0x61, - 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, - 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x63, 0x6f, 0x6e, 0x5f, - 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x63, 0x6f, 0x6e, 0x55, - 0x72, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xeb, 0x03, 0x0a, 0x15, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, - 0x63, 0x6b, 0x65, 0x74, 0x46, 0x75, 0x65, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, - 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, - 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, - 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x65, 0x6c, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x61, 0x64, 0x64, 0x65, 0x64, 0x46, 0x75, 0x65, - 0x6c, 0x12, 0x30, 0x0a, 0x14, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, - 0x64, 0x64, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x12, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x65, 0x64, 0x46, - 0x75, 0x65, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x5f, - 0x66, 0x75, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x76, 0x65, 0x72, - 0x66, 0x6c, 0x6f, 0x77, 0x46, 0x75, 0x65, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x75, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x75, 0x65, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x66, - 0x75, 0x65, 0x6c, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0d, 0x66, 0x75, 0x65, 0x6c, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, - 0x6c, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x72, 0x65, - 0x73, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x09, 0x72, 0x65, 0x73, 0x65, 0x74, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, - 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, - 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, - 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x67, - 0x69, 0x66, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, - 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0e, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x22, 0x82, 0x04, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, - 0x65, 0x74, 0x49, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, - 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x21, 0x0a, 0x0c, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x75, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x75, 0x65, 0x6c, 0x12, - 0x25, 0x0a, 0x0e, 0x66, 0x75, 0x65, 0x6c, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x66, 0x75, 0x65, 0x6c, 0x54, 0x68, 0x72, - 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, - 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x69, - 0x67, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x20, 0x0a, 0x0c, 0x6c, 0x61, - 0x75, 0x6e, 0x63, 0x68, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0a, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x27, 0x0a, 0x0f, - 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, - 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, - 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 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, 0x08, 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, 0x09, 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, 0x0a, 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, 0x0b, 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, 0x0c, 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, 0x0d, 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, 0x0e, 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, 0x0f, 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, 0x10, 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, 0x11, 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, 0x12, 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, 0x13, 0x20, 0x03, + 0x28, 0x03, 0x52, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, + 0x73, 0x12, 0x43, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x14, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 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, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, + 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x16, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x6f, 0x70, 0x31, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x70, 0x31, 0x55, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x72, 0x5f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x67, - 0x6e, 0x69, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x72, 0x6f, - 0x6f, 0x6d, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x72, 0x6f, 0x6f, 0x6d, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x49, 0x64, 0x12, 0x28, - 0x0a, 0x10, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x75, - 0x72, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, - 0x43, 0x6f, 0x76, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x1e, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, - 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x72, - 0x65, 0x73, 0x65, 0x74, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xe6, 0x02, 0x0a, 0x12, 0x52, 0x6f, 0x6f, - 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x64, 0x12, - 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, - 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, - 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x4c, 0x65, 0x76, 0x65, - 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x61, 0x75, 0x6e, 0x63, - 0x68, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x74, - 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x72, 0x65, - 0x73, 0x65, 0x74, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x6f, 0x70, 0x31, 0x5f, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, - 0x6f, 0x70, 0x31, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x69, 0x67, 0x6e, - 0x69, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0d, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x27, 0x0a, 0x10, 0x69, 0x6e, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x52, - 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, - 0x77, 0x61, 0x72, 0x64, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x77, - 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x07, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, - 0x73, 0x22, 0x93, 0x01, 0x0a, 0x17, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, - 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, - 0x09, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, - 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, - 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x07, - 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x42, 0x33, 0x5a, 0x31, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x72, 0x6f, 0x6f, 0x6d, 0x2f, 0x76, 0x31, 0x3b, - 0x72, 0x6f, 0x6f, 0x6d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x22, 0x80, 0x04, 0x0a, 0x17, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x4c, + 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, 0x6e, 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, 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, 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, 0x25, 0x0a, 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, + 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x08, 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, 0x09, + 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, + 0x0a, 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, 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, + 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, 0x69, + 0x73, 0x5f, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, + 0x73, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x79, 0x6e, 0x74, 0x68, 0x65, + 0x74, 0x69, 0x63, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x79, 0x6e, 0x74, 0x68, + 0x65, 0x74, 0x69, 0x63, 0x22, 0x4a, 0x0a, 0x0f, 0x52, 0x6f, 0x6f, 0x6d, 0x48, 0x65, 0x61, 0x74, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x6c, 0x74, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x21, 0x0a, + 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x65, 0x61, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x74, + 0x22, 0x5f, 0x0a, 0x0f, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x61, 0x6e, 0x6b, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, + 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x63, 0x6f, + 0x72, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0x94, 0x02, 0x0a, 0x15, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, + 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x72, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x17, 0x0a, 0x07, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, + 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, + 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x63, + 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x63, + 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x49, 0x64, + 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xeb, 0x03, 0x0a, 0x15, 0x52, 0x6f, 0x6f, + 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x46, 0x75, 0x65, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, + 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, + 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x66, + 0x75, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x61, 0x64, 0x64, 0x65, 0x64, + 0x46, 0x75, 0x65, 0x6c, 0x12, 0x30, 0x0a, 0x14, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, + 0x65, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x12, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, + 0x65, 0x64, 0x46, 0x75, 0x65, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, + 0x6f, 0x77, 0x5f, 0x66, 0x75, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, + 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x46, 0x75, 0x65, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x63, + 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x75, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x75, 0x65, 0x6c, 0x12, 0x25, + 0x0a, 0x0e, 0x66, 0x75, 0x65, 0x6c, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x66, 0x75, 0x65, 0x6c, 0x54, 0x68, 0x72, 0x65, + 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x0a, + 0x0b, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x09, 0x72, 0x65, 0x73, 0x65, 0x74, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x24, 0x0a, + 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, + 0x67, 0x69, 0x66, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, + 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x82, 0x04, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x52, + 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, + 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, + 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, + 0x21, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x75, 0x65, 0x6c, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x75, + 0x65, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x75, 0x65, 0x6c, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, + 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x66, 0x75, 0x65, 0x6c, + 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x69, 0x67, 0x6e, + 0x69, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x20, 0x0a, + 0x0c, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x41, 0x74, 0x4d, 0x73, 0x12, + 0x27, 0x0a, 0x0f, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x63, 0x6f, + 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, + 0x61, 0x73, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, + 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x6f, 0x70, 0x31, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x70, 0x31, + 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, + 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0d, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, + 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x22, 0x0a, + 0x0d, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x6f, 0x6f, 0x6d, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x49, + 0x64, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x63, + 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x1e, 0x0a, 0x0b, 0x72, + 0x65, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x09, 0x72, 0x65, 0x73, 0x65, 0x74, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xe6, 0x02, 0x0a, 0x12, + 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, + 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, + 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, + 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x6c, 0x65, + 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x61, + 0x75, 0x6e, 0x63, 0x68, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x72, 0x65, + 0x73, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x09, 0x72, 0x65, 0x73, 0x65, 0x74, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x6f, + 0x70, 0x31, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0a, 0x74, 0x6f, 0x70, 0x31, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, + 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x72, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x10, 0x69, 0x6e, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0d, + 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x45, 0x0a, + 0x07, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, + 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x07, 0x72, 0x65, 0x77, + 0x61, 0x72, 0x64, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x17, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, + 0x6b, 0x65, 0x74, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, + 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, + 0x76, 0x65, 0x6c, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x73, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, + 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, + 0x74, 0x52, 0x07, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x42, 0x33, 0x5a, 0x31, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x72, 0x6f, 0x6f, 0x6d, 0x2f, + 0x76, 0x31, 0x3b, 0x72, 0x6f, 0x6f, 0x6d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x76, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/proto/events/room/v1/events.proto b/api/proto/events/room/v1/events.proto index a58e1fc0..33c56ebd 100644 --- a/api/proto/events/room/v1/events.proto +++ b/api/proto/events/room/v1/events.proto @@ -72,6 +72,11 @@ message RoomUserJoined { string avatar = 9; string display_user_id = 10; string pretty_display_user_id = 11; + // VIP 字段来自同一次 GetMyVip effective state,首次进房 outbox 与重复进房 direct IM 必须保持同一语义。 + string vip_program_type = 12; + int32 effective_vip_level = 13; + string effective_vip_name = 14; + bool room_entry_notice_enabled = 15; } // RoomUserLeft 表达用户离房成功。 diff --git a/api/proto/room/v1/room.pb.go b/api/proto/room/v1/room.pb.go index ad8868c7..5a748eab 100644 --- a/api/proto/room/v1/room.pb.go +++ b/api/proto/room/v1/room.pb.go @@ -5865,20 +5865,92 @@ func (x *JoinRoomRequest) GetResponseMode() string { return "" } +// 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"` +} + +func (x *RoomEffectiveVipSnapshot) Reset() { + *x = RoomEffectiveVipSnapshot{} + mi := &file_proto_room_v1_room_proto_msgTypes[69] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoomEffectiveVipSnapshot) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoomEffectiveVipSnapshot) ProtoMessage() {} + +func (x *RoomEffectiveVipSnapshot) ProtoReflect() protoreflect.Message { + mi := &file_proto_room_v1_room_proto_msgTypes[69] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RoomEffectiveVipSnapshot.ProtoReflect.Descriptor instead. +func (*RoomEffectiveVipSnapshot) Descriptor() ([]byte, []int) { + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{69} +} + +func (x *RoomEffectiveVipSnapshot) GetProgramType() string { + if x != nil { + return x.ProgramType + } + return "" +} + +func (x *RoomEffectiveVipSnapshot) GetLevel() int32 { + if x != nil { + return x.Level + } + return 0 +} + +func (x *RoomEffectiveVipSnapshot) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *RoomEffectiveVipSnapshot) GetRoomEntryNoticeEnabled() bool { + if x != nil { + return x.RoomEntryNoticeEnabled + } + return false +} + // JoinRoomResponse 返回加入后的房间快照。 type JoinRoomResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - User *RoomUser `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` + 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"` } func (x *JoinRoomResponse) Reset() { *x = JoinRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[69] + mi := &file_proto_room_v1_room_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5890,7 +5962,7 @@ func (x *JoinRoomResponse) String() string { func (*JoinRoomResponse) ProtoMessage() {} func (x *JoinRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[69] + mi := &file_proto_room_v1_room_proto_msgTypes[70] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5903,7 +5975,7 @@ func (x *JoinRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use JoinRoomResponse.ProtoReflect.Descriptor instead. func (*JoinRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{69} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{70} } func (x *JoinRoomResponse) GetResult() *CommandResult { @@ -5927,6 +5999,13 @@ func (x *JoinRoomResponse) GetRoom() *RoomSnapshot { return nil } +func (x *JoinRoomResponse) GetEffectiveVip() *RoomEffectiveVipSnapshot { + if x != nil { + return x.EffectiveVip + } + return nil +} + // RoomHeartbeatRequest 显式刷新已经存在的房间业务 presence。 // 它不能替代 JoinRoom;用户不在房间时必须拒绝,避免心跳把已离开的用户重新加入房间。 type RoomHeartbeatRequest struct { @@ -5939,7 +6018,7 @@ type RoomHeartbeatRequest struct { func (x *RoomHeartbeatRequest) Reset() { *x = RoomHeartbeatRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[70] + mi := &file_proto_room_v1_room_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5951,7 +6030,7 @@ func (x *RoomHeartbeatRequest) String() string { func (*RoomHeartbeatRequest) ProtoMessage() {} func (x *RoomHeartbeatRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[70] + mi := &file_proto_room_v1_room_proto_msgTypes[71] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5964,7 +6043,7 @@ func (x *RoomHeartbeatRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomHeartbeatRequest.ProtoReflect.Descriptor instead. func (*RoomHeartbeatRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{70} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{71} } func (x *RoomHeartbeatRequest) GetMeta() *RequestMeta { @@ -5987,7 +6066,7 @@ type RoomHeartbeatResponse struct { func (x *RoomHeartbeatResponse) Reset() { *x = RoomHeartbeatResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[71] + mi := &file_proto_room_v1_room_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5999,7 +6078,7 @@ func (x *RoomHeartbeatResponse) String() string { func (*RoomHeartbeatResponse) ProtoMessage() {} func (x *RoomHeartbeatResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[71] + mi := &file_proto_room_v1_room_proto_msgTypes[72] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6012,7 +6091,7 @@ func (x *RoomHeartbeatResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomHeartbeatResponse.ProtoReflect.Descriptor instead. func (*RoomHeartbeatResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{71} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{72} } func (x *RoomHeartbeatResponse) GetResult() *CommandResult { @@ -6047,7 +6126,7 @@ type LeaveRoomRequest struct { func (x *LeaveRoomRequest) Reset() { *x = LeaveRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[72] + mi := &file_proto_room_v1_room_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6059,7 +6138,7 @@ func (x *LeaveRoomRequest) String() string { func (*LeaveRoomRequest) ProtoMessage() {} func (x *LeaveRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[72] + mi := &file_proto_room_v1_room_proto_msgTypes[73] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6072,7 +6151,7 @@ func (x *LeaveRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use LeaveRoomRequest.ProtoReflect.Descriptor instead. func (*LeaveRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{72} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{73} } func (x *LeaveRoomRequest) GetMeta() *RequestMeta { @@ -6094,7 +6173,7 @@ type LeaveRoomResponse struct { func (x *LeaveRoomResponse) Reset() { *x = LeaveRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[73] + mi := &file_proto_room_v1_room_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6106,7 +6185,7 @@ func (x *LeaveRoomResponse) String() string { func (*LeaveRoomResponse) ProtoMessage() {} func (x *LeaveRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[73] + mi := &file_proto_room_v1_room_proto_msgTypes[74] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6119,7 +6198,7 @@ func (x *LeaveRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use LeaveRoomResponse.ProtoReflect.Descriptor instead. func (*LeaveRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{73} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{74} } func (x *LeaveRoomResponse) GetResult() *CommandResult { @@ -6148,7 +6227,7 @@ type CloseRoomRequest struct { func (x *CloseRoomRequest) Reset() { *x = CloseRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[74] + mi := &file_proto_room_v1_room_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6160,7 +6239,7 @@ func (x *CloseRoomRequest) String() string { func (*CloseRoomRequest) ProtoMessage() {} func (x *CloseRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[74] + mi := &file_proto_room_v1_room_proto_msgTypes[75] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6173,7 +6252,7 @@ func (x *CloseRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CloseRoomRequest.ProtoReflect.Descriptor instead. func (*CloseRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{74} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{75} } func (x *CloseRoomRequest) GetMeta() *RequestMeta { @@ -6202,7 +6281,7 @@ type CloseRoomResponse struct { func (x *CloseRoomResponse) Reset() { *x = CloseRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[75] + mi := &file_proto_room_v1_room_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6214,7 +6293,7 @@ func (x *CloseRoomResponse) String() string { func (*CloseRoomResponse) ProtoMessage() {} func (x *CloseRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[75] + mi := &file_proto_room_v1_room_proto_msgTypes[76] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6227,7 +6306,7 @@ func (x *CloseRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CloseRoomResponse.ProtoReflect.Descriptor instead. func (*CloseRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{75} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{76} } func (x *CloseRoomResponse) GetResult() *CommandResult { @@ -6273,7 +6352,7 @@ type AdminRoomListItem struct { func (x *AdminRoomListItem) Reset() { *x = AdminRoomListItem{} - mi := &file_proto_room_v1_room_proto_msgTypes[76] + mi := &file_proto_room_v1_room_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6285,7 +6364,7 @@ func (x *AdminRoomListItem) String() string { func (*AdminRoomListItem) ProtoMessage() {} func (x *AdminRoomListItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[76] + mi := &file_proto_room_v1_room_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6298,7 +6377,7 @@ func (x *AdminRoomListItem) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminRoomListItem.ProtoReflect.Descriptor instead. func (*AdminRoomListItem) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{76} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{77} } func (x *AdminRoomListItem) GetRoomId() string { @@ -6452,7 +6531,7 @@ type AdminListRoomsRequest struct { func (x *AdminListRoomsRequest) Reset() { *x = AdminListRoomsRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[77] + mi := &file_proto_room_v1_room_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6464,7 +6543,7 @@ func (x *AdminListRoomsRequest) String() string { func (*AdminListRoomsRequest) ProtoMessage() {} func (x *AdminListRoomsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[77] + mi := &file_proto_room_v1_room_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6477,7 +6556,7 @@ func (x *AdminListRoomsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminListRoomsRequest.ProtoReflect.Descriptor instead. func (*AdminListRoomsRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{77} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{78} } func (x *AdminListRoomsRequest) GetMeta() *RequestMeta { @@ -6555,7 +6634,7 @@ type AdminListRoomsResponse struct { func (x *AdminListRoomsResponse) Reset() { *x = AdminListRoomsResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[78] + mi := &file_proto_room_v1_room_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6567,7 +6646,7 @@ func (x *AdminListRoomsResponse) String() string { func (*AdminListRoomsResponse) ProtoMessage() {} func (x *AdminListRoomsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[78] + mi := &file_proto_room_v1_room_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6580,7 +6659,7 @@ func (x *AdminListRoomsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminListRoomsResponse.ProtoReflect.Descriptor instead. func (*AdminListRoomsResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{78} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{79} } func (x *AdminListRoomsResponse) GetRooms() []*AdminRoomListItem { @@ -6615,7 +6694,7 @@ type AdminGetRoomRequest struct { func (x *AdminGetRoomRequest) Reset() { *x = AdminGetRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[79] + mi := &file_proto_room_v1_room_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6627,7 +6706,7 @@ func (x *AdminGetRoomRequest) String() string { func (*AdminGetRoomRequest) ProtoMessage() {} func (x *AdminGetRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[79] + mi := &file_proto_room_v1_room_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6640,7 +6719,7 @@ func (x *AdminGetRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminGetRoomRequest.ProtoReflect.Descriptor instead. func (*AdminGetRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{79} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{80} } func (x *AdminGetRoomRequest) GetMeta() *RequestMeta { @@ -6668,7 +6747,7 @@ type AdminGetRoomResponse struct { func (x *AdminGetRoomResponse) Reset() { *x = AdminGetRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[80] + mi := &file_proto_room_v1_room_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6680,7 +6759,7 @@ func (x *AdminGetRoomResponse) String() string { func (*AdminGetRoomResponse) ProtoMessage() {} func (x *AdminGetRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[80] + mi := &file_proto_room_v1_room_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6693,7 +6772,7 @@ func (x *AdminGetRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminGetRoomResponse.ProtoReflect.Descriptor instead. func (*AdminGetRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{80} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{81} } func (x *AdminGetRoomResponse) GetRoom() *AdminRoomListItem { @@ -6731,7 +6810,7 @@ type AdminUpdateRoomRequest struct { func (x *AdminUpdateRoomRequest) Reset() { *x = AdminUpdateRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[81] + mi := &file_proto_room_v1_room_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6743,7 +6822,7 @@ func (x *AdminUpdateRoomRequest) String() string { func (*AdminUpdateRoomRequest) ProtoMessage() {} func (x *AdminUpdateRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[81] + mi := &file_proto_room_v1_room_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6756,7 +6835,7 @@ func (x *AdminUpdateRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminUpdateRoomRequest.ProtoReflect.Descriptor instead. func (*AdminUpdateRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{81} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{82} } func (x *AdminUpdateRoomRequest) GetMeta() *RequestMeta { @@ -6847,7 +6926,7 @@ type AdminUpdateRoomResponse struct { func (x *AdminUpdateRoomResponse) Reset() { *x = AdminUpdateRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[82] + mi := &file_proto_room_v1_room_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6859,7 +6938,7 @@ func (x *AdminUpdateRoomResponse) String() string { func (*AdminUpdateRoomResponse) ProtoMessage() {} func (x *AdminUpdateRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[82] + mi := &file_proto_room_v1_room_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6872,7 +6951,7 @@ func (x *AdminUpdateRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminUpdateRoomResponse.ProtoReflect.Descriptor instead. func (*AdminUpdateRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{82} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{83} } func (x *AdminUpdateRoomResponse) GetResult() *CommandResult { @@ -6901,7 +6980,7 @@ type AdminDeleteRoomRequest struct { func (x *AdminDeleteRoomRequest) Reset() { *x = AdminDeleteRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[83] + mi := &file_proto_room_v1_room_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6913,7 +6992,7 @@ func (x *AdminDeleteRoomRequest) String() string { func (*AdminDeleteRoomRequest) ProtoMessage() {} func (x *AdminDeleteRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[83] + mi := &file_proto_room_v1_room_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6926,7 +7005,7 @@ func (x *AdminDeleteRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminDeleteRoomRequest.ProtoReflect.Descriptor instead. func (*AdminDeleteRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{83} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{84} } func (x *AdminDeleteRoomRequest) GetMeta() *RequestMeta { @@ -6961,7 +7040,7 @@ type AdminDeleteRoomResponse struct { func (x *AdminDeleteRoomResponse) Reset() { *x = AdminDeleteRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[84] + mi := &file_proto_room_v1_room_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6973,7 +7052,7 @@ func (x *AdminDeleteRoomResponse) String() string { func (*AdminDeleteRoomResponse) ProtoMessage() {} func (x *AdminDeleteRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[84] + mi := &file_proto_room_v1_room_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6986,7 +7065,7 @@ func (x *AdminDeleteRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminDeleteRoomResponse.ProtoReflect.Descriptor instead. func (*AdminDeleteRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{84} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{85} } func (x *AdminDeleteRoomResponse) GetResult() *CommandResult { @@ -7017,7 +7096,7 @@ type MicUpRequest struct { func (x *MicUpRequest) Reset() { *x = MicUpRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[85] + mi := &file_proto_room_v1_room_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7029,7 +7108,7 @@ func (x *MicUpRequest) String() string { func (*MicUpRequest) ProtoMessage() {} func (x *MicUpRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[85] + mi := &file_proto_room_v1_room_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7042,7 +7121,7 @@ func (x *MicUpRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MicUpRequest.ProtoReflect.Descriptor instead. func (*MicUpRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{85} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{86} } func (x *MicUpRequest) GetMeta() *RequestMeta { @@ -7081,7 +7160,7 @@ type MicUpResponse struct { func (x *MicUpResponse) Reset() { *x = MicUpResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[86] + mi := &file_proto_room_v1_room_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7093,7 +7172,7 @@ func (x *MicUpResponse) String() string { func (*MicUpResponse) ProtoMessage() {} func (x *MicUpResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[86] + mi := &file_proto_room_v1_room_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7106,7 +7185,7 @@ func (x *MicUpResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MicUpResponse.ProtoReflect.Descriptor instead. func (*MicUpResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{86} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{87} } func (x *MicUpResponse) GetResult() *CommandResult { @@ -7160,7 +7239,7 @@ type MicDownRequest struct { func (x *MicDownRequest) Reset() { *x = MicDownRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[87] + mi := &file_proto_room_v1_room_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7172,7 +7251,7 @@ func (x *MicDownRequest) String() string { func (*MicDownRequest) ProtoMessage() {} func (x *MicDownRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[87] + mi := &file_proto_room_v1_room_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7185,7 +7264,7 @@ func (x *MicDownRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MicDownRequest.ProtoReflect.Descriptor instead. func (*MicDownRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{87} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{88} } func (x *MicDownRequest) GetMeta() *RequestMeta { @@ -7229,7 +7308,7 @@ type MicDownResponse struct { func (x *MicDownResponse) Reset() { *x = MicDownResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[88] + mi := &file_proto_room_v1_room_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7241,7 +7320,7 @@ func (x *MicDownResponse) String() string { func (*MicDownResponse) ProtoMessage() {} func (x *MicDownResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[88] + mi := &file_proto_room_v1_room_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7254,7 +7333,7 @@ func (x *MicDownResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MicDownResponse.ProtoReflect.Descriptor instead. func (*MicDownResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{88} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{89} } func (x *MicDownResponse) GetResult() *CommandResult { @@ -7293,7 +7372,7 @@ type ChangeMicSeatRequest struct { func (x *ChangeMicSeatRequest) Reset() { *x = ChangeMicSeatRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[89] + mi := &file_proto_room_v1_room_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7305,7 +7384,7 @@ func (x *ChangeMicSeatRequest) String() string { func (*ChangeMicSeatRequest) ProtoMessage() {} func (x *ChangeMicSeatRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[89] + mi := &file_proto_room_v1_room_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7318,7 +7397,7 @@ func (x *ChangeMicSeatRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeMicSeatRequest.ProtoReflect.Descriptor instead. func (*ChangeMicSeatRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{89} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{90} } func (x *ChangeMicSeatRequest) GetMeta() *RequestMeta { @@ -7361,7 +7440,7 @@ type ChangeMicSeatResponse struct { func (x *ChangeMicSeatResponse) Reset() { *x = ChangeMicSeatResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[90] + mi := &file_proto_room_v1_room_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7373,7 +7452,7 @@ func (x *ChangeMicSeatResponse) String() string { func (*ChangeMicSeatResponse) ProtoMessage() {} func (x *ChangeMicSeatResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[90] + mi := &file_proto_room_v1_room_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7386,7 +7465,7 @@ func (x *ChangeMicSeatResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeMicSeatResponse.ProtoReflect.Descriptor instead. func (*ChangeMicSeatResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{90} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{91} } func (x *ChangeMicSeatResponse) GetResult() *CommandResult { @@ -7423,7 +7502,7 @@ type ConfirmMicPublishingRequest struct { func (x *ConfirmMicPublishingRequest) Reset() { *x = ConfirmMicPublishingRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[91] + mi := &file_proto_room_v1_room_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7435,7 +7514,7 @@ func (x *ConfirmMicPublishingRequest) String() string { func (*ConfirmMicPublishingRequest) ProtoMessage() {} func (x *ConfirmMicPublishingRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[91] + mi := &file_proto_room_v1_room_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7448,7 +7527,7 @@ func (x *ConfirmMicPublishingRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfirmMicPublishingRequest.ProtoReflect.Descriptor instead. func (*ConfirmMicPublishingRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{91} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{92} } func (x *ConfirmMicPublishingRequest) GetMeta() *RequestMeta { @@ -7513,7 +7592,7 @@ type ConfirmMicPublishingResponse struct { func (x *ConfirmMicPublishingResponse) Reset() { *x = ConfirmMicPublishingResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[92] + mi := &file_proto_room_v1_room_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7525,7 +7604,7 @@ func (x *ConfirmMicPublishingResponse) String() string { func (*ConfirmMicPublishingResponse) ProtoMessage() {} func (x *ConfirmMicPublishingResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[92] + mi := &file_proto_room_v1_room_proto_msgTypes[93] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7538,7 +7617,7 @@ func (x *ConfirmMicPublishingResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfirmMicPublishingResponse.ProtoReflect.Descriptor instead. func (*ConfirmMicPublishingResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{92} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{93} } func (x *ConfirmMicPublishingResponse) GetResult() *CommandResult { @@ -7577,7 +7656,7 @@ type MicHeartbeatRequest struct { func (x *MicHeartbeatRequest) Reset() { *x = MicHeartbeatRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[93] + mi := &file_proto_room_v1_room_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7589,7 +7668,7 @@ func (x *MicHeartbeatRequest) String() string { func (*MicHeartbeatRequest) ProtoMessage() {} func (x *MicHeartbeatRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[93] + mi := &file_proto_room_v1_room_proto_msgTypes[94] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7602,7 +7681,7 @@ func (x *MicHeartbeatRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MicHeartbeatRequest.ProtoReflect.Descriptor instead. func (*MicHeartbeatRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{93} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{94} } func (x *MicHeartbeatRequest) GetMeta() *RequestMeta { @@ -7640,7 +7719,7 @@ type MicHeartbeatResponse struct { func (x *MicHeartbeatResponse) Reset() { *x = MicHeartbeatResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[94] + mi := &file_proto_room_v1_room_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7652,7 +7731,7 @@ func (x *MicHeartbeatResponse) String() string { func (*MicHeartbeatResponse) ProtoMessage() {} func (x *MicHeartbeatResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[94] + mi := &file_proto_room_v1_room_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7665,7 +7744,7 @@ func (x *MicHeartbeatResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MicHeartbeatResponse.ProtoReflect.Descriptor instead. func (*MicHeartbeatResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{94} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{95} } func (x *MicHeartbeatResponse) GetResult() *CommandResult { @@ -7712,7 +7791,7 @@ type SetMicMuteRequest struct { func (x *SetMicMuteRequest) Reset() { *x = SetMicMuteRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[95] + mi := &file_proto_room_v1_room_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7724,7 +7803,7 @@ func (x *SetMicMuteRequest) String() string { func (*SetMicMuteRequest) ProtoMessage() {} func (x *SetMicMuteRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[95] + mi := &file_proto_room_v1_room_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7737,7 +7816,7 @@ func (x *SetMicMuteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetMicMuteRequest.ProtoReflect.Descriptor instead. func (*SetMicMuteRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{95} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{96} } func (x *SetMicMuteRequest) GetMeta() *RequestMeta { @@ -7781,7 +7860,7 @@ type SetMicMuteResponse struct { func (x *SetMicMuteResponse) Reset() { *x = SetMicMuteResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[96] + mi := &file_proto_room_v1_room_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7793,7 +7872,7 @@ func (x *SetMicMuteResponse) String() string { func (*SetMicMuteResponse) ProtoMessage() {} func (x *SetMicMuteResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[96] + mi := &file_proto_room_v1_room_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7806,7 +7885,7 @@ func (x *SetMicMuteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetMicMuteResponse.ProtoReflect.Descriptor instead. func (*SetMicMuteResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{96} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{97} } func (x *SetMicMuteResponse) GetResult() *CommandResult { @@ -7848,7 +7927,7 @@ type ApplyRTCEventRequest struct { func (x *ApplyRTCEventRequest) Reset() { *x = ApplyRTCEventRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[97] + mi := &file_proto_room_v1_room_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7860,7 +7939,7 @@ func (x *ApplyRTCEventRequest) String() string { func (*ApplyRTCEventRequest) ProtoMessage() {} func (x *ApplyRTCEventRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[97] + mi := &file_proto_room_v1_room_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7873,7 +7952,7 @@ func (x *ApplyRTCEventRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyRTCEventRequest.ProtoReflect.Descriptor instead. func (*ApplyRTCEventRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{97} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{98} } func (x *ApplyRTCEventRequest) GetMeta() *RequestMeta { @@ -7938,7 +8017,7 @@ type ApplyRTCEventResponse struct { func (x *ApplyRTCEventResponse) Reset() { *x = ApplyRTCEventResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[98] + mi := &file_proto_room_v1_room_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7950,7 +8029,7 @@ func (x *ApplyRTCEventResponse) String() string { func (*ApplyRTCEventResponse) ProtoMessage() {} func (x *ApplyRTCEventResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[98] + mi := &file_proto_room_v1_room_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7963,7 +8042,7 @@ func (x *ApplyRTCEventResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyRTCEventResponse.ProtoReflect.Descriptor instead. func (*ApplyRTCEventResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{98} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{99} } func (x *ApplyRTCEventResponse) GetResult() *CommandResult { @@ -8000,7 +8079,7 @@ type SetMicSeatLockRequest struct { func (x *SetMicSeatLockRequest) Reset() { *x = SetMicSeatLockRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[99] + mi := &file_proto_room_v1_room_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8012,7 +8091,7 @@ func (x *SetMicSeatLockRequest) String() string { func (*SetMicSeatLockRequest) ProtoMessage() {} func (x *SetMicSeatLockRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[99] + mi := &file_proto_room_v1_room_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8025,7 +8104,7 @@ func (x *SetMicSeatLockRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetMicSeatLockRequest.ProtoReflect.Descriptor instead. func (*SetMicSeatLockRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{99} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{100} } func (x *SetMicSeatLockRequest) GetMeta() *RequestMeta { @@ -8061,7 +8140,7 @@ type SetMicSeatLockResponse struct { func (x *SetMicSeatLockResponse) Reset() { *x = SetMicSeatLockResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[100] + mi := &file_proto_room_v1_room_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8073,7 +8152,7 @@ func (x *SetMicSeatLockResponse) String() string { func (*SetMicSeatLockResponse) ProtoMessage() {} func (x *SetMicSeatLockResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[100] + mi := &file_proto_room_v1_room_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8086,7 +8165,7 @@ func (x *SetMicSeatLockResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetMicSeatLockResponse.ProtoReflect.Descriptor instead. func (*SetMicSeatLockResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{100} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{101} } func (x *SetMicSeatLockResponse) GetResult() *CommandResult { @@ -8115,7 +8194,7 @@ type SetChatEnabledRequest struct { func (x *SetChatEnabledRequest) Reset() { *x = SetChatEnabledRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[101] + mi := &file_proto_room_v1_room_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8127,7 +8206,7 @@ func (x *SetChatEnabledRequest) String() string { func (*SetChatEnabledRequest) ProtoMessage() {} func (x *SetChatEnabledRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[101] + mi := &file_proto_room_v1_room_proto_msgTypes[102] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8140,7 +8219,7 @@ func (x *SetChatEnabledRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetChatEnabledRequest.ProtoReflect.Descriptor instead. func (*SetChatEnabledRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{101} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{102} } func (x *SetChatEnabledRequest) GetMeta() *RequestMeta { @@ -8169,7 +8248,7 @@ type SetChatEnabledResponse struct { func (x *SetChatEnabledResponse) Reset() { *x = SetChatEnabledResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[102] + mi := &file_proto_room_v1_room_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8181,7 +8260,7 @@ func (x *SetChatEnabledResponse) String() string { func (*SetChatEnabledResponse) ProtoMessage() {} func (x *SetChatEnabledResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[102] + mi := &file_proto_room_v1_room_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8194,7 +8273,7 @@ func (x *SetChatEnabledResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetChatEnabledResponse.ProtoReflect.Descriptor instead. func (*SetChatEnabledResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{102} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{103} } func (x *SetChatEnabledResponse) GetResult() *CommandResult { @@ -8225,7 +8304,7 @@ type SetRoomPasswordRequest struct { func (x *SetRoomPasswordRequest) Reset() { *x = SetRoomPasswordRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[103] + mi := &file_proto_room_v1_room_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8237,7 +8316,7 @@ func (x *SetRoomPasswordRequest) String() string { func (*SetRoomPasswordRequest) ProtoMessage() {} func (x *SetRoomPasswordRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[103] + mi := &file_proto_room_v1_room_proto_msgTypes[104] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8250,7 +8329,7 @@ func (x *SetRoomPasswordRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetRoomPasswordRequest.ProtoReflect.Descriptor instead. func (*SetRoomPasswordRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{103} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{104} } func (x *SetRoomPasswordRequest) GetMeta() *RequestMeta { @@ -8286,7 +8365,7 @@ type SetRoomPasswordResponse struct { func (x *SetRoomPasswordResponse) Reset() { *x = SetRoomPasswordResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[104] + mi := &file_proto_room_v1_room_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8298,7 +8377,7 @@ func (x *SetRoomPasswordResponse) String() string { func (*SetRoomPasswordResponse) ProtoMessage() {} func (x *SetRoomPasswordResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[104] + mi := &file_proto_room_v1_room_proto_msgTypes[105] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8311,7 +8390,7 @@ func (x *SetRoomPasswordResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetRoomPasswordResponse.ProtoReflect.Descriptor instead. func (*SetRoomPasswordResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{104} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{105} } func (x *SetRoomPasswordResponse) GetResult() *CommandResult { @@ -8341,7 +8420,7 @@ type SetRoomAdminRequest struct { func (x *SetRoomAdminRequest) Reset() { *x = SetRoomAdminRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[105] + mi := &file_proto_room_v1_room_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8353,7 +8432,7 @@ func (x *SetRoomAdminRequest) String() string { func (*SetRoomAdminRequest) ProtoMessage() {} func (x *SetRoomAdminRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[105] + mi := &file_proto_room_v1_room_proto_msgTypes[106] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8366,7 +8445,7 @@ func (x *SetRoomAdminRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetRoomAdminRequest.ProtoReflect.Descriptor instead. func (*SetRoomAdminRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{105} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{106} } func (x *SetRoomAdminRequest) GetMeta() *RequestMeta { @@ -8402,7 +8481,7 @@ type SetRoomAdminResponse struct { func (x *SetRoomAdminResponse) Reset() { *x = SetRoomAdminResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[106] + mi := &file_proto_room_v1_room_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8414,7 +8493,7 @@ func (x *SetRoomAdminResponse) String() string { func (*SetRoomAdminResponse) ProtoMessage() {} func (x *SetRoomAdminResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[106] + mi := &file_proto_room_v1_room_proto_msgTypes[107] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8427,7 +8506,7 @@ func (x *SetRoomAdminResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetRoomAdminResponse.ProtoReflect.Descriptor instead. func (*SetRoomAdminResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{106} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{107} } func (x *SetRoomAdminResponse) GetResult() *CommandResult { @@ -8457,7 +8536,7 @@ type MuteUserRequest struct { func (x *MuteUserRequest) Reset() { *x = MuteUserRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[107] + mi := &file_proto_room_v1_room_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8469,7 +8548,7 @@ func (x *MuteUserRequest) String() string { func (*MuteUserRequest) ProtoMessage() {} func (x *MuteUserRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[107] + mi := &file_proto_room_v1_room_proto_msgTypes[108] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8482,7 +8561,7 @@ func (x *MuteUserRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MuteUserRequest.ProtoReflect.Descriptor instead. func (*MuteUserRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{107} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{108} } func (x *MuteUserRequest) GetMeta() *RequestMeta { @@ -8518,7 +8597,7 @@ type MuteUserResponse struct { func (x *MuteUserResponse) Reset() { *x = MuteUserResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[108] + mi := &file_proto_room_v1_room_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8530,7 +8609,7 @@ func (x *MuteUserResponse) String() string { func (*MuteUserResponse) ProtoMessage() {} func (x *MuteUserResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[108] + mi := &file_proto_room_v1_room_proto_msgTypes[109] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8543,7 +8622,7 @@ func (x *MuteUserResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MuteUserResponse.ProtoReflect.Descriptor instead. func (*MuteUserResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{108} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{109} } func (x *MuteUserResponse) GetResult() *CommandResult { @@ -8574,7 +8653,7 @@ type KickUserRequest struct { func (x *KickUserRequest) Reset() { *x = KickUserRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[109] + mi := &file_proto_room_v1_room_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8586,7 +8665,7 @@ func (x *KickUserRequest) String() string { func (*KickUserRequest) ProtoMessage() {} func (x *KickUserRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[109] + mi := &file_proto_room_v1_room_proto_msgTypes[110] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8599,7 +8678,7 @@ func (x *KickUserRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use KickUserRequest.ProtoReflect.Descriptor instead. func (*KickUserRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{109} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{110} } func (x *KickUserRequest) GetMeta() *RequestMeta { @@ -8639,7 +8718,7 @@ type KickUserResponse struct { func (x *KickUserResponse) Reset() { *x = KickUserResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[110] + mi := &file_proto_room_v1_room_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8651,7 +8730,7 @@ func (x *KickUserResponse) String() string { func (*KickUserResponse) ProtoMessage() {} func (x *KickUserResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[110] + mi := &file_proto_room_v1_room_proto_msgTypes[111] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8664,7 +8743,7 @@ func (x *KickUserResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use KickUserResponse.ProtoReflect.Descriptor instead. func (*KickUserResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{110} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{111} } func (x *KickUserResponse) GetResult() *CommandResult { @@ -8707,7 +8786,7 @@ type UnbanUserRequest struct { func (x *UnbanUserRequest) Reset() { *x = UnbanUserRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[111] + mi := &file_proto_room_v1_room_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8719,7 +8798,7 @@ func (x *UnbanUserRequest) String() string { func (*UnbanUserRequest) ProtoMessage() {} func (x *UnbanUserRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[111] + mi := &file_proto_room_v1_room_proto_msgTypes[112] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8732,7 +8811,7 @@ func (x *UnbanUserRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnbanUserRequest.ProtoReflect.Descriptor instead. func (*UnbanUserRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{111} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{112} } func (x *UnbanUserRequest) GetMeta() *RequestMeta { @@ -8761,7 +8840,7 @@ type UnbanUserResponse struct { func (x *UnbanUserResponse) Reset() { *x = UnbanUserResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[112] + mi := &file_proto_room_v1_room_proto_msgTypes[113] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8773,7 +8852,7 @@ func (x *UnbanUserResponse) String() string { func (*UnbanUserResponse) ProtoMessage() {} func (x *UnbanUserResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[112] + mi := &file_proto_room_v1_room_proto_msgTypes[113] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8786,7 +8865,7 @@ func (x *UnbanUserResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnbanUserResponse.ProtoReflect.Descriptor instead. func (*UnbanUserResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{112} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{113} } func (x *UnbanUserResponse) GetResult() *CommandResult { @@ -8820,7 +8899,7 @@ type SystemEvictUserRequest struct { func (x *SystemEvictUserRequest) Reset() { *x = SystemEvictUserRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[113] + mi := &file_proto_room_v1_room_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8832,7 +8911,7 @@ func (x *SystemEvictUserRequest) String() string { func (*SystemEvictUserRequest) ProtoMessage() {} func (x *SystemEvictUserRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[113] + mi := &file_proto_room_v1_room_proto_msgTypes[114] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8845,7 +8924,7 @@ func (x *SystemEvictUserRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SystemEvictUserRequest.ProtoReflect.Descriptor instead. func (*SystemEvictUserRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{113} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{114} } func (x *SystemEvictUserRequest) GetMeta() *RequestMeta { @@ -8899,7 +8978,7 @@ type SystemEvictUserResponse struct { func (x *SystemEvictUserResponse) Reset() { *x = SystemEvictUserResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[114] + mi := &file_proto_room_v1_room_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8911,7 +8990,7 @@ func (x *SystemEvictUserResponse) String() string { func (*SystemEvictUserResponse) ProtoMessage() {} func (x *SystemEvictUserResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[114] + mi := &file_proto_room_v1_room_proto_msgTypes[115] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8924,7 +9003,7 @@ func (x *SystemEvictUserResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SystemEvictUserResponse.ProtoReflect.Descriptor instead. func (*SystemEvictUserResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{114} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{115} } func (x *SystemEvictUserResponse) GetHadCurrentRoom() bool { @@ -8986,7 +9065,7 @@ type SendGiftTargetHostScope struct { func (x *SendGiftTargetHostScope) Reset() { *x = SendGiftTargetHostScope{} - mi := &file_proto_room_v1_room_proto_msgTypes[115] + mi := &file_proto_room_v1_room_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8998,7 +9077,7 @@ func (x *SendGiftTargetHostScope) String() string { func (*SendGiftTargetHostScope) ProtoMessage() {} func (x *SendGiftTargetHostScope) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[115] + mi := &file_proto_room_v1_room_proto_msgTypes[116] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9011,7 +9090,7 @@ func (x *SendGiftTargetHostScope) ProtoReflect() protoreflect.Message { // Deprecated: Use SendGiftTargetHostScope.ProtoReflect.Descriptor instead. func (*SendGiftTargetHostScope) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{115} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{116} } func (x *SendGiftTargetHostScope) GetTargetUserId() int64 { @@ -9058,7 +9137,7 @@ type SendGiftDisplayProfile struct { func (x *SendGiftDisplayProfile) Reset() { *x = SendGiftDisplayProfile{} - mi := &file_proto_room_v1_room_proto_msgTypes[116] + mi := &file_proto_room_v1_room_proto_msgTypes[117] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9070,7 +9149,7 @@ func (x *SendGiftDisplayProfile) String() string { func (*SendGiftDisplayProfile) ProtoMessage() {} func (x *SendGiftDisplayProfile) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[116] + mi := &file_proto_room_v1_room_proto_msgTypes[117] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9083,7 +9162,7 @@ func (x *SendGiftDisplayProfile) ProtoReflect() protoreflect.Message { // Deprecated: Use SendGiftDisplayProfile.ProtoReflect.Descriptor instead. func (*SendGiftDisplayProfile) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{116} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{117} } func (x *SendGiftDisplayProfile) GetUserId() int64 { @@ -9143,7 +9222,7 @@ type SendGiftBatchTarget struct { func (x *SendGiftBatchTarget) Reset() { *x = SendGiftBatchTarget{} - mi := &file_proto_room_v1_room_proto_msgTypes[117] + mi := &file_proto_room_v1_room_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9155,7 +9234,7 @@ func (x *SendGiftBatchTarget) String() string { func (*SendGiftBatchTarget) ProtoMessage() {} func (x *SendGiftBatchTarget) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[117] + mi := &file_proto_room_v1_room_proto_msgTypes[118] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9168,7 +9247,7 @@ func (x *SendGiftBatchTarget) ProtoReflect() protoreflect.Message { // Deprecated: Use SendGiftBatchTarget.ProtoReflect.Descriptor instead. func (*SendGiftBatchTarget) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{117} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{118} } func (x *SendGiftBatchTarget) GetTargetUserId() int64 { @@ -9281,7 +9360,7 @@ type SendGiftBatchDisplay struct { func (x *SendGiftBatchDisplay) Reset() { *x = SendGiftBatchDisplay{} - mi := &file_proto_room_v1_room_proto_msgTypes[118] + mi := &file_proto_room_v1_room_proto_msgTypes[119] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9293,7 +9372,7 @@ func (x *SendGiftBatchDisplay) String() string { func (*SendGiftBatchDisplay) ProtoMessage() {} func (x *SendGiftBatchDisplay) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[118] + mi := &file_proto_room_v1_room_proto_msgTypes[119] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9306,7 +9385,7 @@ func (x *SendGiftBatchDisplay) ProtoReflect() protoreflect.Message { // Deprecated: Use SendGiftBatchDisplay.ProtoReflect.Descriptor instead. func (*SendGiftBatchDisplay) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{118} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{119} } func (x *SendGiftBatchDisplay) GetEventId() string { @@ -9504,7 +9583,7 @@ type SendGiftRequest struct { func (x *SendGiftRequest) Reset() { *x = SendGiftRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[119] + mi := &file_proto_room_v1_room_proto_msgTypes[120] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9516,7 +9595,7 @@ func (x *SendGiftRequest) String() string { func (*SendGiftRequest) ProtoMessage() {} func (x *SendGiftRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[119] + mi := &file_proto_room_v1_room_proto_msgTypes[120] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9529,7 +9608,7 @@ func (x *SendGiftRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SendGiftRequest.ProtoReflect.Descriptor instead. func (*SendGiftRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{119} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{120} } func (x *SendGiftRequest) GetMeta() *RequestMeta { @@ -9684,7 +9763,7 @@ type SendGiftResponse struct { func (x *SendGiftResponse) Reset() { *x = SendGiftResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[120] + mi := &file_proto_room_v1_room_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9696,7 +9775,7 @@ func (x *SendGiftResponse) String() string { func (*SendGiftResponse) ProtoMessage() {} func (x *SendGiftResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[120] + mi := &file_proto_room_v1_room_proto_msgTypes[121] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9709,7 +9788,7 @@ func (x *SendGiftResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SendGiftResponse.ProtoReflect.Descriptor instead. func (*SendGiftResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{120} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{121} } func (x *SendGiftResponse) GetResult() *CommandResult { @@ -9802,7 +9881,7 @@ type CheckSpeakPermissionRequest struct { func (x *CheckSpeakPermissionRequest) Reset() { *x = CheckSpeakPermissionRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[121] + mi := &file_proto_room_v1_room_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9814,7 +9893,7 @@ func (x *CheckSpeakPermissionRequest) String() string { func (*CheckSpeakPermissionRequest) ProtoMessage() {} func (x *CheckSpeakPermissionRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[121] + mi := &file_proto_room_v1_room_proto_msgTypes[122] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9827,7 +9906,7 @@ func (x *CheckSpeakPermissionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckSpeakPermissionRequest.ProtoReflect.Descriptor instead. func (*CheckSpeakPermissionRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{121} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{122} } func (x *CheckSpeakPermissionRequest) GetRoomId() string { @@ -9864,7 +9943,7 @@ type CheckSpeakPermissionResponse struct { func (x *CheckSpeakPermissionResponse) Reset() { *x = CheckSpeakPermissionResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[122] + mi := &file_proto_room_v1_room_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9876,7 +9955,7 @@ func (x *CheckSpeakPermissionResponse) String() string { func (*CheckSpeakPermissionResponse) ProtoMessage() {} func (x *CheckSpeakPermissionResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[122] + mi := &file_proto_room_v1_room_proto_msgTypes[123] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9889,7 +9968,7 @@ func (x *CheckSpeakPermissionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckSpeakPermissionResponse.ProtoReflect.Descriptor instead. func (*CheckSpeakPermissionResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{122} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{123} } func (x *CheckSpeakPermissionResponse) GetAllowed() bool { @@ -9928,7 +10007,7 @@ type VerifyRoomPresenceRequest struct { func (x *VerifyRoomPresenceRequest) Reset() { *x = VerifyRoomPresenceRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[123] + mi := &file_proto_room_v1_room_proto_msgTypes[124] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9940,7 +10019,7 @@ func (x *VerifyRoomPresenceRequest) String() string { func (*VerifyRoomPresenceRequest) ProtoMessage() {} func (x *VerifyRoomPresenceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[123] + mi := &file_proto_room_v1_room_proto_msgTypes[124] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9953,7 +10032,7 @@ func (x *VerifyRoomPresenceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyRoomPresenceRequest.ProtoReflect.Descriptor instead. func (*VerifyRoomPresenceRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{123} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{124} } func (x *VerifyRoomPresenceRequest) GetRoomId() string { @@ -10004,7 +10083,7 @@ type VerifyRoomPresenceResponse struct { func (x *VerifyRoomPresenceResponse) Reset() { *x = VerifyRoomPresenceResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[124] + mi := &file_proto_room_v1_room_proto_msgTypes[125] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10016,7 +10095,7 @@ func (x *VerifyRoomPresenceResponse) String() string { func (*VerifyRoomPresenceResponse) ProtoMessage() {} func (x *VerifyRoomPresenceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[124] + mi := &file_proto_room_v1_room_proto_msgTypes[125] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10029,7 +10108,7 @@ func (x *VerifyRoomPresenceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyRoomPresenceResponse.ProtoReflect.Descriptor instead. func (*VerifyRoomPresenceResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{124} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{125} } func (x *VerifyRoomPresenceResponse) GetPresent() bool { @@ -10053,8 +10132,9 @@ func (x *VerifyRoomPresenceResponse) GetRoomVersion() int64 { return 0 } -// ListRoomsRequest 查询当前用户所在区域可见的房间列表。 -// visible_region_id 必须来自 gateway 对 user-service 的 GetUser 结果,客户端不能直接提交。 +// ListRoomsRequest 查询首页公共房间列表。 +// visible_region_id 是 gateway 解析的实际查询区域:默认取 viewer 区域,显式筛选时取已校验的 filter_region_id。 +// gateway 同时写 filter_region_id 绑定游标;客户端不能直接构造任一内部字段。 type ListRoomsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -10067,17 +10147,19 @@ type ListRoomsRequest struct { 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 只能传当前用户区域国家列表内的国家码。 + // country_code 是可选国家筛选值;gateway 必须先确认它属于 active 区域。 CountryCode string `protobuf:"bytes,8,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` - // viewer_country_code 是当前用户国家,用于区域内国家优先排序,不作为客户端可选筛选条件。 + // viewer_country_code 是当前用户国家,用于 All/区域列表的本国家优先排序。 ViewerCountryCode string `protobuf:"bytes,9,opt,name=viewer_country_code,json=viewerCountryCode,proto3" json:"viewer_country_code,omitempty"` - // all_visible_regions 只能由 gateway 根据后台白名单配置注入;为 true 时列表不按 visible_region_id 过滤。 + // all_visible_regions 只能由 gateway 根据 App 策略或后台白名单注入;为 true 时列表不按 visible_region_id 过滤。 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"` } func (x *ListRoomsRequest) Reset() { *x = ListRoomsRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[125] + mi := &file_proto_room_v1_room_proto_msgTypes[126] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10089,7 +10171,7 @@ func (x *ListRoomsRequest) String() string { func (*ListRoomsRequest) ProtoMessage() {} func (x *ListRoomsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[125] + mi := &file_proto_room_v1_room_proto_msgTypes[126] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10102,7 +10184,7 @@ func (x *ListRoomsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomsRequest.ProtoReflect.Descriptor instead. func (*ListRoomsRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{125} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{126} } func (x *ListRoomsRequest) GetMeta() *RequestMeta { @@ -10175,6 +10257,13 @@ func (x *ListRoomsRequest) GetAllVisibleRegions() bool { return false } +func (x *ListRoomsRequest) GetFilterRegionId() int64 { + if x != nil { + return x.FilterRegionId + } + return 0 +} + // ListRoomsByOwnersRequest 查询一组房主名下 active 房间。 // owner_user_ids 必须由 gateway 根据上游业务归属注入,客户端不能直接提交任意房主集合。 type ListRoomsByOwnersRequest struct { @@ -10193,7 +10282,7 @@ type ListRoomsByOwnersRequest struct { func (x *ListRoomsByOwnersRequest) Reset() { *x = ListRoomsByOwnersRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[126] + mi := &file_proto_room_v1_room_proto_msgTypes[127] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10205,7 +10294,7 @@ func (x *ListRoomsByOwnersRequest) String() string { func (*ListRoomsByOwnersRequest) ProtoMessage() {} func (x *ListRoomsByOwnersRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[126] + mi := &file_proto_room_v1_room_proto_msgTypes[127] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10218,7 +10307,7 @@ func (x *ListRoomsByOwnersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomsByOwnersRequest.ProtoReflect.Descriptor instead. func (*ListRoomsByOwnersRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{126} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{127} } func (x *ListRoomsByOwnersRequest) GetMeta() *RequestMeta { @@ -10290,7 +10379,7 @@ type ListRoomFeedsRequest struct { func (x *ListRoomFeedsRequest) Reset() { *x = ListRoomFeedsRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[127] + mi := &file_proto_room_v1_room_proto_msgTypes[128] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10302,7 +10391,7 @@ func (x *ListRoomFeedsRequest) String() string { func (*ListRoomFeedsRequest) ProtoMessage() {} func (x *ListRoomFeedsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[127] + mi := &file_proto_room_v1_room_proto_msgTypes[128] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10315,7 +10404,7 @@ func (x *ListRoomFeedsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomFeedsRequest.ProtoReflect.Descriptor instead. func (*ListRoomFeedsRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{127} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{128} } func (x *ListRoomFeedsRequest) GetMeta() *RequestMeta { @@ -10388,7 +10477,7 @@ type ListRoomGiftLeaderboardRequest struct { func (x *ListRoomGiftLeaderboardRequest) Reset() { *x = ListRoomGiftLeaderboardRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[128] + mi := &file_proto_room_v1_room_proto_msgTypes[129] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10400,7 +10489,7 @@ func (x *ListRoomGiftLeaderboardRequest) String() string { func (*ListRoomGiftLeaderboardRequest) ProtoMessage() {} func (x *ListRoomGiftLeaderboardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[128] + mi := &file_proto_room_v1_room_proto_msgTypes[129] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10413,7 +10502,7 @@ func (x *ListRoomGiftLeaderboardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomGiftLeaderboardRequest.ProtoReflect.Descriptor instead. func (*ListRoomGiftLeaderboardRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{128} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{129} } func (x *ListRoomGiftLeaderboardRequest) GetMeta() *RequestMeta { @@ -10456,7 +10545,7 @@ type RoomFeedRelatedUser struct { func (x *RoomFeedRelatedUser) Reset() { *x = RoomFeedRelatedUser{} - mi := &file_proto_room_v1_room_proto_msgTypes[129] + mi := &file_proto_room_v1_room_proto_msgTypes[130] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10468,7 +10557,7 @@ func (x *RoomFeedRelatedUser) String() string { func (*RoomFeedRelatedUser) ProtoMessage() {} func (x *RoomFeedRelatedUser) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[129] + mi := &file_proto_room_v1_room_proto_msgTypes[130] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10481,7 +10570,7 @@ func (x *RoomFeedRelatedUser) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomFeedRelatedUser.ProtoReflect.Descriptor instead. func (*RoomFeedRelatedUser) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{129} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{130} } func (x *RoomFeedRelatedUser) GetUserId() int64 { @@ -10523,7 +10612,7 @@ type RoomListItem struct { func (x *RoomListItem) Reset() { *x = RoomListItem{} - mi := &file_proto_room_v1_room_proto_msgTypes[130] + mi := &file_proto_room_v1_room_proto_msgTypes[131] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10535,7 +10624,7 @@ func (x *RoomListItem) String() string { func (*RoomListItem) ProtoMessage() {} func (x *RoomListItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[130] + mi := &file_proto_room_v1_room_proto_msgTypes[131] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10548,7 +10637,7 @@ func (x *RoomListItem) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomListItem.ProtoReflect.Descriptor instead. func (*RoomListItem) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{130} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{131} } func (x *RoomListItem) GetRoomId() string { @@ -10668,7 +10757,7 @@ type ListRoomsResponse struct { func (x *ListRoomsResponse) Reset() { *x = ListRoomsResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[131] + mi := &file_proto_room_v1_room_proto_msgTypes[132] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10680,7 +10769,7 @@ func (x *ListRoomsResponse) String() string { func (*ListRoomsResponse) ProtoMessage() {} func (x *ListRoomsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[131] + mi := &file_proto_room_v1_room_proto_msgTypes[132] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10693,7 +10782,7 @@ func (x *ListRoomsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomsResponse.ProtoReflect.Descriptor instead. func (*ListRoomsResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{131} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{132} } func (x *ListRoomsResponse) GetRooms() []*RoomListItem { @@ -10724,7 +10813,7 @@ type RoomGiftLeaderboardItem struct { func (x *RoomGiftLeaderboardItem) Reset() { *x = RoomGiftLeaderboardItem{} - mi := &file_proto_room_v1_room_proto_msgTypes[132] + mi := &file_proto_room_v1_room_proto_msgTypes[133] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10736,7 +10825,7 @@ func (x *RoomGiftLeaderboardItem) String() string { func (*RoomGiftLeaderboardItem) ProtoMessage() {} func (x *RoomGiftLeaderboardItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[132] + mi := &file_proto_room_v1_room_proto_msgTypes[133] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10749,7 +10838,7 @@ func (x *RoomGiftLeaderboardItem) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomGiftLeaderboardItem.ProtoReflect.Descriptor instead. func (*RoomGiftLeaderboardItem) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{132} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{133} } func (x *RoomGiftLeaderboardItem) GetRank() int64 { @@ -10796,7 +10885,7 @@ type ListRoomGiftLeaderboardResponse struct { func (x *ListRoomGiftLeaderboardResponse) Reset() { *x = ListRoomGiftLeaderboardResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[133] + mi := &file_proto_room_v1_room_proto_msgTypes[134] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10808,7 +10897,7 @@ func (x *ListRoomGiftLeaderboardResponse) String() string { func (*ListRoomGiftLeaderboardResponse) ProtoMessage() {} func (x *ListRoomGiftLeaderboardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[133] + mi := &file_proto_room_v1_room_proto_msgTypes[134] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10821,7 +10910,7 @@ func (x *ListRoomGiftLeaderboardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomGiftLeaderboardResponse.ProtoReflect.Descriptor instead. func (*ListRoomGiftLeaderboardResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{133} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{134} } func (x *ListRoomGiftLeaderboardResponse) GetItems() []*RoomGiftLeaderboardItem { @@ -10881,7 +10970,7 @@ type ListRoomContributionRankRequest struct { func (x *ListRoomContributionRankRequest) Reset() { *x = ListRoomContributionRankRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[134] + mi := &file_proto_room_v1_room_proto_msgTypes[135] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10893,7 +10982,7 @@ func (x *ListRoomContributionRankRequest) String() string { func (*ListRoomContributionRankRequest) ProtoMessage() {} func (x *ListRoomContributionRankRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[134] + mi := &file_proto_room_v1_room_proto_msgTypes[135] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10906,7 +10995,7 @@ func (x *ListRoomContributionRankRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomContributionRankRequest.ProtoReflect.Descriptor instead. func (*ListRoomContributionRankRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{134} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{135} } func (x *ListRoomContributionRankRequest) GetMeta() *RequestMeta { @@ -10961,7 +11050,7 @@ type ListRoomContributionRankResponse struct { func (x *ListRoomContributionRankResponse) Reset() { *x = ListRoomContributionRankResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[135] + mi := &file_proto_room_v1_room_proto_msgTypes[136] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10973,7 +11062,7 @@ func (x *ListRoomContributionRankResponse) String() string { func (*ListRoomContributionRankResponse) ProtoMessage() {} func (x *ListRoomContributionRankResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[135] + mi := &file_proto_room_v1_room_proto_msgTypes[136] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10986,7 +11075,7 @@ func (x *ListRoomContributionRankResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomContributionRankResponse.ProtoReflect.Descriptor instead. func (*ListRoomContributionRankResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{135} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{136} } func (x *ListRoomContributionRankResponse) GetRoomId() string { @@ -11051,7 +11140,7 @@ type GetMyRoomRequest struct { func (x *GetMyRoomRequest) Reset() { *x = GetMyRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[136] + mi := &file_proto_room_v1_room_proto_msgTypes[137] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11063,7 +11152,7 @@ func (x *GetMyRoomRequest) String() string { func (*GetMyRoomRequest) ProtoMessage() {} func (x *GetMyRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[136] + mi := &file_proto_room_v1_room_proto_msgTypes[137] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11076,7 +11165,7 @@ func (x *GetMyRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyRoomRequest.ProtoReflect.Descriptor instead. func (*GetMyRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{136} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{137} } func (x *GetMyRoomRequest) GetMeta() *RequestMeta { @@ -11107,7 +11196,7 @@ type GetMyRoomResponse struct { func (x *GetMyRoomResponse) Reset() { *x = GetMyRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[137] + mi := &file_proto_room_v1_room_proto_msgTypes[138] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11119,7 +11208,7 @@ func (x *GetMyRoomResponse) String() string { func (*GetMyRoomResponse) ProtoMessage() {} func (x *GetMyRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[137] + mi := &file_proto_room_v1_room_proto_msgTypes[138] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11132,7 +11221,7 @@ func (x *GetMyRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyRoomResponse.ProtoReflect.Descriptor instead. func (*GetMyRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{137} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{138} } func (x *GetMyRoomResponse) GetHasRoom() bool { @@ -11169,7 +11258,7 @@ type GetCurrentRoomRequest struct { func (x *GetCurrentRoomRequest) Reset() { *x = GetCurrentRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[138] + mi := &file_proto_room_v1_room_proto_msgTypes[139] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11181,7 +11270,7 @@ func (x *GetCurrentRoomRequest) String() string { func (*GetCurrentRoomRequest) ProtoMessage() {} func (x *GetCurrentRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[138] + mi := &file_proto_room_v1_room_proto_msgTypes[139] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11194,7 +11283,7 @@ func (x *GetCurrentRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCurrentRoomRequest.ProtoReflect.Descriptor instead. func (*GetCurrentRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{138} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{139} } func (x *GetCurrentRoomRequest) GetMeta() *RequestMeta { @@ -11231,7 +11320,7 @@ type GetCurrentRoomResponse struct { func (x *GetCurrentRoomResponse) Reset() { *x = GetCurrentRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[139] + mi := &file_proto_room_v1_room_proto_msgTypes[140] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11243,7 +11332,7 @@ func (x *GetCurrentRoomResponse) String() string { func (*GetCurrentRoomResponse) ProtoMessage() {} func (x *GetCurrentRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[139] + mi := &file_proto_room_v1_room_proto_msgTypes[140] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11256,7 +11345,7 @@ func (x *GetCurrentRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCurrentRoomResponse.ProtoReflect.Descriptor instead. func (*GetCurrentRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{139} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{140} } func (x *GetCurrentRoomResponse) GetHasCurrentRoom() bool { @@ -11336,7 +11425,7 @@ type GetRoomSnapshotRequest struct { func (x *GetRoomSnapshotRequest) Reset() { *x = GetRoomSnapshotRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[140] + mi := &file_proto_room_v1_room_proto_msgTypes[141] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11348,7 +11437,7 @@ func (x *GetRoomSnapshotRequest) String() string { func (*GetRoomSnapshotRequest) ProtoMessage() {} func (x *GetRoomSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[140] + mi := &file_proto_room_v1_room_proto_msgTypes[141] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11361,7 +11450,7 @@ func (x *GetRoomSnapshotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRoomSnapshotRequest.ProtoReflect.Descriptor instead. func (*GetRoomSnapshotRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{140} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{141} } func (x *GetRoomSnapshotRequest) GetMeta() *RequestMeta { @@ -11399,7 +11488,7 @@ type GetRoomSnapshotResponse struct { func (x *GetRoomSnapshotResponse) Reset() { *x = GetRoomSnapshotResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[141] + mi := &file_proto_room_v1_room_proto_msgTypes[142] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11411,7 +11500,7 @@ func (x *GetRoomSnapshotResponse) String() string { func (*GetRoomSnapshotResponse) ProtoMessage() {} func (x *GetRoomSnapshotResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[141] + mi := &file_proto_room_v1_room_proto_msgTypes[142] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11424,7 +11513,7 @@ func (x *GetRoomSnapshotResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRoomSnapshotResponse.ProtoReflect.Descriptor instead. func (*GetRoomSnapshotResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{141} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{142} } func (x *GetRoomSnapshotResponse) GetRoom() *RoomSnapshot { @@ -11462,7 +11551,7 @@ type GetRoomRocketRequest struct { func (x *GetRoomRocketRequest) Reset() { *x = GetRoomRocketRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[142] + mi := &file_proto_room_v1_room_proto_msgTypes[143] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11474,7 +11563,7 @@ func (x *GetRoomRocketRequest) String() string { func (*GetRoomRocketRequest) ProtoMessage() {} func (x *GetRoomRocketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[142] + mi := &file_proto_room_v1_room_proto_msgTypes[143] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11487,7 +11576,7 @@ func (x *GetRoomRocketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRoomRocketRequest.ProtoReflect.Descriptor instead. func (*GetRoomRocketRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{142} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{143} } func (x *GetRoomRocketRequest) GetMeta() *RequestMeta { @@ -11522,7 +11611,7 @@ type GetRoomRocketResponse struct { func (x *GetRoomRocketResponse) Reset() { *x = GetRoomRocketResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[143] + mi := &file_proto_room_v1_room_proto_msgTypes[144] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11534,7 +11623,7 @@ func (x *GetRoomRocketResponse) String() string { func (*GetRoomRocketResponse) ProtoMessage() {} func (x *GetRoomRocketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[143] + mi := &file_proto_room_v1_room_proto_msgTypes[144] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11547,7 +11636,7 @@ func (x *GetRoomRocketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRoomRocketResponse.ProtoReflect.Descriptor instead. func (*GetRoomRocketResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{143} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{144} } func (x *GetRoomRocketResponse) GetRocket() *RoomRocketInfo { @@ -11580,7 +11669,7 @@ type ListRoomOnlineUsersRequest struct { func (x *ListRoomOnlineUsersRequest) Reset() { *x = ListRoomOnlineUsersRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[144] + mi := &file_proto_room_v1_room_proto_msgTypes[145] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11592,7 +11681,7 @@ func (x *ListRoomOnlineUsersRequest) String() string { func (*ListRoomOnlineUsersRequest) ProtoMessage() {} func (x *ListRoomOnlineUsersRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[144] + mi := &file_proto_room_v1_room_proto_msgTypes[145] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11605,7 +11694,7 @@ func (x *ListRoomOnlineUsersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomOnlineUsersRequest.ProtoReflect.Descriptor instead. func (*ListRoomOnlineUsersRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{144} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{145} } func (x *ListRoomOnlineUsersRequest) GetMeta() *RequestMeta { @@ -11665,7 +11754,7 @@ type ListRoomOnlineUsersResponse struct { func (x *ListRoomOnlineUsersResponse) Reset() { *x = ListRoomOnlineUsersResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[145] + mi := &file_proto_room_v1_room_proto_msgTypes[146] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11677,7 +11766,7 @@ func (x *ListRoomOnlineUsersResponse) String() string { func (*ListRoomOnlineUsersResponse) ProtoMessage() {} func (x *ListRoomOnlineUsersResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[145] + mi := &file_proto_room_v1_room_proto_msgTypes[146] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11690,7 +11779,7 @@ func (x *ListRoomOnlineUsersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomOnlineUsersResponse.ProtoReflect.Descriptor instead. func (*ListRoomOnlineUsersResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{145} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{146} } func (x *ListRoomOnlineUsersResponse) GetUsers() []*RoomUser { @@ -11752,7 +11841,7 @@ type RoomBannedUser struct { func (x *RoomBannedUser) Reset() { *x = RoomBannedUser{} - mi := &file_proto_room_v1_room_proto_msgTypes[146] + mi := &file_proto_room_v1_room_proto_msgTypes[147] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11764,7 +11853,7 @@ func (x *RoomBannedUser) String() string { func (*RoomBannedUser) ProtoMessage() {} func (x *RoomBannedUser) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[146] + mi := &file_proto_room_v1_room_proto_msgTypes[147] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11777,7 +11866,7 @@ func (x *RoomBannedUser) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomBannedUser.ProtoReflect.Descriptor instead. func (*RoomBannedUser) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{146} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{147} } func (x *RoomBannedUser) GetUserId() int64 { @@ -11837,7 +11926,7 @@ type ListRoomBannedUsersRequest struct { func (x *ListRoomBannedUsersRequest) Reset() { *x = ListRoomBannedUsersRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[147] + mi := &file_proto_room_v1_room_proto_msgTypes[148] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11849,7 +11938,7 @@ func (x *ListRoomBannedUsersRequest) String() string { func (*ListRoomBannedUsersRequest) ProtoMessage() {} func (x *ListRoomBannedUsersRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[147] + mi := &file_proto_room_v1_room_proto_msgTypes[148] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11862,7 +11951,7 @@ func (x *ListRoomBannedUsersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomBannedUsersRequest.ProtoReflect.Descriptor instead. func (*ListRoomBannedUsersRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{147} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{148} } func (x *ListRoomBannedUsersRequest) GetMeta() *RequestMeta { @@ -11914,7 +12003,7 @@ type ListRoomBannedUsersResponse struct { func (x *ListRoomBannedUsersResponse) Reset() { *x = ListRoomBannedUsersResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[148] + mi := &file_proto_room_v1_room_proto_msgTypes[149] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11926,7 +12015,7 @@ func (x *ListRoomBannedUsersResponse) String() string { func (*ListRoomBannedUsersResponse) ProtoMessage() {} func (x *ListRoomBannedUsersResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[148] + mi := &file_proto_room_v1_room_proto_msgTypes[149] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11939,7 +12028,7 @@ func (x *ListRoomBannedUsersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomBannedUsersResponse.ProtoReflect.Descriptor instead. func (*ListRoomBannedUsersResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{148} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{149} } func (x *ListRoomBannedUsersResponse) GetItems() []*RoomBannedUser { @@ -11991,7 +12080,7 @@ type FollowRoomRequest struct { func (x *FollowRoomRequest) Reset() { *x = FollowRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[149] + mi := &file_proto_room_v1_room_proto_msgTypes[150] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12003,7 +12092,7 @@ func (x *FollowRoomRequest) String() string { func (*FollowRoomRequest) ProtoMessage() {} func (x *FollowRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[149] + mi := &file_proto_room_v1_room_proto_msgTypes[150] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12016,7 +12105,7 @@ func (x *FollowRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FollowRoomRequest.ProtoReflect.Descriptor instead. func (*FollowRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{149} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{150} } func (x *FollowRoomRequest) GetMeta() *RequestMeta { @@ -12053,7 +12142,7 @@ type FollowRoomResponse struct { func (x *FollowRoomResponse) Reset() { *x = FollowRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[150] + mi := &file_proto_room_v1_room_proto_msgTypes[151] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12065,7 +12154,7 @@ func (x *FollowRoomResponse) String() string { func (*FollowRoomResponse) ProtoMessage() {} func (x *FollowRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[150] + mi := &file_proto_room_v1_room_proto_msgTypes[151] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12078,7 +12167,7 @@ func (x *FollowRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use FollowRoomResponse.ProtoReflect.Descriptor instead. func (*FollowRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{150} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{151} } func (x *FollowRoomResponse) GetRoomId() string { @@ -12122,7 +12211,7 @@ type UnfollowRoomRequest struct { func (x *UnfollowRoomRequest) Reset() { *x = UnfollowRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[151] + mi := &file_proto_room_v1_room_proto_msgTypes[152] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12134,7 +12223,7 @@ func (x *UnfollowRoomRequest) String() string { func (*UnfollowRoomRequest) ProtoMessage() {} func (x *UnfollowRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[151] + mi := &file_proto_room_v1_room_proto_msgTypes[152] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12147,7 +12236,7 @@ func (x *UnfollowRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnfollowRoomRequest.ProtoReflect.Descriptor instead. func (*UnfollowRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{151} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{152} } func (x *UnfollowRoomRequest) GetMeta() *RequestMeta { @@ -12183,7 +12272,7 @@ type UnfollowRoomResponse struct { func (x *UnfollowRoomResponse) Reset() { *x = UnfollowRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[152] + mi := &file_proto_room_v1_room_proto_msgTypes[153] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12195,7 +12284,7 @@ func (x *UnfollowRoomResponse) String() string { func (*UnfollowRoomResponse) ProtoMessage() {} func (x *UnfollowRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[152] + mi := &file_proto_room_v1_room_proto_msgTypes[153] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12208,7 +12297,7 @@ func (x *UnfollowRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnfollowRoomResponse.ProtoReflect.Descriptor instead. func (*UnfollowRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{152} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{153} } func (x *UnfollowRoomResponse) GetRoomId() string { @@ -13357,313 +13446,227 @@ var file_proto_room_v1_room_proto_rawDesc = []byte{ 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, 0x22, 0xa6, 0x01, 0x0a, 0x10, - 0x4a, 0x6f, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2b, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, - 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, - 0x73, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, - 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x46, 0x0a, 0x14, 0x52, 0x6f, 0x6f, 0x6d, 0x48, 0x65, 0x61, 0x72, - 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, - 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0xab, 0x01, 0x0a, - 0x15, 0x52, 0x6f, 0x6f, 0x6d, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, - 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2b, 0x0a, 0x04, - 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, - 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, - 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x42, 0x0a, 0x10, 0x4c, 0x65, - 0x61, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, - 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x7a, - 0x0a, 0x11, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, - 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, - 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x5a, 0x0a, 0x10, 0x43, 0x6c, - 0x6f, 0x73, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, - 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x16, - 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x7a, 0x0a, 0x11, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x52, - 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, 0x6f, - 0x6f, 0x6d, 0x22, 0x8f, 0x05, 0x0a, 0x11, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, - 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, - 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x6f, 0x6f, 0x6d, 0x53, 0x68, - 0x6f, 0x72, 0x74, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, - 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x55, - 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x5f, 0x72, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x6f, 0x73, - 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x6c, 0x6f, 0x73, 0x65, - 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x0f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x42, 0x79, 0x41, 0x64, 0x6d, - 0x69, 0x6e, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x5f, 0x62, - 0x79, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x11, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x42, 0x79, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6c, 0x6f, - 0x73, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x65, 0x61, 0x74, 0x18, - 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x68, 0x65, 0x61, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x6f, - 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x0b, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, - 0x0a, 0x0a, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x09, 0x73, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, 0x0a, - 0x13, 0x6f, 0x63, 0x63, 0x75, 0x70, 0x69, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x6f, 0x63, 0x63, 0x75, - 0x70, 0x69, 0x65, 0x64, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, - 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x22, 0x0a, 0x0d, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x12, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, - 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, - 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, - 0x41, 0x74, 0x4d, 0x73, 0x22, 0xba, 0x02, 0x0a, 0x15, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, - 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, - 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, - 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, - 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x17, 0x0a, - 0x07, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x62, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x73, 0x6f, 0x72, 0x74, 0x42, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x64, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x73, 0x6f, 0x72, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, - 0x0d, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x22, 0x8c, 0x01, 0x0a, 0x16, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x05, - 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x72, - 0x6f, 0x6f, 0x6d, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, - 0x22, 0x5e, 0x0a, 0x13, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, - 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, - 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, - 0x22, 0x72, 0x0a, 0x14, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, - 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, - 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x12, 0x24, - 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, - 0x6d, 0x65, 0x4d, 0x73, 0x22, 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, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x6f, 0x64, 0x65, 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, 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, + 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, 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, + 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, 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, + 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, @@ -13671,481 +13674,544 @@ var file_proto_room_v1_room_proto_rawDesc = []byte{ 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, + 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, 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, + 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, 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, + 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, 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, + 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, 0x22, 0x7a, - 0x0a, 0x11, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 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, 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, 0xe2, - 0x06, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 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, 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, 0x22, 0xed, 0x04, 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, 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, 0xed, 0x02, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, + 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, 0xe2, 0x06, 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, 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, - 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, + 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, 0x22, 0xed, 0x04, 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, 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, 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, @@ -14160,236 +14226,219 @@ var file_proto_room_v1_room_proto_rawDesc = []byte{ 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, + 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, 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, 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, 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, + 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, @@ -14397,425 +14446,483 @@ var file_proto_room_v1_room_proto_rawDesc = []byte{ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x55, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, - 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, - 0x53, 0x69, 0x7a, 0x65, 0x22, 0xbf, 0x01, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, - 0x6d, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x55, 0x73, - 0x65, 0x72, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, - 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, - 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, - 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, - 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, - 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x75, 0x0a, 0x11, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, - 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, - 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x72, - 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, - 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x95, 0x01, - 0x0a, 0x12, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x1a, 0x0a, - 0x08, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x08, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x6c, - 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0c, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, - 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, - 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x77, 0x0a, 0x13, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, - 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, - 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, - 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, - 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x71, - 0x0a, 0x14, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, - 0x1a, 0x0a, 0x08, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x08, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, - 0x73, 0x32, 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, + 0x72, 0x49, 0x64, 0x22, 0x74, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, + 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x06, + 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, + 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x72, 0x6f, 0x63, + 0x6b, 0x65, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xd0, 0x01, 0x0a, 0x1a, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x65, 0x72, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, + 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, + 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x76, 0x69, 0x65, 0x77, 0x65, + 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, + 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, + 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6f, 0x72, 0x74, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x22, 0xee, 0x01, 0x0a, + 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x55, + 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x05, + 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, + 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, + 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, + 0x7a, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x33, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, + 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x4f, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0xd2, 0x01, + 0x0a, 0x0e, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, + 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, + 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x22, 0x0a, + 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, + 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x75, 0x6e, 0x62, 0x61, 0x6e, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x6e, 0x62, 0x61, 0x6e, 0x41, 0x74, 0x4d, + 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6d, + 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, + 0x6e, 0x67, 0x4d, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, + 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, + 0x6e, 0x74, 0x22, 0xbc, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, + 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, + 0x61, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x76, 0x69, + 0x65, 0x77, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0c, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, + 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, + 0x65, 0x22, 0xbf, 0x01, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, + 0x6e, 0x6e, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x33, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, + 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x12, 0x0a, 0x04, + 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, + 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x24, 0x0a, + 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, + 0x65, 0x4d, 0x73, 0x22, 0x75, 0x0a, 0x11, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, + 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, + 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, + 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x95, 0x01, 0x0a, 0x12, 0x46, + 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x6f, + 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x66, 0x6f, + 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x24, 0x0a, 0x0e, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, + 0x4d, 0x73, 0x22, 0x77, 0x0a, 0x13, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, + 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, + 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, + 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, + 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x71, 0x0a, 0x14, 0x55, + 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, + 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, + 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x32, 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, 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, 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, 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, + 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, 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, + 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, 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, + 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, 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, + 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, 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, + 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, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xee, 0x01, 0x0a, 0x10, 0x52, 0x6f, 0x6f, 0x6d, 0x47, - 0x75, 0x61, 0x72, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x53, 0x70, 0x65, 0x61, 0x6b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x70, 0x65, 0x61, 0x6b, 0x50, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x70, 0x65, 0x61, 0x6b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, + 0x31, 0x2e, 0x4d, 0x69, 0x63, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x63, + 0x4d, 0x75, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x4d, 0x75, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x4d, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0d, 0x41, 0x70, 0x70, + 0x6c, 0x79, 0x52, 0x54, 0x43, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, + 0x52, 0x54, 0x43, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x54, 0x43, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x53, + 0x65, 0x61, 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x53, 0x65, + 0x61, 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x74, 0x4d, 0x69, 0x63, 0x53, 0x65, 0x61, 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x74, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x74, 0x45, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, + 0x43, 0x68, 0x61, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, + 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x41, 0x64, 0x6d, + 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, + 0x6d, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, + 0x0a, 0x08, 0x4d, 0x75, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x65, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x65, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x4b, + 0x69, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x09, 0x55, 0x6e, 0x62, 0x61, + 0x6e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x45, 0x76, 0x69, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x25, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x45, 0x76, 0x69, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x76, 0x69, 0x63, 0x74, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x53, 0x65, + 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x12, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0a, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, + 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, + 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x55, 0x6e, + 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x66, 0x6f, 0x6c, + 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x32, 0xee, 0x01, 0x0a, 0x10, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x75, 0x61, 0x72, + 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x53, 0x70, 0x65, 0x61, 0x6b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x70, 0x65, 0x61, 0x6b, 0x50, 0x65, 0x72, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x53, 0x70, 0x65, 0x61, 0x6b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x56, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, + 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, - 0x63, 0x65, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, - 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x72, 0x65, - 0x73, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, - 0x69, 0x66, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 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, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x32, 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, 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, + 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, 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, + 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, 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, + 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, - 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, + 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, } var ( @@ -14830,7 +14937,7 @@ func file_proto_room_v1_room_proto_rawDescGZIP() []byte { return file_proto_room_v1_room_proto_rawDescData } -var file_proto_room_v1_room_proto_msgTypes = make([]protoimpl.MessageInfo, 154) +var file_proto_room_v1_room_proto_msgTypes = make([]protoimpl.MessageInfo, 155) var file_proto_room_v1_room_proto_goTypes = []any{ (*RequestMeta)(nil), // 0: hyapp.room.v1.RequestMeta (*CommandResult)(nil), // 1: hyapp.room.v1.CommandResult @@ -14901,91 +15008,92 @@ var file_proto_room_v1_room_proto_goTypes = []any{ (*RoomEntryVehicleSnapshot)(nil), // 66: hyapp.room.v1.RoomEntryVehicleSnapshot (*RoomUserDisplayProfile)(nil), // 67: hyapp.room.v1.RoomUserDisplayProfile (*JoinRoomRequest)(nil), // 68: hyapp.room.v1.JoinRoomRequest - (*JoinRoomResponse)(nil), // 69: hyapp.room.v1.JoinRoomResponse - (*RoomHeartbeatRequest)(nil), // 70: hyapp.room.v1.RoomHeartbeatRequest - (*RoomHeartbeatResponse)(nil), // 71: hyapp.room.v1.RoomHeartbeatResponse - (*LeaveRoomRequest)(nil), // 72: hyapp.room.v1.LeaveRoomRequest - (*LeaveRoomResponse)(nil), // 73: hyapp.room.v1.LeaveRoomResponse - (*CloseRoomRequest)(nil), // 74: hyapp.room.v1.CloseRoomRequest - (*CloseRoomResponse)(nil), // 75: hyapp.room.v1.CloseRoomResponse - (*AdminRoomListItem)(nil), // 76: hyapp.room.v1.AdminRoomListItem - (*AdminListRoomsRequest)(nil), // 77: hyapp.room.v1.AdminListRoomsRequest - (*AdminListRoomsResponse)(nil), // 78: hyapp.room.v1.AdminListRoomsResponse - (*AdminGetRoomRequest)(nil), // 79: hyapp.room.v1.AdminGetRoomRequest - (*AdminGetRoomResponse)(nil), // 80: hyapp.room.v1.AdminGetRoomResponse - (*AdminUpdateRoomRequest)(nil), // 81: hyapp.room.v1.AdminUpdateRoomRequest - (*AdminUpdateRoomResponse)(nil), // 82: hyapp.room.v1.AdminUpdateRoomResponse - (*AdminDeleteRoomRequest)(nil), // 83: hyapp.room.v1.AdminDeleteRoomRequest - (*AdminDeleteRoomResponse)(nil), // 84: hyapp.room.v1.AdminDeleteRoomResponse - (*MicUpRequest)(nil), // 85: hyapp.room.v1.MicUpRequest - (*MicUpResponse)(nil), // 86: hyapp.room.v1.MicUpResponse - (*MicDownRequest)(nil), // 87: hyapp.room.v1.MicDownRequest - (*MicDownResponse)(nil), // 88: hyapp.room.v1.MicDownResponse - (*ChangeMicSeatRequest)(nil), // 89: hyapp.room.v1.ChangeMicSeatRequest - (*ChangeMicSeatResponse)(nil), // 90: hyapp.room.v1.ChangeMicSeatResponse - (*ConfirmMicPublishingRequest)(nil), // 91: hyapp.room.v1.ConfirmMicPublishingRequest - (*ConfirmMicPublishingResponse)(nil), // 92: hyapp.room.v1.ConfirmMicPublishingResponse - (*MicHeartbeatRequest)(nil), // 93: hyapp.room.v1.MicHeartbeatRequest - (*MicHeartbeatResponse)(nil), // 94: hyapp.room.v1.MicHeartbeatResponse - (*SetMicMuteRequest)(nil), // 95: hyapp.room.v1.SetMicMuteRequest - (*SetMicMuteResponse)(nil), // 96: hyapp.room.v1.SetMicMuteResponse - (*ApplyRTCEventRequest)(nil), // 97: hyapp.room.v1.ApplyRTCEventRequest - (*ApplyRTCEventResponse)(nil), // 98: hyapp.room.v1.ApplyRTCEventResponse - (*SetMicSeatLockRequest)(nil), // 99: hyapp.room.v1.SetMicSeatLockRequest - (*SetMicSeatLockResponse)(nil), // 100: hyapp.room.v1.SetMicSeatLockResponse - (*SetChatEnabledRequest)(nil), // 101: hyapp.room.v1.SetChatEnabledRequest - (*SetChatEnabledResponse)(nil), // 102: hyapp.room.v1.SetChatEnabledResponse - (*SetRoomPasswordRequest)(nil), // 103: hyapp.room.v1.SetRoomPasswordRequest - (*SetRoomPasswordResponse)(nil), // 104: hyapp.room.v1.SetRoomPasswordResponse - (*SetRoomAdminRequest)(nil), // 105: hyapp.room.v1.SetRoomAdminRequest - (*SetRoomAdminResponse)(nil), // 106: hyapp.room.v1.SetRoomAdminResponse - (*MuteUserRequest)(nil), // 107: hyapp.room.v1.MuteUserRequest - (*MuteUserResponse)(nil), // 108: hyapp.room.v1.MuteUserResponse - (*KickUserRequest)(nil), // 109: hyapp.room.v1.KickUserRequest - (*KickUserResponse)(nil), // 110: hyapp.room.v1.KickUserResponse - (*UnbanUserRequest)(nil), // 111: hyapp.room.v1.UnbanUserRequest - (*UnbanUserResponse)(nil), // 112: hyapp.room.v1.UnbanUserResponse - (*SystemEvictUserRequest)(nil), // 113: hyapp.room.v1.SystemEvictUserRequest - (*SystemEvictUserResponse)(nil), // 114: hyapp.room.v1.SystemEvictUserResponse - (*SendGiftTargetHostScope)(nil), // 115: hyapp.room.v1.SendGiftTargetHostScope - (*SendGiftDisplayProfile)(nil), // 116: hyapp.room.v1.SendGiftDisplayProfile - (*SendGiftBatchTarget)(nil), // 117: hyapp.room.v1.SendGiftBatchTarget - (*SendGiftBatchDisplay)(nil), // 118: hyapp.room.v1.SendGiftBatchDisplay - (*SendGiftRequest)(nil), // 119: hyapp.room.v1.SendGiftRequest - (*SendGiftResponse)(nil), // 120: hyapp.room.v1.SendGiftResponse - (*CheckSpeakPermissionRequest)(nil), // 121: hyapp.room.v1.CheckSpeakPermissionRequest - (*CheckSpeakPermissionResponse)(nil), // 122: hyapp.room.v1.CheckSpeakPermissionResponse - (*VerifyRoomPresenceRequest)(nil), // 123: hyapp.room.v1.VerifyRoomPresenceRequest - (*VerifyRoomPresenceResponse)(nil), // 124: hyapp.room.v1.VerifyRoomPresenceResponse - (*ListRoomsRequest)(nil), // 125: hyapp.room.v1.ListRoomsRequest - (*ListRoomsByOwnersRequest)(nil), // 126: hyapp.room.v1.ListRoomsByOwnersRequest - (*ListRoomFeedsRequest)(nil), // 127: hyapp.room.v1.ListRoomFeedsRequest - (*ListRoomGiftLeaderboardRequest)(nil), // 128: hyapp.room.v1.ListRoomGiftLeaderboardRequest - (*RoomFeedRelatedUser)(nil), // 129: hyapp.room.v1.RoomFeedRelatedUser - (*RoomListItem)(nil), // 130: hyapp.room.v1.RoomListItem - (*ListRoomsResponse)(nil), // 131: hyapp.room.v1.ListRoomsResponse - (*RoomGiftLeaderboardItem)(nil), // 132: hyapp.room.v1.RoomGiftLeaderboardItem - (*ListRoomGiftLeaderboardResponse)(nil), // 133: hyapp.room.v1.ListRoomGiftLeaderboardResponse - (*ListRoomContributionRankRequest)(nil), // 134: hyapp.room.v1.ListRoomContributionRankRequest - (*ListRoomContributionRankResponse)(nil), // 135: hyapp.room.v1.ListRoomContributionRankResponse - (*GetMyRoomRequest)(nil), // 136: hyapp.room.v1.GetMyRoomRequest - (*GetMyRoomResponse)(nil), // 137: hyapp.room.v1.GetMyRoomResponse - (*GetCurrentRoomRequest)(nil), // 138: hyapp.room.v1.GetCurrentRoomRequest - (*GetCurrentRoomResponse)(nil), // 139: hyapp.room.v1.GetCurrentRoomResponse - (*GetRoomSnapshotRequest)(nil), // 140: hyapp.room.v1.GetRoomSnapshotRequest - (*GetRoomSnapshotResponse)(nil), // 141: hyapp.room.v1.GetRoomSnapshotResponse - (*GetRoomRocketRequest)(nil), // 142: hyapp.room.v1.GetRoomRocketRequest - (*GetRoomRocketResponse)(nil), // 143: hyapp.room.v1.GetRoomRocketResponse - (*ListRoomOnlineUsersRequest)(nil), // 144: hyapp.room.v1.ListRoomOnlineUsersRequest - (*ListRoomOnlineUsersResponse)(nil), // 145: hyapp.room.v1.ListRoomOnlineUsersResponse - (*RoomBannedUser)(nil), // 146: hyapp.room.v1.RoomBannedUser - (*ListRoomBannedUsersRequest)(nil), // 147: hyapp.room.v1.ListRoomBannedUsersRequest - (*ListRoomBannedUsersResponse)(nil), // 148: hyapp.room.v1.ListRoomBannedUsersResponse - (*FollowRoomRequest)(nil), // 149: hyapp.room.v1.FollowRoomRequest - (*FollowRoomResponse)(nil), // 150: hyapp.room.v1.FollowRoomResponse - (*UnfollowRoomRequest)(nil), // 151: hyapp.room.v1.UnfollowRoomRequest - (*UnfollowRoomResponse)(nil), // 152: hyapp.room.v1.UnfollowRoomResponse - nil, // 153: hyapp.room.v1.RoomSnapshot.RoomExtEntry + (*RoomEffectiveVipSnapshot)(nil), // 69: hyapp.room.v1.RoomEffectiveVipSnapshot + (*JoinRoomResponse)(nil), // 70: hyapp.room.v1.JoinRoomResponse + (*RoomHeartbeatRequest)(nil), // 71: hyapp.room.v1.RoomHeartbeatRequest + (*RoomHeartbeatResponse)(nil), // 72: hyapp.room.v1.RoomHeartbeatResponse + (*LeaveRoomRequest)(nil), // 73: hyapp.room.v1.LeaveRoomRequest + (*LeaveRoomResponse)(nil), // 74: hyapp.room.v1.LeaveRoomResponse + (*CloseRoomRequest)(nil), // 75: hyapp.room.v1.CloseRoomRequest + (*CloseRoomResponse)(nil), // 76: hyapp.room.v1.CloseRoomResponse + (*AdminRoomListItem)(nil), // 77: hyapp.room.v1.AdminRoomListItem + (*AdminListRoomsRequest)(nil), // 78: hyapp.room.v1.AdminListRoomsRequest + (*AdminListRoomsResponse)(nil), // 79: hyapp.room.v1.AdminListRoomsResponse + (*AdminGetRoomRequest)(nil), // 80: hyapp.room.v1.AdminGetRoomRequest + (*AdminGetRoomResponse)(nil), // 81: hyapp.room.v1.AdminGetRoomResponse + (*AdminUpdateRoomRequest)(nil), // 82: hyapp.room.v1.AdminUpdateRoomRequest + (*AdminUpdateRoomResponse)(nil), // 83: hyapp.room.v1.AdminUpdateRoomResponse + (*AdminDeleteRoomRequest)(nil), // 84: hyapp.room.v1.AdminDeleteRoomRequest + (*AdminDeleteRoomResponse)(nil), // 85: hyapp.room.v1.AdminDeleteRoomResponse + (*MicUpRequest)(nil), // 86: hyapp.room.v1.MicUpRequest + (*MicUpResponse)(nil), // 87: hyapp.room.v1.MicUpResponse + (*MicDownRequest)(nil), // 88: hyapp.room.v1.MicDownRequest + (*MicDownResponse)(nil), // 89: hyapp.room.v1.MicDownResponse + (*ChangeMicSeatRequest)(nil), // 90: hyapp.room.v1.ChangeMicSeatRequest + (*ChangeMicSeatResponse)(nil), // 91: hyapp.room.v1.ChangeMicSeatResponse + (*ConfirmMicPublishingRequest)(nil), // 92: hyapp.room.v1.ConfirmMicPublishingRequest + (*ConfirmMicPublishingResponse)(nil), // 93: hyapp.room.v1.ConfirmMicPublishingResponse + (*MicHeartbeatRequest)(nil), // 94: hyapp.room.v1.MicHeartbeatRequest + (*MicHeartbeatResponse)(nil), // 95: hyapp.room.v1.MicHeartbeatResponse + (*SetMicMuteRequest)(nil), // 96: hyapp.room.v1.SetMicMuteRequest + (*SetMicMuteResponse)(nil), // 97: hyapp.room.v1.SetMicMuteResponse + (*ApplyRTCEventRequest)(nil), // 98: hyapp.room.v1.ApplyRTCEventRequest + (*ApplyRTCEventResponse)(nil), // 99: hyapp.room.v1.ApplyRTCEventResponse + (*SetMicSeatLockRequest)(nil), // 100: hyapp.room.v1.SetMicSeatLockRequest + (*SetMicSeatLockResponse)(nil), // 101: hyapp.room.v1.SetMicSeatLockResponse + (*SetChatEnabledRequest)(nil), // 102: hyapp.room.v1.SetChatEnabledRequest + (*SetChatEnabledResponse)(nil), // 103: hyapp.room.v1.SetChatEnabledResponse + (*SetRoomPasswordRequest)(nil), // 104: hyapp.room.v1.SetRoomPasswordRequest + (*SetRoomPasswordResponse)(nil), // 105: hyapp.room.v1.SetRoomPasswordResponse + (*SetRoomAdminRequest)(nil), // 106: hyapp.room.v1.SetRoomAdminRequest + (*SetRoomAdminResponse)(nil), // 107: hyapp.room.v1.SetRoomAdminResponse + (*MuteUserRequest)(nil), // 108: hyapp.room.v1.MuteUserRequest + (*MuteUserResponse)(nil), // 109: hyapp.room.v1.MuteUserResponse + (*KickUserRequest)(nil), // 110: hyapp.room.v1.KickUserRequest + (*KickUserResponse)(nil), // 111: hyapp.room.v1.KickUserResponse + (*UnbanUserRequest)(nil), // 112: hyapp.room.v1.UnbanUserRequest + (*UnbanUserResponse)(nil), // 113: hyapp.room.v1.UnbanUserResponse + (*SystemEvictUserRequest)(nil), // 114: hyapp.room.v1.SystemEvictUserRequest + (*SystemEvictUserResponse)(nil), // 115: hyapp.room.v1.SystemEvictUserResponse + (*SendGiftTargetHostScope)(nil), // 116: hyapp.room.v1.SendGiftTargetHostScope + (*SendGiftDisplayProfile)(nil), // 117: hyapp.room.v1.SendGiftDisplayProfile + (*SendGiftBatchTarget)(nil), // 118: hyapp.room.v1.SendGiftBatchTarget + (*SendGiftBatchDisplay)(nil), // 119: hyapp.room.v1.SendGiftBatchDisplay + (*SendGiftRequest)(nil), // 120: hyapp.room.v1.SendGiftRequest + (*SendGiftResponse)(nil), // 121: hyapp.room.v1.SendGiftResponse + (*CheckSpeakPermissionRequest)(nil), // 122: hyapp.room.v1.CheckSpeakPermissionRequest + (*CheckSpeakPermissionResponse)(nil), // 123: hyapp.room.v1.CheckSpeakPermissionResponse + (*VerifyRoomPresenceRequest)(nil), // 124: hyapp.room.v1.VerifyRoomPresenceRequest + (*VerifyRoomPresenceResponse)(nil), // 125: hyapp.room.v1.VerifyRoomPresenceResponse + (*ListRoomsRequest)(nil), // 126: hyapp.room.v1.ListRoomsRequest + (*ListRoomsByOwnersRequest)(nil), // 127: hyapp.room.v1.ListRoomsByOwnersRequest + (*ListRoomFeedsRequest)(nil), // 128: hyapp.room.v1.ListRoomFeedsRequest + (*ListRoomGiftLeaderboardRequest)(nil), // 129: hyapp.room.v1.ListRoomGiftLeaderboardRequest + (*RoomFeedRelatedUser)(nil), // 130: hyapp.room.v1.RoomFeedRelatedUser + (*RoomListItem)(nil), // 131: hyapp.room.v1.RoomListItem + (*ListRoomsResponse)(nil), // 132: hyapp.room.v1.ListRoomsResponse + (*RoomGiftLeaderboardItem)(nil), // 133: hyapp.room.v1.RoomGiftLeaderboardItem + (*ListRoomGiftLeaderboardResponse)(nil), // 134: hyapp.room.v1.ListRoomGiftLeaderboardResponse + (*ListRoomContributionRankRequest)(nil), // 135: hyapp.room.v1.ListRoomContributionRankRequest + (*ListRoomContributionRankResponse)(nil), // 136: hyapp.room.v1.ListRoomContributionRankResponse + (*GetMyRoomRequest)(nil), // 137: hyapp.room.v1.GetMyRoomRequest + (*GetMyRoomResponse)(nil), // 138: hyapp.room.v1.GetMyRoomResponse + (*GetCurrentRoomRequest)(nil), // 139: hyapp.room.v1.GetCurrentRoomRequest + (*GetCurrentRoomResponse)(nil), // 140: hyapp.room.v1.GetCurrentRoomResponse + (*GetRoomSnapshotRequest)(nil), // 141: hyapp.room.v1.GetRoomSnapshotRequest + (*GetRoomSnapshotResponse)(nil), // 142: hyapp.room.v1.GetRoomSnapshotResponse + (*GetRoomRocketRequest)(nil), // 143: hyapp.room.v1.GetRoomRocketRequest + (*GetRoomRocketResponse)(nil), // 144: hyapp.room.v1.GetRoomRocketResponse + (*ListRoomOnlineUsersRequest)(nil), // 145: hyapp.room.v1.ListRoomOnlineUsersRequest + (*ListRoomOnlineUsersResponse)(nil), // 146: hyapp.room.v1.ListRoomOnlineUsersResponse + (*RoomBannedUser)(nil), // 147: hyapp.room.v1.RoomBannedUser + (*ListRoomBannedUsersRequest)(nil), // 148: hyapp.room.v1.ListRoomBannedUsersRequest + (*ListRoomBannedUsersResponse)(nil), // 149: hyapp.room.v1.ListRoomBannedUsersResponse + (*FollowRoomRequest)(nil), // 150: hyapp.room.v1.FollowRoomRequest + (*FollowRoomResponse)(nil), // 151: hyapp.room.v1.FollowRoomResponse + (*UnfollowRoomRequest)(nil), // 152: hyapp.room.v1.UnfollowRoomRequest + (*UnfollowRoomResponse)(nil), // 153: hyapp.room.v1.UnfollowRoomResponse + nil, // 154: hyapp.room.v1.RoomSnapshot.RoomExtEntry } var file_proto_room_v1_room_proto_depIdxs = []int32{ 8, // 0: hyapp.room.v1.RoomRocketLevel.in_room_rewards:type_name -> hyapp.room.v1.RoomRocketRewardItem @@ -15034,7 +15142,7 @@ var file_proto_room_v1_room_proto_depIdxs = []int32{ 4, // 43: hyapp.room.v1.RoomSnapshot.mic_seats:type_name -> hyapp.room.v1.SeatState 2, // 44: hyapp.room.v1.RoomSnapshot.online_users:type_name -> hyapp.room.v1.RoomUser 5, // 45: hyapp.room.v1.RoomSnapshot.gift_rank:type_name -> hyapp.room.v1.RankItem - 153, // 46: hyapp.room.v1.RoomSnapshot.room_ext:type_name -> hyapp.room.v1.RoomSnapshot.RoomExtEntry + 154, // 46: hyapp.room.v1.RoomSnapshot.room_ext:type_name -> hyapp.room.v1.RoomSnapshot.RoomExtEntry 13, // 47: hyapp.room.v1.RoomSnapshot.rocket:type_name -> hyapp.room.v1.RoomRocketState 53, // 48: hyapp.room.v1.RoomSnapshot.ban_states:type_name -> hyapp.room.v1.RoomBanState 0, // 49: hyapp.room.v1.SaveRoomBackgroundRequest.meta:type_name -> hyapp.room.v1.RequestMeta @@ -15057,234 +15165,235 @@ var file_proto_room_v1_room_proto_depIdxs = []int32{ 1, // 66: hyapp.room.v1.JoinRoomResponse.result:type_name -> hyapp.room.v1.CommandResult 2, // 67: hyapp.room.v1.JoinRoomResponse.user:type_name -> hyapp.room.v1.RoomUser 54, // 68: hyapp.room.v1.JoinRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 69: hyapp.room.v1.RoomHeartbeatRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 70: hyapp.room.v1.RoomHeartbeatResponse.result:type_name -> hyapp.room.v1.CommandResult - 2, // 71: hyapp.room.v1.RoomHeartbeatResponse.user:type_name -> hyapp.room.v1.RoomUser - 54, // 72: hyapp.room.v1.RoomHeartbeatResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 73: hyapp.room.v1.LeaveRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 74: hyapp.room.v1.LeaveRoomResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 75: hyapp.room.v1.LeaveRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 76: hyapp.room.v1.CloseRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 77: hyapp.room.v1.CloseRoomResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 78: hyapp.room.v1.CloseRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 79: hyapp.room.v1.AdminListRoomsRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 76, // 80: hyapp.room.v1.AdminListRoomsResponse.rooms:type_name -> hyapp.room.v1.AdminRoomListItem - 0, // 81: hyapp.room.v1.AdminGetRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 76, // 82: hyapp.room.v1.AdminGetRoomResponse.room:type_name -> hyapp.room.v1.AdminRoomListItem - 0, // 83: hyapp.room.v1.AdminUpdateRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 84: hyapp.room.v1.AdminUpdateRoomResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 85: hyapp.room.v1.AdminUpdateRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 86: hyapp.room.v1.AdminDeleteRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 87: hyapp.room.v1.AdminDeleteRoomResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 88: hyapp.room.v1.AdminDeleteRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 89: hyapp.room.v1.MicUpRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 67, // 90: hyapp.room.v1.MicUpRequest.target_display_profile:type_name -> hyapp.room.v1.RoomUserDisplayProfile - 1, // 91: hyapp.room.v1.MicUpResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 92: hyapp.room.v1.MicUpResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 93: hyapp.room.v1.MicDownRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 67, // 94: hyapp.room.v1.MicDownRequest.target_display_profile:type_name -> hyapp.room.v1.RoomUserDisplayProfile - 1, // 95: hyapp.room.v1.MicDownResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 96: hyapp.room.v1.MicDownResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 97: hyapp.room.v1.ChangeMicSeatRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 67, // 98: hyapp.room.v1.ChangeMicSeatRequest.target_display_profile:type_name -> hyapp.room.v1.RoomUserDisplayProfile - 1, // 99: hyapp.room.v1.ChangeMicSeatResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 100: hyapp.room.v1.ChangeMicSeatResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 101: hyapp.room.v1.ConfirmMicPublishingRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 67, // 102: hyapp.room.v1.ConfirmMicPublishingRequest.target_display_profile:type_name -> hyapp.room.v1.RoomUserDisplayProfile - 1, // 103: hyapp.room.v1.ConfirmMicPublishingResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 104: hyapp.room.v1.ConfirmMicPublishingResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 105: hyapp.room.v1.MicHeartbeatRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 106: hyapp.room.v1.MicHeartbeatResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 107: hyapp.room.v1.MicHeartbeatResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 108: hyapp.room.v1.SetMicMuteRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 67, // 109: hyapp.room.v1.SetMicMuteRequest.target_display_profile:type_name -> hyapp.room.v1.RoomUserDisplayProfile - 1, // 110: hyapp.room.v1.SetMicMuteResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 111: hyapp.room.v1.SetMicMuteResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 112: hyapp.room.v1.ApplyRTCEventRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 113: hyapp.room.v1.ApplyRTCEventResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 114: hyapp.room.v1.ApplyRTCEventResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 115: hyapp.room.v1.SetMicSeatLockRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 116: hyapp.room.v1.SetMicSeatLockResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 117: hyapp.room.v1.SetMicSeatLockResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 118: hyapp.room.v1.SetChatEnabledRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 119: hyapp.room.v1.SetChatEnabledResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 120: hyapp.room.v1.SetChatEnabledResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 121: hyapp.room.v1.SetRoomPasswordRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 122: hyapp.room.v1.SetRoomPasswordResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 123: hyapp.room.v1.SetRoomPasswordResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 124: hyapp.room.v1.SetRoomAdminRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 125: hyapp.room.v1.SetRoomAdminResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 126: hyapp.room.v1.SetRoomAdminResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 127: hyapp.room.v1.MuteUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 128: hyapp.room.v1.MuteUserResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 129: hyapp.room.v1.MuteUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 130: hyapp.room.v1.KickUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 131: hyapp.room.v1.KickUserResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 132: hyapp.room.v1.KickUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 133: hyapp.room.v1.UnbanUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 134: hyapp.room.v1.UnbanUserResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 135: hyapp.room.v1.UnbanUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 136: hyapp.room.v1.SystemEvictUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 137: hyapp.room.v1.SystemEvictUserResponse.result:type_name -> hyapp.room.v1.CommandResult - 54, // 138: hyapp.room.v1.SystemEvictUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 7, // 139: hyapp.room.v1.SendGiftBatchTarget.lucky_gift:type_name -> hyapp.room.v1.LuckyGiftDrawResult - 117, // 140: hyapp.room.v1.SendGiftBatchDisplay.targets:type_name -> hyapp.room.v1.SendGiftBatchTarget - 0, // 141: hyapp.room.v1.SendGiftRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 115, // 142: hyapp.room.v1.SendGiftRequest.target_host_scopes:type_name -> hyapp.room.v1.SendGiftTargetHostScope - 116, // 143: hyapp.room.v1.SendGiftRequest.sender_display_profile:type_name -> hyapp.room.v1.SendGiftDisplayProfile - 116, // 144: hyapp.room.v1.SendGiftRequest.target_display_profiles:type_name -> hyapp.room.v1.SendGiftDisplayProfile - 1, // 145: hyapp.room.v1.SendGiftResponse.result:type_name -> hyapp.room.v1.CommandResult - 5, // 146: hyapp.room.v1.SendGiftResponse.gift_rank:type_name -> hyapp.room.v1.RankItem - 54, // 147: hyapp.room.v1.SendGiftResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 13, // 148: hyapp.room.v1.SendGiftResponse.rocket:type_name -> hyapp.room.v1.RoomRocketState - 7, // 149: hyapp.room.v1.SendGiftResponse.lucky_gift:type_name -> hyapp.room.v1.LuckyGiftDrawResult - 7, // 150: hyapp.room.v1.SendGiftResponse.lucky_gifts:type_name -> hyapp.room.v1.LuckyGiftDrawResult - 118, // 151: hyapp.room.v1.SendGiftResponse.batch_display:type_name -> hyapp.room.v1.SendGiftBatchDisplay - 0, // 152: hyapp.room.v1.ListRoomsRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 0, // 153: hyapp.room.v1.ListRoomsByOwnersRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 0, // 154: hyapp.room.v1.ListRoomFeedsRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 129, // 155: hyapp.room.v1.ListRoomFeedsRequest.related_users:type_name -> hyapp.room.v1.RoomFeedRelatedUser - 0, // 156: hyapp.room.v1.ListRoomGiftLeaderboardRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 130, // 157: hyapp.room.v1.ListRoomsResponse.rooms:type_name -> hyapp.room.v1.RoomListItem - 130, // 158: hyapp.room.v1.RoomGiftLeaderboardItem.room:type_name -> hyapp.room.v1.RoomListItem - 132, // 159: hyapp.room.v1.ListRoomGiftLeaderboardResponse.items:type_name -> hyapp.room.v1.RoomGiftLeaderboardItem - 0, // 160: hyapp.room.v1.ListRoomContributionRankRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 6, // 161: hyapp.room.v1.ListRoomContributionRankResponse.items:type_name -> hyapp.room.v1.RoomContributionRankItem - 0, // 162: hyapp.room.v1.GetMyRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 130, // 163: hyapp.room.v1.GetMyRoomResponse.room:type_name -> hyapp.room.v1.RoomListItem - 0, // 164: hyapp.room.v1.GetCurrentRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 0, // 165: hyapp.room.v1.GetRoomSnapshotRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 54, // 166: hyapp.room.v1.GetRoomSnapshotResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 167: hyapp.room.v1.GetRoomRocketRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 14, // 168: hyapp.room.v1.GetRoomRocketResponse.rocket:type_name -> hyapp.room.v1.RoomRocketInfo - 0, // 169: hyapp.room.v1.ListRoomOnlineUsersRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 2, // 170: hyapp.room.v1.ListRoomOnlineUsersResponse.users:type_name -> hyapp.room.v1.RoomUser - 3, // 171: hyapp.room.v1.ListRoomOnlineUsersResponse.items:type_name -> hyapp.room.v1.RoomOnlineUser - 0, // 172: hyapp.room.v1.ListRoomBannedUsersRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 146, // 173: hyapp.room.v1.ListRoomBannedUsersResponse.items:type_name -> hyapp.room.v1.RoomBannedUser - 0, // 174: hyapp.room.v1.FollowRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 0, // 175: hyapp.room.v1.UnfollowRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 62, // 176: hyapp.room.v1.RoomCommandService.CreateRoom:input_type -> hyapp.room.v1.CreateRoomRequest - 64, // 177: hyapp.room.v1.RoomCommandService.UpdateRoomProfile:input_type -> hyapp.room.v1.UpdateRoomProfileRequest - 56, // 178: hyapp.room.v1.RoomCommandService.SaveRoomBackground:input_type -> hyapp.room.v1.SaveRoomBackgroundRequest - 60, // 179: hyapp.room.v1.RoomCommandService.SetRoomBackground:input_type -> hyapp.room.v1.SetRoomBackgroundRequest - 68, // 180: hyapp.room.v1.RoomCommandService.JoinRoom:input_type -> hyapp.room.v1.JoinRoomRequest - 70, // 181: hyapp.room.v1.RoomCommandService.RoomHeartbeat:input_type -> hyapp.room.v1.RoomHeartbeatRequest - 72, // 182: hyapp.room.v1.RoomCommandService.LeaveRoom:input_type -> hyapp.room.v1.LeaveRoomRequest - 74, // 183: hyapp.room.v1.RoomCommandService.CloseRoom:input_type -> hyapp.room.v1.CloseRoomRequest - 81, // 184: hyapp.room.v1.RoomCommandService.AdminUpdateRoom:input_type -> hyapp.room.v1.AdminUpdateRoomRequest - 83, // 185: hyapp.room.v1.RoomCommandService.AdminDeleteRoom:input_type -> hyapp.room.v1.AdminDeleteRoomRequest - 19, // 186: hyapp.room.v1.RoomCommandService.AdminUpdateRoomRocketConfig:input_type -> hyapp.room.v1.AdminUpdateRoomRocketConfigRequest - 24, // 187: hyapp.room.v1.RoomCommandService.AdminUpdateRoomSeatConfig:input_type -> hyapp.room.v1.AdminUpdateRoomSeatConfigRequest - 31, // 188: hyapp.room.v1.RoomCommandService.AdminUpdateHumanRoomRobotConfig:input_type -> hyapp.room.v1.AdminUpdateHumanRoomRobotConfigRequest - 37, // 189: hyapp.room.v1.RoomCommandService.AdminCreateRoomPin:input_type -> hyapp.room.v1.AdminCreateRoomPinRequest - 39, // 190: hyapp.room.v1.RoomCommandService.AdminCancelRoomPin:input_type -> hyapp.room.v1.AdminCancelRoomPinRequest - 45, // 191: hyapp.room.v1.RoomCommandService.AdminCreateRobotRoom:input_type -> hyapp.room.v1.AdminCreateRobotRoomRequest - 47, // 192: hyapp.room.v1.RoomCommandService.AdminSetRobotRoomStatus:input_type -> hyapp.room.v1.AdminSetRobotRoomStatusRequest - 49, // 193: hyapp.room.v1.RoomCommandService.AdminRenameOwnerCountryCode:input_type -> hyapp.room.v1.AdminRenameOwnerCountryCodeRequest - 85, // 194: hyapp.room.v1.RoomCommandService.MicUp:input_type -> hyapp.room.v1.MicUpRequest - 87, // 195: hyapp.room.v1.RoomCommandService.MicDown:input_type -> hyapp.room.v1.MicDownRequest - 89, // 196: hyapp.room.v1.RoomCommandService.ChangeMicSeat:input_type -> hyapp.room.v1.ChangeMicSeatRequest - 91, // 197: hyapp.room.v1.RoomCommandService.ConfirmMicPublishing:input_type -> hyapp.room.v1.ConfirmMicPublishingRequest - 93, // 198: hyapp.room.v1.RoomCommandService.MicHeartbeat:input_type -> hyapp.room.v1.MicHeartbeatRequest - 95, // 199: hyapp.room.v1.RoomCommandService.SetMicMute:input_type -> hyapp.room.v1.SetMicMuteRequest - 97, // 200: hyapp.room.v1.RoomCommandService.ApplyRTCEvent:input_type -> hyapp.room.v1.ApplyRTCEventRequest - 99, // 201: hyapp.room.v1.RoomCommandService.SetMicSeatLock:input_type -> hyapp.room.v1.SetMicSeatLockRequest - 101, // 202: hyapp.room.v1.RoomCommandService.SetChatEnabled:input_type -> hyapp.room.v1.SetChatEnabledRequest - 103, // 203: hyapp.room.v1.RoomCommandService.SetRoomPassword:input_type -> hyapp.room.v1.SetRoomPasswordRequest - 105, // 204: hyapp.room.v1.RoomCommandService.SetRoomAdmin:input_type -> hyapp.room.v1.SetRoomAdminRequest - 107, // 205: hyapp.room.v1.RoomCommandService.MuteUser:input_type -> hyapp.room.v1.MuteUserRequest - 109, // 206: hyapp.room.v1.RoomCommandService.KickUser:input_type -> hyapp.room.v1.KickUserRequest - 111, // 207: hyapp.room.v1.RoomCommandService.UnbanUser:input_type -> hyapp.room.v1.UnbanUserRequest - 113, // 208: hyapp.room.v1.RoomCommandService.SystemEvictUser:input_type -> hyapp.room.v1.SystemEvictUserRequest - 119, // 209: hyapp.room.v1.RoomCommandService.SendGift:input_type -> hyapp.room.v1.SendGiftRequest - 149, // 210: hyapp.room.v1.RoomCommandService.FollowRoom:input_type -> hyapp.room.v1.FollowRoomRequest - 151, // 211: hyapp.room.v1.RoomCommandService.UnfollowRoom:input_type -> hyapp.room.v1.UnfollowRoomRequest - 121, // 212: hyapp.room.v1.RoomGuardService.CheckSpeakPermission:input_type -> hyapp.room.v1.CheckSpeakPermissionRequest - 123, // 213: hyapp.room.v1.RoomGuardService.VerifyRoomPresence:input_type -> hyapp.room.v1.VerifyRoomPresenceRequest - 77, // 214: hyapp.room.v1.RoomQueryService.AdminListRooms:input_type -> hyapp.room.v1.AdminListRoomsRequest - 79, // 215: hyapp.room.v1.RoomQueryService.AdminGetRoom:input_type -> hyapp.room.v1.AdminGetRoomRequest - 17, // 216: hyapp.room.v1.RoomQueryService.AdminGetRoomRocketConfig:input_type -> hyapp.room.v1.AdminGetRoomRocketConfigRequest - 22, // 217: hyapp.room.v1.RoomQueryService.AdminGetRoomSeatConfig:input_type -> hyapp.room.v1.AdminGetRoomSeatConfigRequest - 29, // 218: hyapp.room.v1.RoomQueryService.AdminGetHumanRoomRobotConfig:input_type -> hyapp.room.v1.AdminGetHumanRoomRobotConfigRequest - 35, // 219: hyapp.room.v1.RoomQueryService.AdminListRoomPins:input_type -> hyapp.room.v1.AdminListRoomPinsRequest - 43, // 220: hyapp.room.v1.RoomQueryService.AdminListRobotRooms:input_type -> hyapp.room.v1.AdminListRobotRoomsRequest - 51, // 221: hyapp.room.v1.RoomQueryService.AdminFilterAvailableRoomRobots:input_type -> hyapp.room.v1.AdminFilterAvailableRoomRobotsRequest - 125, // 222: hyapp.room.v1.RoomQueryService.ListRooms:input_type -> hyapp.room.v1.ListRoomsRequest - 126, // 223: hyapp.room.v1.RoomQueryService.ListRoomsByOwners:input_type -> hyapp.room.v1.ListRoomsByOwnersRequest - 127, // 224: hyapp.room.v1.RoomQueryService.ListRoomFeeds:input_type -> hyapp.room.v1.ListRoomFeedsRequest - 128, // 225: hyapp.room.v1.RoomQueryService.ListRoomGiftLeaderboard:input_type -> hyapp.room.v1.ListRoomGiftLeaderboardRequest - 134, // 226: hyapp.room.v1.RoomQueryService.ListRoomContributionRank:input_type -> hyapp.room.v1.ListRoomContributionRankRequest - 136, // 227: hyapp.room.v1.RoomQueryService.GetMyRoom:input_type -> hyapp.room.v1.GetMyRoomRequest - 138, // 228: hyapp.room.v1.RoomQueryService.GetCurrentRoom:input_type -> hyapp.room.v1.GetCurrentRoomRequest - 140, // 229: hyapp.room.v1.RoomQueryService.GetRoomSnapshot:input_type -> hyapp.room.v1.GetRoomSnapshotRequest - 58, // 230: hyapp.room.v1.RoomQueryService.ListRoomBackgrounds:input_type -> hyapp.room.v1.ListRoomBackgroundsRequest - 142, // 231: hyapp.room.v1.RoomQueryService.GetRoomRocket:input_type -> hyapp.room.v1.GetRoomRocketRequest - 144, // 232: hyapp.room.v1.RoomQueryService.ListRoomOnlineUsers:input_type -> hyapp.room.v1.ListRoomOnlineUsersRequest - 147, // 233: hyapp.room.v1.RoomQueryService.ListRoomBannedUsers:input_type -> hyapp.room.v1.ListRoomBannedUsersRequest - 63, // 234: hyapp.room.v1.RoomCommandService.CreateRoom:output_type -> hyapp.room.v1.CreateRoomResponse - 65, // 235: hyapp.room.v1.RoomCommandService.UpdateRoomProfile:output_type -> hyapp.room.v1.UpdateRoomProfileResponse - 57, // 236: hyapp.room.v1.RoomCommandService.SaveRoomBackground:output_type -> hyapp.room.v1.SaveRoomBackgroundResponse - 61, // 237: hyapp.room.v1.RoomCommandService.SetRoomBackground:output_type -> hyapp.room.v1.SetRoomBackgroundResponse - 69, // 238: hyapp.room.v1.RoomCommandService.JoinRoom:output_type -> hyapp.room.v1.JoinRoomResponse - 71, // 239: hyapp.room.v1.RoomCommandService.RoomHeartbeat:output_type -> hyapp.room.v1.RoomHeartbeatResponse - 73, // 240: hyapp.room.v1.RoomCommandService.LeaveRoom:output_type -> hyapp.room.v1.LeaveRoomResponse - 75, // 241: hyapp.room.v1.RoomCommandService.CloseRoom:output_type -> hyapp.room.v1.CloseRoomResponse - 82, // 242: hyapp.room.v1.RoomCommandService.AdminUpdateRoom:output_type -> hyapp.room.v1.AdminUpdateRoomResponse - 84, // 243: hyapp.room.v1.RoomCommandService.AdminDeleteRoom:output_type -> hyapp.room.v1.AdminDeleteRoomResponse - 20, // 244: hyapp.room.v1.RoomCommandService.AdminUpdateRoomRocketConfig:output_type -> hyapp.room.v1.AdminUpdateRoomRocketConfigResponse - 25, // 245: hyapp.room.v1.RoomCommandService.AdminUpdateRoomSeatConfig:output_type -> hyapp.room.v1.AdminUpdateRoomSeatConfigResponse - 32, // 246: hyapp.room.v1.RoomCommandService.AdminUpdateHumanRoomRobotConfig:output_type -> hyapp.room.v1.AdminUpdateHumanRoomRobotConfigResponse - 38, // 247: hyapp.room.v1.RoomCommandService.AdminCreateRoomPin:output_type -> hyapp.room.v1.AdminCreateRoomPinResponse - 40, // 248: hyapp.room.v1.RoomCommandService.AdminCancelRoomPin:output_type -> hyapp.room.v1.AdminCancelRoomPinResponse - 46, // 249: hyapp.room.v1.RoomCommandService.AdminCreateRobotRoom:output_type -> hyapp.room.v1.AdminCreateRobotRoomResponse - 48, // 250: hyapp.room.v1.RoomCommandService.AdminSetRobotRoomStatus:output_type -> hyapp.room.v1.AdminSetRobotRoomStatusResponse - 50, // 251: hyapp.room.v1.RoomCommandService.AdminRenameOwnerCountryCode:output_type -> hyapp.room.v1.AdminRenameOwnerCountryCodeResponse - 86, // 252: hyapp.room.v1.RoomCommandService.MicUp:output_type -> hyapp.room.v1.MicUpResponse - 88, // 253: hyapp.room.v1.RoomCommandService.MicDown:output_type -> hyapp.room.v1.MicDownResponse - 90, // 254: hyapp.room.v1.RoomCommandService.ChangeMicSeat:output_type -> hyapp.room.v1.ChangeMicSeatResponse - 92, // 255: hyapp.room.v1.RoomCommandService.ConfirmMicPublishing:output_type -> hyapp.room.v1.ConfirmMicPublishingResponse - 94, // 256: hyapp.room.v1.RoomCommandService.MicHeartbeat:output_type -> hyapp.room.v1.MicHeartbeatResponse - 96, // 257: hyapp.room.v1.RoomCommandService.SetMicMute:output_type -> hyapp.room.v1.SetMicMuteResponse - 98, // 258: hyapp.room.v1.RoomCommandService.ApplyRTCEvent:output_type -> hyapp.room.v1.ApplyRTCEventResponse - 100, // 259: hyapp.room.v1.RoomCommandService.SetMicSeatLock:output_type -> hyapp.room.v1.SetMicSeatLockResponse - 102, // 260: hyapp.room.v1.RoomCommandService.SetChatEnabled:output_type -> hyapp.room.v1.SetChatEnabledResponse - 104, // 261: hyapp.room.v1.RoomCommandService.SetRoomPassword:output_type -> hyapp.room.v1.SetRoomPasswordResponse - 106, // 262: hyapp.room.v1.RoomCommandService.SetRoomAdmin:output_type -> hyapp.room.v1.SetRoomAdminResponse - 108, // 263: hyapp.room.v1.RoomCommandService.MuteUser:output_type -> hyapp.room.v1.MuteUserResponse - 110, // 264: hyapp.room.v1.RoomCommandService.KickUser:output_type -> hyapp.room.v1.KickUserResponse - 112, // 265: hyapp.room.v1.RoomCommandService.UnbanUser:output_type -> hyapp.room.v1.UnbanUserResponse - 114, // 266: hyapp.room.v1.RoomCommandService.SystemEvictUser:output_type -> hyapp.room.v1.SystemEvictUserResponse - 120, // 267: hyapp.room.v1.RoomCommandService.SendGift:output_type -> hyapp.room.v1.SendGiftResponse - 150, // 268: hyapp.room.v1.RoomCommandService.FollowRoom:output_type -> hyapp.room.v1.FollowRoomResponse - 152, // 269: hyapp.room.v1.RoomCommandService.UnfollowRoom:output_type -> hyapp.room.v1.UnfollowRoomResponse - 122, // 270: hyapp.room.v1.RoomGuardService.CheckSpeakPermission:output_type -> hyapp.room.v1.CheckSpeakPermissionResponse - 124, // 271: hyapp.room.v1.RoomGuardService.VerifyRoomPresence:output_type -> hyapp.room.v1.VerifyRoomPresenceResponse - 78, // 272: hyapp.room.v1.RoomQueryService.AdminListRooms:output_type -> hyapp.room.v1.AdminListRoomsResponse - 80, // 273: hyapp.room.v1.RoomQueryService.AdminGetRoom:output_type -> hyapp.room.v1.AdminGetRoomResponse - 18, // 274: hyapp.room.v1.RoomQueryService.AdminGetRoomRocketConfig:output_type -> hyapp.room.v1.AdminGetRoomRocketConfigResponse - 23, // 275: hyapp.room.v1.RoomQueryService.AdminGetRoomSeatConfig:output_type -> hyapp.room.v1.AdminGetRoomSeatConfigResponse - 30, // 276: hyapp.room.v1.RoomQueryService.AdminGetHumanRoomRobotConfig:output_type -> hyapp.room.v1.AdminGetHumanRoomRobotConfigResponse - 36, // 277: hyapp.room.v1.RoomQueryService.AdminListRoomPins:output_type -> hyapp.room.v1.AdminListRoomPinsResponse - 44, // 278: hyapp.room.v1.RoomQueryService.AdminListRobotRooms:output_type -> hyapp.room.v1.AdminListRobotRoomsResponse - 52, // 279: hyapp.room.v1.RoomQueryService.AdminFilterAvailableRoomRobots:output_type -> hyapp.room.v1.AdminFilterAvailableRoomRobotsResponse - 131, // 280: hyapp.room.v1.RoomQueryService.ListRooms:output_type -> hyapp.room.v1.ListRoomsResponse - 131, // 281: hyapp.room.v1.RoomQueryService.ListRoomsByOwners:output_type -> hyapp.room.v1.ListRoomsResponse - 131, // 282: hyapp.room.v1.RoomQueryService.ListRoomFeeds:output_type -> hyapp.room.v1.ListRoomsResponse - 133, // 283: hyapp.room.v1.RoomQueryService.ListRoomGiftLeaderboard:output_type -> hyapp.room.v1.ListRoomGiftLeaderboardResponse - 135, // 284: hyapp.room.v1.RoomQueryService.ListRoomContributionRank:output_type -> hyapp.room.v1.ListRoomContributionRankResponse - 137, // 285: hyapp.room.v1.RoomQueryService.GetMyRoom:output_type -> hyapp.room.v1.GetMyRoomResponse - 139, // 286: hyapp.room.v1.RoomQueryService.GetCurrentRoom:output_type -> hyapp.room.v1.GetCurrentRoomResponse - 141, // 287: hyapp.room.v1.RoomQueryService.GetRoomSnapshot:output_type -> hyapp.room.v1.GetRoomSnapshotResponse - 59, // 288: hyapp.room.v1.RoomQueryService.ListRoomBackgrounds:output_type -> hyapp.room.v1.ListRoomBackgroundsResponse - 143, // 289: hyapp.room.v1.RoomQueryService.GetRoomRocket:output_type -> hyapp.room.v1.GetRoomRocketResponse - 145, // 290: hyapp.room.v1.RoomQueryService.ListRoomOnlineUsers:output_type -> hyapp.room.v1.ListRoomOnlineUsersResponse - 148, // 291: hyapp.room.v1.RoomQueryService.ListRoomBannedUsers:output_type -> hyapp.room.v1.ListRoomBannedUsersResponse - 234, // [234:292] is the sub-list for method output_type - 176, // [176:234] is the sub-list for method input_type - 176, // [176:176] is the sub-list for extension type_name - 176, // [176:176] is the sub-list for extension extendee - 0, // [0:176] is the sub-list for field type_name + 69, // 69: hyapp.room.v1.JoinRoomResponse.effective_vip:type_name -> hyapp.room.v1.RoomEffectiveVipSnapshot + 0, // 70: hyapp.room.v1.RoomHeartbeatRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 71: hyapp.room.v1.RoomHeartbeatResponse.result:type_name -> hyapp.room.v1.CommandResult + 2, // 72: hyapp.room.v1.RoomHeartbeatResponse.user:type_name -> hyapp.room.v1.RoomUser + 54, // 73: hyapp.room.v1.RoomHeartbeatResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 74: hyapp.room.v1.LeaveRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 75: hyapp.room.v1.LeaveRoomResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 76: hyapp.room.v1.LeaveRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 77: hyapp.room.v1.CloseRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 78: hyapp.room.v1.CloseRoomResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 79: hyapp.room.v1.CloseRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 80: hyapp.room.v1.AdminListRoomsRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 77, // 81: hyapp.room.v1.AdminListRoomsResponse.rooms:type_name -> hyapp.room.v1.AdminRoomListItem + 0, // 82: hyapp.room.v1.AdminGetRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 77, // 83: hyapp.room.v1.AdminGetRoomResponse.room:type_name -> hyapp.room.v1.AdminRoomListItem + 0, // 84: hyapp.room.v1.AdminUpdateRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 85: hyapp.room.v1.AdminUpdateRoomResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 86: hyapp.room.v1.AdminUpdateRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 87: hyapp.room.v1.AdminDeleteRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 88: hyapp.room.v1.AdminDeleteRoomResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 89: hyapp.room.v1.AdminDeleteRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 90: hyapp.room.v1.MicUpRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 67, // 91: hyapp.room.v1.MicUpRequest.target_display_profile:type_name -> hyapp.room.v1.RoomUserDisplayProfile + 1, // 92: hyapp.room.v1.MicUpResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 93: hyapp.room.v1.MicUpResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 94: hyapp.room.v1.MicDownRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 67, // 95: hyapp.room.v1.MicDownRequest.target_display_profile:type_name -> hyapp.room.v1.RoomUserDisplayProfile + 1, // 96: hyapp.room.v1.MicDownResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 97: hyapp.room.v1.MicDownResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 98: hyapp.room.v1.ChangeMicSeatRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 67, // 99: hyapp.room.v1.ChangeMicSeatRequest.target_display_profile:type_name -> hyapp.room.v1.RoomUserDisplayProfile + 1, // 100: hyapp.room.v1.ChangeMicSeatResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 101: hyapp.room.v1.ChangeMicSeatResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 102: hyapp.room.v1.ConfirmMicPublishingRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 67, // 103: hyapp.room.v1.ConfirmMicPublishingRequest.target_display_profile:type_name -> hyapp.room.v1.RoomUserDisplayProfile + 1, // 104: hyapp.room.v1.ConfirmMicPublishingResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 105: hyapp.room.v1.ConfirmMicPublishingResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 106: hyapp.room.v1.MicHeartbeatRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 107: hyapp.room.v1.MicHeartbeatResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 108: hyapp.room.v1.MicHeartbeatResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 109: hyapp.room.v1.SetMicMuteRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 67, // 110: hyapp.room.v1.SetMicMuteRequest.target_display_profile:type_name -> hyapp.room.v1.RoomUserDisplayProfile + 1, // 111: hyapp.room.v1.SetMicMuteResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 112: hyapp.room.v1.SetMicMuteResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 113: hyapp.room.v1.ApplyRTCEventRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 114: hyapp.room.v1.ApplyRTCEventResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 115: hyapp.room.v1.ApplyRTCEventResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 116: hyapp.room.v1.SetMicSeatLockRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 117: hyapp.room.v1.SetMicSeatLockResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 118: hyapp.room.v1.SetMicSeatLockResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 119: hyapp.room.v1.SetChatEnabledRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 120: hyapp.room.v1.SetChatEnabledResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 121: hyapp.room.v1.SetChatEnabledResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 122: hyapp.room.v1.SetRoomPasswordRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 123: hyapp.room.v1.SetRoomPasswordResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 124: hyapp.room.v1.SetRoomPasswordResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 125: hyapp.room.v1.SetRoomAdminRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 126: hyapp.room.v1.SetRoomAdminResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 127: hyapp.room.v1.SetRoomAdminResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 128: hyapp.room.v1.MuteUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 129: hyapp.room.v1.MuteUserResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 130: hyapp.room.v1.MuteUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 131: hyapp.room.v1.KickUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 132: hyapp.room.v1.KickUserResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 133: hyapp.room.v1.KickUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 134: hyapp.room.v1.UnbanUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 135: hyapp.room.v1.UnbanUserResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 136: hyapp.room.v1.UnbanUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 137: hyapp.room.v1.SystemEvictUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 138: hyapp.room.v1.SystemEvictUserResponse.result:type_name -> hyapp.room.v1.CommandResult + 54, // 139: hyapp.room.v1.SystemEvictUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 7, // 140: hyapp.room.v1.SendGiftBatchTarget.lucky_gift:type_name -> hyapp.room.v1.LuckyGiftDrawResult + 118, // 141: hyapp.room.v1.SendGiftBatchDisplay.targets:type_name -> hyapp.room.v1.SendGiftBatchTarget + 0, // 142: hyapp.room.v1.SendGiftRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 116, // 143: hyapp.room.v1.SendGiftRequest.target_host_scopes:type_name -> hyapp.room.v1.SendGiftTargetHostScope + 117, // 144: hyapp.room.v1.SendGiftRequest.sender_display_profile:type_name -> hyapp.room.v1.SendGiftDisplayProfile + 117, // 145: hyapp.room.v1.SendGiftRequest.target_display_profiles:type_name -> hyapp.room.v1.SendGiftDisplayProfile + 1, // 146: hyapp.room.v1.SendGiftResponse.result:type_name -> hyapp.room.v1.CommandResult + 5, // 147: hyapp.room.v1.SendGiftResponse.gift_rank:type_name -> hyapp.room.v1.RankItem + 54, // 148: hyapp.room.v1.SendGiftResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 13, // 149: hyapp.room.v1.SendGiftResponse.rocket:type_name -> hyapp.room.v1.RoomRocketState + 7, // 150: hyapp.room.v1.SendGiftResponse.lucky_gift:type_name -> hyapp.room.v1.LuckyGiftDrawResult + 7, // 151: hyapp.room.v1.SendGiftResponse.lucky_gifts:type_name -> hyapp.room.v1.LuckyGiftDrawResult + 119, // 152: hyapp.room.v1.SendGiftResponse.batch_display:type_name -> hyapp.room.v1.SendGiftBatchDisplay + 0, // 153: hyapp.room.v1.ListRoomsRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 0, // 154: hyapp.room.v1.ListRoomsByOwnersRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 0, // 155: hyapp.room.v1.ListRoomFeedsRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 130, // 156: hyapp.room.v1.ListRoomFeedsRequest.related_users:type_name -> hyapp.room.v1.RoomFeedRelatedUser + 0, // 157: hyapp.room.v1.ListRoomGiftLeaderboardRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 131, // 158: hyapp.room.v1.ListRoomsResponse.rooms:type_name -> hyapp.room.v1.RoomListItem + 131, // 159: hyapp.room.v1.RoomGiftLeaderboardItem.room:type_name -> hyapp.room.v1.RoomListItem + 133, // 160: hyapp.room.v1.ListRoomGiftLeaderboardResponse.items:type_name -> hyapp.room.v1.RoomGiftLeaderboardItem + 0, // 161: hyapp.room.v1.ListRoomContributionRankRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 6, // 162: hyapp.room.v1.ListRoomContributionRankResponse.items:type_name -> hyapp.room.v1.RoomContributionRankItem + 0, // 163: hyapp.room.v1.GetMyRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 131, // 164: hyapp.room.v1.GetMyRoomResponse.room:type_name -> hyapp.room.v1.RoomListItem + 0, // 165: hyapp.room.v1.GetCurrentRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 0, // 166: hyapp.room.v1.GetRoomSnapshotRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 54, // 167: hyapp.room.v1.GetRoomSnapshotResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 168: hyapp.room.v1.GetRoomRocketRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 14, // 169: hyapp.room.v1.GetRoomRocketResponse.rocket:type_name -> hyapp.room.v1.RoomRocketInfo + 0, // 170: hyapp.room.v1.ListRoomOnlineUsersRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 2, // 171: hyapp.room.v1.ListRoomOnlineUsersResponse.users:type_name -> hyapp.room.v1.RoomUser + 3, // 172: hyapp.room.v1.ListRoomOnlineUsersResponse.items:type_name -> hyapp.room.v1.RoomOnlineUser + 0, // 173: hyapp.room.v1.ListRoomBannedUsersRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 147, // 174: hyapp.room.v1.ListRoomBannedUsersResponse.items:type_name -> hyapp.room.v1.RoomBannedUser + 0, // 175: hyapp.room.v1.FollowRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 0, // 176: hyapp.room.v1.UnfollowRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 62, // 177: hyapp.room.v1.RoomCommandService.CreateRoom:input_type -> hyapp.room.v1.CreateRoomRequest + 64, // 178: hyapp.room.v1.RoomCommandService.UpdateRoomProfile:input_type -> hyapp.room.v1.UpdateRoomProfileRequest + 56, // 179: hyapp.room.v1.RoomCommandService.SaveRoomBackground:input_type -> hyapp.room.v1.SaveRoomBackgroundRequest + 60, // 180: hyapp.room.v1.RoomCommandService.SetRoomBackground:input_type -> hyapp.room.v1.SetRoomBackgroundRequest + 68, // 181: hyapp.room.v1.RoomCommandService.JoinRoom:input_type -> hyapp.room.v1.JoinRoomRequest + 71, // 182: hyapp.room.v1.RoomCommandService.RoomHeartbeat:input_type -> hyapp.room.v1.RoomHeartbeatRequest + 73, // 183: hyapp.room.v1.RoomCommandService.LeaveRoom:input_type -> hyapp.room.v1.LeaveRoomRequest + 75, // 184: hyapp.room.v1.RoomCommandService.CloseRoom:input_type -> hyapp.room.v1.CloseRoomRequest + 82, // 185: hyapp.room.v1.RoomCommandService.AdminUpdateRoom:input_type -> hyapp.room.v1.AdminUpdateRoomRequest + 84, // 186: hyapp.room.v1.RoomCommandService.AdminDeleteRoom:input_type -> hyapp.room.v1.AdminDeleteRoomRequest + 19, // 187: hyapp.room.v1.RoomCommandService.AdminUpdateRoomRocketConfig:input_type -> hyapp.room.v1.AdminUpdateRoomRocketConfigRequest + 24, // 188: hyapp.room.v1.RoomCommandService.AdminUpdateRoomSeatConfig:input_type -> hyapp.room.v1.AdminUpdateRoomSeatConfigRequest + 31, // 189: hyapp.room.v1.RoomCommandService.AdminUpdateHumanRoomRobotConfig:input_type -> hyapp.room.v1.AdminUpdateHumanRoomRobotConfigRequest + 37, // 190: hyapp.room.v1.RoomCommandService.AdminCreateRoomPin:input_type -> hyapp.room.v1.AdminCreateRoomPinRequest + 39, // 191: hyapp.room.v1.RoomCommandService.AdminCancelRoomPin:input_type -> hyapp.room.v1.AdminCancelRoomPinRequest + 45, // 192: hyapp.room.v1.RoomCommandService.AdminCreateRobotRoom:input_type -> hyapp.room.v1.AdminCreateRobotRoomRequest + 47, // 193: hyapp.room.v1.RoomCommandService.AdminSetRobotRoomStatus:input_type -> hyapp.room.v1.AdminSetRobotRoomStatusRequest + 49, // 194: hyapp.room.v1.RoomCommandService.AdminRenameOwnerCountryCode:input_type -> hyapp.room.v1.AdminRenameOwnerCountryCodeRequest + 86, // 195: hyapp.room.v1.RoomCommandService.MicUp:input_type -> hyapp.room.v1.MicUpRequest + 88, // 196: hyapp.room.v1.RoomCommandService.MicDown:input_type -> hyapp.room.v1.MicDownRequest + 90, // 197: hyapp.room.v1.RoomCommandService.ChangeMicSeat:input_type -> hyapp.room.v1.ChangeMicSeatRequest + 92, // 198: hyapp.room.v1.RoomCommandService.ConfirmMicPublishing:input_type -> hyapp.room.v1.ConfirmMicPublishingRequest + 94, // 199: hyapp.room.v1.RoomCommandService.MicHeartbeat:input_type -> hyapp.room.v1.MicHeartbeatRequest + 96, // 200: hyapp.room.v1.RoomCommandService.SetMicMute:input_type -> hyapp.room.v1.SetMicMuteRequest + 98, // 201: hyapp.room.v1.RoomCommandService.ApplyRTCEvent:input_type -> hyapp.room.v1.ApplyRTCEventRequest + 100, // 202: hyapp.room.v1.RoomCommandService.SetMicSeatLock:input_type -> hyapp.room.v1.SetMicSeatLockRequest + 102, // 203: hyapp.room.v1.RoomCommandService.SetChatEnabled:input_type -> hyapp.room.v1.SetChatEnabledRequest + 104, // 204: hyapp.room.v1.RoomCommandService.SetRoomPassword:input_type -> hyapp.room.v1.SetRoomPasswordRequest + 106, // 205: hyapp.room.v1.RoomCommandService.SetRoomAdmin:input_type -> hyapp.room.v1.SetRoomAdminRequest + 108, // 206: hyapp.room.v1.RoomCommandService.MuteUser:input_type -> hyapp.room.v1.MuteUserRequest + 110, // 207: hyapp.room.v1.RoomCommandService.KickUser:input_type -> hyapp.room.v1.KickUserRequest + 112, // 208: hyapp.room.v1.RoomCommandService.UnbanUser:input_type -> hyapp.room.v1.UnbanUserRequest + 114, // 209: hyapp.room.v1.RoomCommandService.SystemEvictUser:input_type -> hyapp.room.v1.SystemEvictUserRequest + 120, // 210: hyapp.room.v1.RoomCommandService.SendGift:input_type -> hyapp.room.v1.SendGiftRequest + 150, // 211: hyapp.room.v1.RoomCommandService.FollowRoom:input_type -> hyapp.room.v1.FollowRoomRequest + 152, // 212: hyapp.room.v1.RoomCommandService.UnfollowRoom:input_type -> hyapp.room.v1.UnfollowRoomRequest + 122, // 213: hyapp.room.v1.RoomGuardService.CheckSpeakPermission:input_type -> hyapp.room.v1.CheckSpeakPermissionRequest + 124, // 214: hyapp.room.v1.RoomGuardService.VerifyRoomPresence:input_type -> hyapp.room.v1.VerifyRoomPresenceRequest + 78, // 215: hyapp.room.v1.RoomQueryService.AdminListRooms:input_type -> hyapp.room.v1.AdminListRoomsRequest + 80, // 216: hyapp.room.v1.RoomQueryService.AdminGetRoom:input_type -> hyapp.room.v1.AdminGetRoomRequest + 17, // 217: hyapp.room.v1.RoomQueryService.AdminGetRoomRocketConfig:input_type -> hyapp.room.v1.AdminGetRoomRocketConfigRequest + 22, // 218: hyapp.room.v1.RoomQueryService.AdminGetRoomSeatConfig:input_type -> hyapp.room.v1.AdminGetRoomSeatConfigRequest + 29, // 219: hyapp.room.v1.RoomQueryService.AdminGetHumanRoomRobotConfig:input_type -> hyapp.room.v1.AdminGetHumanRoomRobotConfigRequest + 35, // 220: hyapp.room.v1.RoomQueryService.AdminListRoomPins:input_type -> hyapp.room.v1.AdminListRoomPinsRequest + 43, // 221: hyapp.room.v1.RoomQueryService.AdminListRobotRooms:input_type -> hyapp.room.v1.AdminListRobotRoomsRequest + 51, // 222: hyapp.room.v1.RoomQueryService.AdminFilterAvailableRoomRobots:input_type -> hyapp.room.v1.AdminFilterAvailableRoomRobotsRequest + 126, // 223: hyapp.room.v1.RoomQueryService.ListRooms:input_type -> hyapp.room.v1.ListRoomsRequest + 127, // 224: hyapp.room.v1.RoomQueryService.ListRoomsByOwners:input_type -> hyapp.room.v1.ListRoomsByOwnersRequest + 128, // 225: hyapp.room.v1.RoomQueryService.ListRoomFeeds:input_type -> hyapp.room.v1.ListRoomFeedsRequest + 129, // 226: hyapp.room.v1.RoomQueryService.ListRoomGiftLeaderboard:input_type -> hyapp.room.v1.ListRoomGiftLeaderboardRequest + 135, // 227: hyapp.room.v1.RoomQueryService.ListRoomContributionRank:input_type -> hyapp.room.v1.ListRoomContributionRankRequest + 137, // 228: hyapp.room.v1.RoomQueryService.GetMyRoom:input_type -> hyapp.room.v1.GetMyRoomRequest + 139, // 229: hyapp.room.v1.RoomQueryService.GetCurrentRoom:input_type -> hyapp.room.v1.GetCurrentRoomRequest + 141, // 230: hyapp.room.v1.RoomQueryService.GetRoomSnapshot:input_type -> hyapp.room.v1.GetRoomSnapshotRequest + 58, // 231: hyapp.room.v1.RoomQueryService.ListRoomBackgrounds:input_type -> hyapp.room.v1.ListRoomBackgroundsRequest + 143, // 232: hyapp.room.v1.RoomQueryService.GetRoomRocket:input_type -> hyapp.room.v1.GetRoomRocketRequest + 145, // 233: hyapp.room.v1.RoomQueryService.ListRoomOnlineUsers:input_type -> hyapp.room.v1.ListRoomOnlineUsersRequest + 148, // 234: hyapp.room.v1.RoomQueryService.ListRoomBannedUsers:input_type -> hyapp.room.v1.ListRoomBannedUsersRequest + 63, // 235: hyapp.room.v1.RoomCommandService.CreateRoom:output_type -> hyapp.room.v1.CreateRoomResponse + 65, // 236: hyapp.room.v1.RoomCommandService.UpdateRoomProfile:output_type -> hyapp.room.v1.UpdateRoomProfileResponse + 57, // 237: hyapp.room.v1.RoomCommandService.SaveRoomBackground:output_type -> hyapp.room.v1.SaveRoomBackgroundResponse + 61, // 238: hyapp.room.v1.RoomCommandService.SetRoomBackground:output_type -> hyapp.room.v1.SetRoomBackgroundResponse + 70, // 239: hyapp.room.v1.RoomCommandService.JoinRoom:output_type -> hyapp.room.v1.JoinRoomResponse + 72, // 240: hyapp.room.v1.RoomCommandService.RoomHeartbeat:output_type -> hyapp.room.v1.RoomHeartbeatResponse + 74, // 241: hyapp.room.v1.RoomCommandService.LeaveRoom:output_type -> hyapp.room.v1.LeaveRoomResponse + 76, // 242: hyapp.room.v1.RoomCommandService.CloseRoom:output_type -> hyapp.room.v1.CloseRoomResponse + 83, // 243: hyapp.room.v1.RoomCommandService.AdminUpdateRoom:output_type -> hyapp.room.v1.AdminUpdateRoomResponse + 85, // 244: hyapp.room.v1.RoomCommandService.AdminDeleteRoom:output_type -> hyapp.room.v1.AdminDeleteRoomResponse + 20, // 245: hyapp.room.v1.RoomCommandService.AdminUpdateRoomRocketConfig:output_type -> hyapp.room.v1.AdminUpdateRoomRocketConfigResponse + 25, // 246: hyapp.room.v1.RoomCommandService.AdminUpdateRoomSeatConfig:output_type -> hyapp.room.v1.AdminUpdateRoomSeatConfigResponse + 32, // 247: hyapp.room.v1.RoomCommandService.AdminUpdateHumanRoomRobotConfig:output_type -> hyapp.room.v1.AdminUpdateHumanRoomRobotConfigResponse + 38, // 248: hyapp.room.v1.RoomCommandService.AdminCreateRoomPin:output_type -> hyapp.room.v1.AdminCreateRoomPinResponse + 40, // 249: hyapp.room.v1.RoomCommandService.AdminCancelRoomPin:output_type -> hyapp.room.v1.AdminCancelRoomPinResponse + 46, // 250: hyapp.room.v1.RoomCommandService.AdminCreateRobotRoom:output_type -> hyapp.room.v1.AdminCreateRobotRoomResponse + 48, // 251: hyapp.room.v1.RoomCommandService.AdminSetRobotRoomStatus:output_type -> hyapp.room.v1.AdminSetRobotRoomStatusResponse + 50, // 252: hyapp.room.v1.RoomCommandService.AdminRenameOwnerCountryCode:output_type -> hyapp.room.v1.AdminRenameOwnerCountryCodeResponse + 87, // 253: hyapp.room.v1.RoomCommandService.MicUp:output_type -> hyapp.room.v1.MicUpResponse + 89, // 254: hyapp.room.v1.RoomCommandService.MicDown:output_type -> hyapp.room.v1.MicDownResponse + 91, // 255: hyapp.room.v1.RoomCommandService.ChangeMicSeat:output_type -> hyapp.room.v1.ChangeMicSeatResponse + 93, // 256: hyapp.room.v1.RoomCommandService.ConfirmMicPublishing:output_type -> hyapp.room.v1.ConfirmMicPublishingResponse + 95, // 257: hyapp.room.v1.RoomCommandService.MicHeartbeat:output_type -> hyapp.room.v1.MicHeartbeatResponse + 97, // 258: hyapp.room.v1.RoomCommandService.SetMicMute:output_type -> hyapp.room.v1.SetMicMuteResponse + 99, // 259: hyapp.room.v1.RoomCommandService.ApplyRTCEvent:output_type -> hyapp.room.v1.ApplyRTCEventResponse + 101, // 260: hyapp.room.v1.RoomCommandService.SetMicSeatLock:output_type -> hyapp.room.v1.SetMicSeatLockResponse + 103, // 261: hyapp.room.v1.RoomCommandService.SetChatEnabled:output_type -> hyapp.room.v1.SetChatEnabledResponse + 105, // 262: hyapp.room.v1.RoomCommandService.SetRoomPassword:output_type -> hyapp.room.v1.SetRoomPasswordResponse + 107, // 263: hyapp.room.v1.RoomCommandService.SetRoomAdmin:output_type -> hyapp.room.v1.SetRoomAdminResponse + 109, // 264: hyapp.room.v1.RoomCommandService.MuteUser:output_type -> hyapp.room.v1.MuteUserResponse + 111, // 265: hyapp.room.v1.RoomCommandService.KickUser:output_type -> hyapp.room.v1.KickUserResponse + 113, // 266: hyapp.room.v1.RoomCommandService.UnbanUser:output_type -> hyapp.room.v1.UnbanUserResponse + 115, // 267: hyapp.room.v1.RoomCommandService.SystemEvictUser:output_type -> hyapp.room.v1.SystemEvictUserResponse + 121, // 268: hyapp.room.v1.RoomCommandService.SendGift:output_type -> hyapp.room.v1.SendGiftResponse + 151, // 269: hyapp.room.v1.RoomCommandService.FollowRoom:output_type -> hyapp.room.v1.FollowRoomResponse + 153, // 270: hyapp.room.v1.RoomCommandService.UnfollowRoom:output_type -> hyapp.room.v1.UnfollowRoomResponse + 123, // 271: hyapp.room.v1.RoomGuardService.CheckSpeakPermission:output_type -> hyapp.room.v1.CheckSpeakPermissionResponse + 125, // 272: hyapp.room.v1.RoomGuardService.VerifyRoomPresence:output_type -> hyapp.room.v1.VerifyRoomPresenceResponse + 79, // 273: hyapp.room.v1.RoomQueryService.AdminListRooms:output_type -> hyapp.room.v1.AdminListRoomsResponse + 81, // 274: hyapp.room.v1.RoomQueryService.AdminGetRoom:output_type -> hyapp.room.v1.AdminGetRoomResponse + 18, // 275: hyapp.room.v1.RoomQueryService.AdminGetRoomRocketConfig:output_type -> hyapp.room.v1.AdminGetRoomRocketConfigResponse + 23, // 276: hyapp.room.v1.RoomQueryService.AdminGetRoomSeatConfig:output_type -> hyapp.room.v1.AdminGetRoomSeatConfigResponse + 30, // 277: hyapp.room.v1.RoomQueryService.AdminGetHumanRoomRobotConfig:output_type -> hyapp.room.v1.AdminGetHumanRoomRobotConfigResponse + 36, // 278: hyapp.room.v1.RoomQueryService.AdminListRoomPins:output_type -> hyapp.room.v1.AdminListRoomPinsResponse + 44, // 279: hyapp.room.v1.RoomQueryService.AdminListRobotRooms:output_type -> hyapp.room.v1.AdminListRobotRoomsResponse + 52, // 280: hyapp.room.v1.RoomQueryService.AdminFilterAvailableRoomRobots:output_type -> hyapp.room.v1.AdminFilterAvailableRoomRobotsResponse + 132, // 281: hyapp.room.v1.RoomQueryService.ListRooms:output_type -> hyapp.room.v1.ListRoomsResponse + 132, // 282: hyapp.room.v1.RoomQueryService.ListRoomsByOwners:output_type -> hyapp.room.v1.ListRoomsResponse + 132, // 283: hyapp.room.v1.RoomQueryService.ListRoomFeeds:output_type -> hyapp.room.v1.ListRoomsResponse + 134, // 284: hyapp.room.v1.RoomQueryService.ListRoomGiftLeaderboard:output_type -> hyapp.room.v1.ListRoomGiftLeaderboardResponse + 136, // 285: hyapp.room.v1.RoomQueryService.ListRoomContributionRank:output_type -> hyapp.room.v1.ListRoomContributionRankResponse + 138, // 286: hyapp.room.v1.RoomQueryService.GetMyRoom:output_type -> hyapp.room.v1.GetMyRoomResponse + 140, // 287: hyapp.room.v1.RoomQueryService.GetCurrentRoom:output_type -> hyapp.room.v1.GetCurrentRoomResponse + 142, // 288: hyapp.room.v1.RoomQueryService.GetRoomSnapshot:output_type -> hyapp.room.v1.GetRoomSnapshotResponse + 59, // 289: hyapp.room.v1.RoomQueryService.ListRoomBackgrounds:output_type -> hyapp.room.v1.ListRoomBackgroundsResponse + 144, // 290: hyapp.room.v1.RoomQueryService.GetRoomRocket:output_type -> hyapp.room.v1.GetRoomRocketResponse + 146, // 291: hyapp.room.v1.RoomQueryService.ListRoomOnlineUsers:output_type -> hyapp.room.v1.ListRoomOnlineUsersResponse + 149, // 292: hyapp.room.v1.RoomQueryService.ListRoomBannedUsers:output_type -> hyapp.room.v1.ListRoomBannedUsersResponse + 235, // [235:293] is the sub-list for method output_type + 177, // [177:235] is the sub-list for method input_type + 177, // [177:177] is the sub-list for extension type_name + 177, // [177:177] is the sub-list for extension extendee + 0, // [0:177] is the sub-list for field type_name } func init() { file_proto_room_v1_room_proto_init() } @@ -15293,14 +15402,14 @@ func file_proto_room_v1_room_proto_init() { return } file_proto_room_v1_room_proto_msgTypes[64].OneofWrappers = []any{} - file_proto_room_v1_room_proto_msgTypes[81].OneofWrappers = []any{} + file_proto_room_v1_room_proto_msgTypes[82].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_room_v1_room_proto_rawDesc, NumEnums: 0, - NumMessages: 154, + NumMessages: 155, NumExtensions: 0, NumServices: 3, }, diff --git a/api/proto/room/v1/room.proto b/api/proto/room/v1/room.proto index a5b44452..6f836944 100644 --- a/api/proto/room/v1/room.proto +++ b/api/proto/room/v1/room.proto @@ -682,11 +682,21 @@ message JoinRoomRequest { string response_mode = 9; } +// RoomEffectiveVipSnapshot 是 room-service 在进房时从 wallet-service 固化的轻量 VIP 展示事实。 +// 权益执行仍以后端 effective_benefits 为准,客户端不能用该快照自行声明房间权限。 +message RoomEffectiveVipSnapshot { + string program_type = 1; + int32 level = 2; + string name = 3; + bool room_entry_notice_enabled = 4; +} + // JoinRoomResponse 返回加入后的房间快照。 message JoinRoomResponse { CommandResult result = 1; RoomUser user = 2; RoomSnapshot room = 3; + RoomEffectiveVipSnapshot effective_vip = 4; } // RoomHeartbeatRequest 显式刷新已经存在的房间业务 presence。 @@ -1195,8 +1205,9 @@ message VerifyRoomPresenceResponse { int64 room_version = 3; } -// ListRoomsRequest 查询当前用户所在区域可见的房间列表。 -// visible_region_id 必须来自 gateway 对 user-service 的 GetUser 结果,客户端不能直接提交。 +// ListRoomsRequest 查询首页公共房间列表。 +// visible_region_id 是 gateway 解析的实际查询区域:默认取 viewer 区域,显式筛选时取已校验的 filter_region_id。 +// gateway 同时写 filter_region_id 绑定游标;客户端不能直接构造任一内部字段。 message ListRoomsRequest { RequestMeta meta = 1; int64 viewer_user_id = 2; @@ -1205,12 +1216,14 @@ message ListRoomsRequest { string cursor = 5; int32 limit = 6; string query = 7; - // country_code 是可选国家筛选值;gateway 只能传当前用户区域国家列表内的国家码。 + // country_code 是可选国家筛选值;gateway 必须先确认它属于 active 区域。 string country_code = 8; - // viewer_country_code 是当前用户国家,用于区域内国家优先排序,不作为客户端可选筛选条件。 + // viewer_country_code 是当前用户国家,用于 All/区域列表的本国家优先排序。 string viewer_country_code = 9; - // all_visible_regions 只能由 gateway 根据后台白名单配置注入;为 true 时列表不按 visible_region_id 过滤。 + // all_visible_regions 只能由 gateway 根据 App 策略或后台白名单注入;为 true 时列表不按 visible_region_id 过滤。 bool all_visible_regions = 10; + // filter_region_id 是 gateway 校验过的 active 区域筛选;它与 all_visible_regions/country_code 互斥。 + int64 filter_region_id = 11; } // ListRoomsByOwnersRequest 查询一组房主名下 active 房间。 diff --git a/api/proto/user/v1/host.pb.go b/api/proto/user/v1/host.pb.go index 1928c5ba..9f92ed66 100644 --- a/api/proto/user/v1/host.pb.go +++ b/api/proto/user/v1/host.pb.go @@ -884,6 +884,8 @@ type UserRoleSummary struct { CoinSellerStatus string `protobuf:"bytes,11,opt,name=coin_seller_status,json=coinSellerStatus,proto3" json:"coin_seller_status,omitempty"` PendingRoleInvitations int64 `protobuf:"varint,12,opt,name=pending_role_invitations,json=pendingRoleInvitations,proto3" json:"pending_role_invitations,omitempty"` IsManager bool `protobuf:"varint,13,opt,name=is_manager,json=isManager,proto3" json:"is_manager,omitempty"` + // roles 给后台等需要多身份并列展示的调用方提供稳定字符串集合;原布尔字段继续兼容 App 入口显隐。 + Roles []string `protobuf:"bytes,14,rep,name=roles,proto3" json:"roles,omitempty"` } func (x *UserRoleSummary) Reset() { @@ -1007,6 +1009,13 @@ func (x *UserRoleSummary) GetIsManager() bool { return false } +func (x *UserRoleSummary) GetRoles() []string { + if x != nil { + return x.Roles + } + return nil +} + // AgencyMembership 是 host 与 Agency 的有时效关系事实。 type AgencyMembership struct { state protoimpl.MessageState @@ -6661,7 +6670,7 @@ var file_proto_user_v1_host_proto_rawDesc = []byte{ 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, 0xb4, 0x03, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, + 0x4d, 0x73, 0x22, 0xca, 0x03, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 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, 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, @@ -6688,219 +6697,204 @@ var file_proto_user_v1_host_proto_rawDesc = []byte{ 0x28, 0x03, 0x52, 0x16, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, - 0x69, 0x73, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x22, 0xaa, 0x03, 0x0a, 0x10, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, 0x23, - 0x0a, 0x0d, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, - 0x70, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x64, - 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, 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, - 0x27, 0x0a, 0x0f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x73, 0x68, 0x69, 0x70, 0x54, 0x79, 0x70, 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, 0x0c, 0x6a, 0x6f, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6a, 0x6f, 0x69, 0x6e, 0x65, 0x64, 0x41, 0x74, - 0x4d, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, - 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x41, 0x74, - 0x4d, 0x73, 0x12, 0x27, 0x0a, 0x10, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x65, 0x6e, - 0x64, 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x65, - 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x65, 0x6e, 0x64, 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, - 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, 0x99, 0x03, 0x0a, 0x11, 0x41, 0x67, 0x65, 0x6e, 0x63, - 0x79, 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, 0x03, 0x52, 0x0d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 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, 0x2a, 0x0a, 0x11, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x6e, 0x74, 0x5f, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x61, - 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, - 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x2d, 0x0a, 0x13, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x72, - 0x65, 0x76, 0x69, 0x65, 0x77, 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, - 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x65, 0x64, - 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x65, - 0x76, 0x69, 0x65, 0x77, 0x65, 0x64, 0x41, 0x74, 0x4d, 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, 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, 0xf4, 0x04, 0x0a, 0x0e, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x69, 0x6e, - 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 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, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x76, - 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x26, 0x0a, 0x0f, 0x69, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x12, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x72, 0x5f, 0x62, 0x64, - 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, - 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x72, 0x42, 0x64, 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, 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, 0x1f, 0x0a, 0x0b, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x64, - 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x64, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x31, - 0x0a, 0x15, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x70, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x62, - 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x11, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x72, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0e, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 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, 0x22, 0x97, 0x01, 0x0a, 0x15, 0x53, 0x65, - 0x61, 0x72, 0x63, 0x68, 0x41, 0x67, 0x65, 0x6e, 0x63, 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, 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, - 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 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, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, - 0x69, 0x7a, 0x65, 0x22, 0x4b, 0x0a, 0x16, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, - 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, - 0x22, 0x9b, 0x01, 0x0a, 0x14, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, - 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, + 0x69, 0x73, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x6c, + 0x65, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x22, + 0xaa, 0x03, 0x0a, 0x10, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x68, 0x69, 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, + 0x69, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, + 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, + 0x65, 0x6e, 0x63, 0x79, 0x49, 0x64, 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, 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, 0x27, 0x0a, 0x0f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, + 0x68, 0x69, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x54, 0x79, 0x70, 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, 0x0c, 0x6a, 0x6f, 0x69, 0x6e, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6a, 0x6f, + 0x69, 0x6e, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x65, 0x6e, 0x64, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x65, + 0x6e, 0x64, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x27, 0x0a, 0x10, 0x65, 0x6e, 0x64, 0x65, + 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0d, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x6e, 0x64, 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, 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, 0x99, 0x03, 0x0a, + 0x11, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x03, 0x52, 0x0d, 0x61, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 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, 0x2a, 0x0a, 0x11, 0x61, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x6e, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x6e, 0x74, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x16, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, + 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x10, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x65, 0x64, 0x42, 0x79, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, + 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, + 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x65, + 0x76, 0x69, 0x65, 0x77, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0c, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x65, 0x64, 0x41, 0x74, 0x4d, 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, 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, 0xf4, 0x04, 0x0a, 0x0e, 0x52, 0x6f, 0x6c, + 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x69, + 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0c, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 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, + 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 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, 0x26, 0x0a, 0x0f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x76, 0x69, 0x74, + 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x12, 0x69, 0x6e, 0x76, 0x69, + 0x74, 0x65, 0x72, 0x5f, 0x62, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x72, 0x42, 0x64, 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, 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, 0x1f, 0x0a, 0x0b, 0x61, 0x67, 0x65, 0x6e, + 0x63, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, + 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x11, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x64, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x15, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6c, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x12, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x70, 0x72, 0x6f, 0x63, 0x65, + 0x73, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, + 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x63, + 0x65, 0x73, 0x73, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, + 0x26, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, + 0x6d, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, + 0x73, 0x65, 0x64, 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, 0x22, + 0x97, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, 0x67, 0x65, 0x6e, 0x63, 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, 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, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x64, 0x22, 0x5b, - 0x0a, 0x15, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 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, 0xf4, 0x01, 0x0a, 0x1e, - 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 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, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x65, - 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1a, - 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 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, 0xe5, 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x41, 0x67, 0x65, 0x6e, - 0x63, 0x79, 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, 0x3d, 0x0a, 0x0c, 0x68, 0x6f, - 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x0b, 0x68, 0x6f, - 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x3f, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0a, - 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x22, 0xe7, 0x01, 0x0a, 0x15, 0x4b, - 0x69, 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, + 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, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 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, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x4b, 0x0a, 0x16, 0x53, 0x65, 0x61, + 0x72, 0x63, 0x68, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x08, 0x61, 0x67, + 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x22, 0x9b, 0x01, 0x0a, 0x14, 0x41, 0x70, 0x70, 0x6c, 0x79, + 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x63, 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, 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, 0x61, 0x67, 0x65, 0x6e, 0x63, + 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, + 0x63, 0x79, 0x49, 0x64, 0x22, 0x5b, 0x0a, 0x15, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x41, + 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0xf4, 0x01, 0x0a, 0x1e, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, + 0x63, 0x79, 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, 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, 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, 0x1b, 0x0a, - 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x68, 0x6f, - 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0a, 0x68, 0x6f, 0x73, 0x74, 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, 0x22, 0x98, 0x01, 0x0a, 0x16, 0x4b, 0x69, 0x63, 0x6b, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3f, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x73, 0x68, 0x69, 0x70, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, + 0x64, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, + 0x65, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, + 0x0e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 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, 0xe5, 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x76, + 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 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, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x3d, 0x0a, 0x0c, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x52, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, - 0xd3, 0x01, 0x0a, 0x13, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 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, 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, 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, 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, 0x1f, 0x0a, 0x0b, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x67, 0x65, 0x6e, 0x63, - 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x55, 0x0a, 0x14, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, - 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xae, 0x01, 0x0a, - 0x0f, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 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, 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, 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, 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, 0x51, 0x0a, - 0x10, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x22, 0xb0, 0x01, 0x0a, 0x11, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x52, + 0x6c, 0x65, 0x52, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, + 0x3f, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x68, 0x69, 0x70, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, + 0x22, 0xe7, 0x01, 0x0a, 0x15, 0x4b, 0x69, 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, + 0x6f, 0x73, 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, 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, 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, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x64, + 0x12, 0x20, 0x0a, 0x0c, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x68, 0x6f, 0x73, 0x74, 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, 0x22, 0x98, 0x01, 0x0a, 0x16, 0x4b, + 0x69, 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, + 0x68, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, + 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, 0x3d, 0x0a, 0x0c, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, + 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0xd3, 0x01, 0x0a, 0x13, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, + 0x41, 0x67, 0x65, 0x6e, 0x63, 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, 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, + 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, 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, 0x1f, 0x0a, 0x0b, 0x61, 0x67, + 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x55, 0x0a, 0x14, 0x49, + 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x22, 0xae, 0x01, 0x0a, 0x0f, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 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, @@ -6911,413 +6905,476 @@ var file_proto_user_v1_host_proto_rawDesc = []byte{ 0x69, 0x6e, 0x76, 0x69, 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, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x22, 0x53, 0x0a, 0x12, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x48, 0x6f, 0x73, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x69, 0x6e, 0x76, - 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, - 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, - 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa3, 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, - 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 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, 0x24, 0x0a, 0x0e, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x65, 0x61, - 0x64, 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, 0x54, - 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x44, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x62, 0x64, 0x5f, - 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, - 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x0a, 0x62, 0x64, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x22, 0xa8, 0x01, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x63, 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, 0x24, 0x0a, 0x0e, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x65, - 0x61, 0x64, 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, - 0x51, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, + 0x72, 0x49, 0x64, 0x22, 0x51, 0x0a, 0x10, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 0x44, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, + 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, 0x76, 0x69, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb0, 0x01, 0x0a, 0x11, 0x49, 0x6e, 0x76, 0x69, 0x74, + 0x65, 0x48, 0x6f, 0x73, 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, 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, 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, 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, 0x53, 0x0a, 0x12, 0x49, 0x6e, 0x76, + 0x69, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3d, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa3, + 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, + 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, 0x24, 0x0a, 0x0e, 0x6c, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0c, 0x6c, 0x65, 0x61, 0x64, 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, 0x54, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x42, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x39, 0x0a, 0x0b, 0x62, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x0a, + 0x62, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22, 0xa8, 0x01, 0x0a, 0x1b, 0x4c, + 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x63, + 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, 0x24, 0x0a, 0x0e, 0x6c, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x65, 0x61, 0x64, 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, 0x51, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x08, + 0x61, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x22, 0x95, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, + 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x54, 0x65, 0x61, 0x6d, 0x41, 0x67, 0x65, 0x6e, + 0x63, 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, 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, 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, + 0x22, 0x7f, 0x0a, 0x11, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x54, 0x65, 0x61, 0x6d, 0x41, + 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, + 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, 0x29, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x5f, 0x62, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x64, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x64, 0x22, 0xc4, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, + 0x72, 0x54, 0x65, 0x61, 0x6d, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 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, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x54, + 0x65, 0x61, 0x6d, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, + 0x69, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x64, 0x5f, + 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x64, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x1b, 0x0a, + 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x08, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x64, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x72, + 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x74, + 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x22, 0x9a, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, + 0x74, 0x42, 0x44, 0x41, 0x67, 0x65, 0x6e, 0x63, 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, 0x1c, 0x0a, 0x0a, 0x62, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x62, 0x64, 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, 0x4b, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x69, - 0x65, 0x73, 0x22, 0x95, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x72, 0x54, 0x65, 0x61, 0x6d, 0x41, 0x67, 0x65, 0x6e, 0x63, 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, 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, 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, 0x22, 0x7f, 0x0a, 0x11, 0x4d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x72, 0x54, 0x65, 0x61, 0x6d, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, - 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x29, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x64, 0x5f, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x42, 0x64, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xc4, 0x01, 0x0a, 0x1f, - 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x54, 0x65, 0x61, 0x6d, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3c, 0x0a, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 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, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x54, 0x65, 0x61, 0x6d, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x28, 0x0a, - 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x64, 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x64, - 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, - 0x5f, 0x62, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x74, 0x6f, 0x74, 0x61, - 0x6c, 0x42, 0x64, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, - 0x65, 0x64, 0x22, 0x9a, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x41, 0x67, 0x65, - 0x6e, 0x63, 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, 0x1c, 0x0a, 0x0a, - 0x62, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x08, 0x62, 0x64, 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, - 0x4b, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x61, 0x67, 0x65, - 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, - 0x63, 0x79, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x22, 0xa7, 0x01, 0x0a, - 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 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, 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, 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, 0x5e, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, - 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x69, 0x6e, 0x76, 0x69, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x52, 0x6f, - 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 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, 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, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x76, 0x69, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, - 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x5a, 0x0a, 0x19, - 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x65, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, + 0x6e, 0x76, 0x69, 0x74, 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, 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, + 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, 0x5e, 0x0a, 0x1b, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x69, + 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x0b, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x93, 0x01, 0x0a, + 0x18, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 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, 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, 0x23, 0x0a, + 0x0d, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x22, 0x5a, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, + 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3d, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xe6, + 0x01, 0x0a, 0x1c, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, + 0x76, 0x69, 0x74, 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, + 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, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x69, 0x6e, 0x76, 0x69, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0xc6, 0x02, 0x0a, 0x1d, 0x50, 0x72, 0x6f, 0x63, + 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, - 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xe6, 0x01, 0x0a, 0x1c, 0x50, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, + 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x0c, 0x68, 0x6f, 0x73, 0x74, + 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x48, + 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x0b, 0x68, 0x6f, 0x73, 0x74, + 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, + 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, + 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x3f, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x68, 0x69, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, + 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0a, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x64, 0x5f, 0x70, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x44, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x09, 0x62, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x22, 0x60, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 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, 0x22, 0x57, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0c, + 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x0b, + 0x68, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x68, 0x0a, 0x1b, 0x42, + 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 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, 0xdf, 0x01, 0x0a, 0x1c, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, + 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0d, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, + 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x68, 0x6f, + 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x1a, 0x5b, 0x0a, 0x11, 0x48, 0x6f, + 0x73, 0x74, 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, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x72, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x42, 0x44, + 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, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x4f, 0x0a, 0x14, 0x47, + 0x65, 0x74, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x52, 0x09, 0x62, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x66, 0x0a, 0x1b, + 0x47, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 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, 0x22, 0x70, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, + 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x13, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, + 0x6c, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x52, 0x11, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x71, 0x0a, 0x26, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x49, + 0x6e, 0x4d, 0x79, 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, 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, 0x6f, 0x0a, 0x27, 0x4c, 0x69, 0x73, + 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, + 0x72, 0x73, 0x49, 0x6e, 0x4d, 0x79, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0c, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, + 0x6c, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, + 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0b, 0x63, + 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x22, 0xb5, 0x01, 0x0a, 0x1a, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, + 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, 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, 0x23, 0x0a, 0x0d, - 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0c, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x22, 0xc6, 0x02, 0x0a, 0x1d, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6c, - 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x0c, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x52, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, - 0x12, 0x3f, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, - 0x70, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, - 0x09, 0x62, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x60, 0x0a, 0x15, 0x47, 0x65, - 0x74, 0x48, 0x6f, 0x73, 0x74, 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, 0x22, 0x57, 0x0a, 0x16, - 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0c, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, - 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x68, 0x0a, 0x1b, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, - 0x74, 0x48, 0x6f, 0x73, 0x74, 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, - 0xdf, 0x01, 0x0a, 0x1c, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, - 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x62, 0x0a, 0x0d, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, - 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x1a, 0x5b, 0x0a, 0x11, 0x48, 0x6f, 0x73, 0x74, 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, 0x30, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x22, 0x72, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x42, 0x44, 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, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x4f, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x42, 0x44, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, - 0x0a, 0x62, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x09, 0x62, 0x64, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x66, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x69, - 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, + 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, 0x03, 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, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x22, 0x98, 0x01, 0x0a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, + 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, + 0x75, 0x62, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x4c, 0x69, + 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x22, 0xc2, 0x01, + 0x0a, 0x25, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, + 0x65, 0x6c, 0x6c, 0x65, 0x72, 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, 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, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 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, 0x22, 0x73, 0x0a, 0x26, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x75, 0x62, 0x43, + 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0b, + 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x75, 0x62, 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, 0xa2, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, + 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 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, 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, 0x70, - 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, - 0x0a, 0x13, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x70, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, - 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x11, 0x63, - 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x22, 0x71, 0x0a, 0x26, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, - 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x49, 0x6e, 0x4d, 0x79, 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, 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, 0x6f, 0x0a, 0x27, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x49, 0x6e, 0x4d, 0x79, - 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, - 0x0a, 0x0c, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x4c, - 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0b, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, - 0x6c, 0x65, 0x72, 0x73, 0x22, 0xb5, 0x01, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, - 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 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, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 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, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x98, 0x01, 0x0a, - 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, - 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x08, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x75, 0x62, 0x52, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, - 0x0a, 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x04, 0x6d, 0x65, 0x74, 0x61, 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, 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, 0xa2, 0x01, 0x0a, + 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, + 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x08, 0x63, + 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, - 0x52, 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x22, 0xc2, 0x01, 0x0a, 0x25, 0x53, 0x75, 0x62, 0x6d, - 0x69, 0x74, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x41, - 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 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, 0x22, 0x9d, 0x01, 0x0a, 0x21, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x69, 0x6e, 0x53, + 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x75, 0x62, 0x52, 0x65, 0x6c, 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, 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, 0x22, 0x8f, 0x01, 0x0a, 0x22, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x69, 0x6e, 0x53, + 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x75, 0x62, 0x52, 0x65, 0x6c, 0x61, 0x74, 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, 0x37, 0x0a, 0x05, 0x63, 0x68, + 0x69, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, + 0x6c, 0x6c, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x63, 0x68, + 0x69, 0x6c, 0x64, 0x22, 0x64, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, + 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 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, 0x22, 0x56, 0x0a, 0x1a, 0x47, 0x65, 0x74, + 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, + 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, + 0x79, 0x22, 0x5f, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 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, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, + 0x49, 0x64, 0x22, 0x42, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, + 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x94, 0x01, 0x0a, 0x1e, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 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, 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, 0x1e, 0x0a, + 0x0a, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x22, 0x53, 0x0a, + 0x1f, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x43, 0x61, + 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 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, 0x22, 0x7e, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, + 0x65, 0x6d, 0x62, 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, 0x1b, 0x0a, + 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 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, 0x22, 0x5d, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, + 0x0a, 0x0b, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x68, 0x69, 0x70, 0x52, 0x0b, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, + 0x73, 0x22, 0x83, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 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, 0x22, 0x65, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x41, 0x67, + 0x65, 0x6e, 0x63, 0x79, 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, 0x41, + 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x22, 0xc8, + 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 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, 0x22, 0x0a, 0x0d, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, + 0x61, 0x64, 0x6d, 0x69, 0x6e, 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, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x51, 0x0a, 0x16, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x52, 0x09, 0x62, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0xf5, 0x01, 0x0a, + 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 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, 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, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 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, 0x31, 0x0a, 0x15, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x4c, 0x65, 0x61, 0x64, 0x65, 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, 0x22, 0x4b, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x64, 0x5f, 0x70, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x44, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x09, 0x62, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x22, 0xf1, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x42, 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, 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, 0x64, 0x6d, 0x69, 0x6e, + 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, + 0x61, 0x64, 0x6d, 0x69, 0x6e, 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, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 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, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x4e, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x42, 0x44, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, + 0x62, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x09, 0x62, 0x64, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0xad, 0x02, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 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, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 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, 0x22, 0x73, 0x0a, 0x26, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, - 0x6c, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, - 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x75, 0x62, 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, 0xa2, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, - 0x6e, 0x53, 0x65, 0x6c, 0x6c, 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, - 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, 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, 0xa2, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, - 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, - 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, - 0x64, 0x72, 0x65, 0x6e, 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, 0x22, 0x9d, 0x01, 0x0a, 0x21, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, - 0x75, 0x62, 0x52, 0x65, 0x6c, 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, 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, 0x22, 0x8f, 0x01, 0x0a, 0x22, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, - 0x75, 0x62, 0x52, 0x65, 0x6c, 0x61, 0x74, 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, 0x37, 0x0a, 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x4c, 0x69, - 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x22, 0x64, 0x0a, - 0x19, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, - 0x61, 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, 0x22, 0x56, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, - 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x38, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x5f, 0x0a, 0x10, 0x47, - 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 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, - 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x64, 0x22, 0x42, 0x0a, 0x11, - 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, - 0x22, 0x94, 0x01, 0x0a, 0x1e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, - 0x73, 0x73, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 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, 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, 0x1e, 0x0a, 0x0a, 0x63, 0x61, 0x70, 0x61, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x61, 0x70, - 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x22, 0x53, 0x0a, 0x1f, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x79, 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, 0x22, 0x7e, 0x0a, 0x17, - 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 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, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, - 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, - 0x63, 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, 0x22, 0x5d, 0x0a, 0x18, - 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0b, 0x6d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0b, - 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x1c, - 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x1b, 0x0a, 0x09, - 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 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, 0x22, 0x65, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x22, 0xc8, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 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, 0x22, 0x0a, 0x0d, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 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, 0x16, 0x0a, 0x06, 0x72, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x22, 0x51, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x4c, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, - 0x0a, 0x62, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x09, 0x62, 0x64, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0xf5, 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x42, 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, 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, 0x64, 0x6d, - 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 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, 0x31, 0x0a, 0x15, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x12, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x61, 0x64, 0x65, 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, 0x22, 0x4b, - 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x52, 0x09, 0x62, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0xf1, 0x01, 0x0a, 0x12, - 0x53, 0x65, 0x74, 0x42, 0x44, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 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, 0x16, 0x0a, 0x06, 0x72, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x1b, 0x63, 0x61, 0x6e, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, + 0x5f, 0x73, 0x75, 0x62, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, + 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x17, 0x63, 0x61, 0x6e, 0x4d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, + 0x72, 0x73, 0x88, 0x01, 0x01, 0x42, 0x1e, 0x0a, 0x1c, 0x5f, 0x63, 0x61, 0x6e, 0x5f, 0x6d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x75, 0x62, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, + 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x22, 0x6c, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, + 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x50, 0x0a, 0x13, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, + 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x52, 0x11, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x22, 0xc8, 0x02, 0x0a, 0x1a, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, + 0x65, 0x6c, 0x6c, 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, @@ -7330,119 +7387,100 @@ var file_proto_user_v1_host_proto_rawDesc = []byte{ 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 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, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x72, - 0x6f, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, - 0x4e, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x42, 0x44, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x64, 0x5f, 0x70, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x44, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x52, 0x09, 0x62, 0x64, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, - 0xad, 0x02, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, - 0x6c, 0x6c, 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, 0x22, 0x0a, 0x0d, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 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, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x1b, - 0x63, 0x61, 0x6e, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x75, 0x62, 0x5f, 0x63, - 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x08, 0x48, 0x00, 0x52, 0x17, 0x63, 0x61, 0x6e, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x53, 0x75, - 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x88, 0x01, 0x01, 0x42, - 0x1e, 0x0a, 0x1c, 0x5f, 0x63, 0x61, 0x6e, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x5f, 0x73, - 0x75, 0x62, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x22, - 0x6c, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, - 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x13, 0x63, - 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, - 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x11, 0x63, 0x6f, 0x69, 0x6e, - 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0xc8, 0x02, - 0x0a, 0x1a, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 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, 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, - 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 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, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 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, 0x12, 0x41, 0x0a, 0x1b, 0x63, 0x61, 0x6e, 0x5f, 0x6d, 0x61, 0x6e, - 0x61, 0x67, 0x65, 0x5f, 0x73, 0x75, 0x62, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, - 0x6c, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x17, 0x63, 0x61, - 0x6e, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, - 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x88, 0x01, 0x01, 0x42, 0x1e, 0x0a, 0x1c, 0x5f, 0x63, 0x61, 0x6e, - 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x75, 0x62, 0x5f, 0x63, 0x6f, 0x69, 0x6e, - 0x5f, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x22, 0x6f, 0x0a, 0x1b, 0x53, 0x65, 0x74, 0x43, - 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x13, 0x63, 0x6f, 0x69, 0x6e, 0x5f, - 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x11, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, - 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0xf5, 0x01, 0x0a, 0x25, 0x52, 0x65, - 0x76, 0x69, 0x65, 0x77, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, - 0x72, 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, 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, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, - 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1a, 0x0a, - 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 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, 0xee, 0x01, 0x0a, 0x26, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x53, 0x75, 0x62, 0x43, - 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0b, - 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x75, 0x62, 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, 0x40, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, - 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x75, 0x62, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x05, 0x63, 0x68, 0x69, - 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, - 0x6c, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x63, 0x68, 0x69, - 0x6c, 0x64, 0x22, 0xc3, 0x02, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, - 0x6e, 0x63, 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, - 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, 0x64, 0x6d, - 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 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, 0x29, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x64, 0x5f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x42, 0x64, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x6f, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x48, 0x6f, 0x73, 0x74, 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, 0x22, 0xc5, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x1b, 0x63, + 0x61, 0x6e, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x75, 0x62, 0x5f, 0x63, 0x6f, + 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, + 0x48, 0x00, 0x52, 0x17, 0x63, 0x61, 0x6e, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x53, 0x75, 0x62, + 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x88, 0x01, 0x01, 0x42, 0x1e, + 0x0a, 0x1c, 0x5f, 0x63, 0x61, 0x6e, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x75, + 0x62, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x22, 0x6f, + 0x0a, 0x1b, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, + 0x13, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, + 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x11, 0x63, 0x6f, + 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, + 0xf5, 0x01, 0x0a, 0x25, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, + 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 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, 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, 0x64, 0x6d, 0x69, + 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, + 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 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, 0xee, 0x01, 0x0a, 0x26, 0x52, 0x65, 0x76, 0x69, + 0x65, 0x77, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x41, + 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, + 0x65, 0x72, 0x53, 0x75, 0x62, 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, 0x40, 0x0a, + 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x75, 0x62, 0x52, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x37, 0x0a, 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, + 0x6d, 0x52, 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x22, 0xc3, 0x02, 0x0a, 0x13, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 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, 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, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, + 0x72, 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, 0x29, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x5f, 0x62, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x64, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x6f, 0x69, 0x6e, 0x5f, 0x65, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6a, 0x6f, + 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, + 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6d, 0x61, + 0x78, 0x48, 0x6f, 0x73, 0x74, 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, 0x22, 0xc5, + 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, + 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x3d, 0x0a, 0x0c, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, + 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x3f, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, + 0x68, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, + 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x22, 0xe9, 0x01, 0x0a, 0x19, 0x41, 0x64, 0x6d, 0x69, 0x6e, + 0x41, 0x64, 0x64, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 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, 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, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, + 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, + 0x63, 0x79, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 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, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x22, 0xcb, 0x01, 0x0a, 0x1a, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x41, 0x64, 0x64, 0x41, + 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, @@ -7454,51 +7492,7 @@ var file_proto_user_v1_host_proto_rawDesc = []byte{ 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, - 0x22, 0xe9, 0x01, 0x0a, 0x19, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x41, 0x64, 0x64, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 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, 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, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x64, 0x12, 0x24, - 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x05, 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, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0xcb, 0x01, 0x0a, - 0x1a, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x41, 0x64, 0x64, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, - 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, - 0x67, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, - 0x63, 0x79, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x3d, 0x0a, 0x0c, 0x68, 0x6f, - 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x0b, 0x68, 0x6f, - 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x3f, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0a, - 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x22, 0xbc, 0x01, 0x0a, 0x12, 0x43, - 0x6c, 0x6f, 0x73, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 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, 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, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, - 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x44, 0x0a, 0x13, 0x43, 0x6c, 0x6f, - 0x73, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x22, - 0xbd, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, + 0x22, 0xbc, 0x01, 0x0a, 0x12, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 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, @@ -7510,12 +7504,47 @@ var file_proto_user_v1_host_proto_rawDesc = []byte{ 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, - 0x45, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, - 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x22, 0xd8, 0x01, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x44, 0x0a, 0x13, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, + 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, 0x61, + 0x67, 0x65, 0x6e, 0x63, 0x79, 0x22, 0xbd, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x41, 0x67, 0x65, 0x6e, 0x63, 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, 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, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x45, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, + 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, + 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, + 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x22, 0xd8, 0x01, 0x0a, + 0x16, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 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, 0x64, 0x6d, 0x69, 0x6e, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, + 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x67, + 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, + 0x67, 0x65, 0x6e, 0x63, 0x79, 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, + 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x48, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x41, 0x67, + 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, + 0x79, 0x22, 0xe8, 0x01, 0x0a, 0x1b, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4a, + 0x6f, 0x69, 0x6e, 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, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, @@ -7525,329 +7554,310 @@ var file_proto_user_v1_host_proto_rawDesc = []byte{ 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x22, 0x48, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, + 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x6f, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 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, 0x4d, 0x0a, 0x1c, + 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x22, 0xe8, 0x01, 0x0a, 0x1b, - 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 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, 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, 0x22, 0x0a, 0x0d, 0x61, 0x64, - 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, - 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6a, - 0x6f, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0b, 0x6a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 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, 0x4d, 0x0a, 0x1c, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, - 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, 0x61, - 0x67, 0x65, 0x6e, 0x63, 0x79, 0x22, 0xfc, 0x01, 0x0a, 0x1a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 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, 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, 0x1b, 0x0a, - 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x88, 0x01, 0x01, - 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x61, 0x76, - 0x61, 0x74, 0x61, 0x72, 0x22, 0x4c, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, - 0x63, 0x79, 0x32, 0xaa, 0x18, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x48, 0x6f, 0x73, 0x74, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, - 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, + 0x6e, 0x63, 0x79, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x22, 0xfc, 0x01, 0x0a, 0x1a, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 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, 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, 0x1b, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x69, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x64, + 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x61, 0x76, 0x61, + 0x74, 0x61, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x06, 0x61, 0x76, 0x61, + 0x74, 0x61, 0x72, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, + 0x09, 0x0a, 0x07, 0x5f, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x22, 0x4c, 0x0a, 0x1b, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x67, 0x65, + 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, + 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x32, 0xaa, 0x18, 0x0a, 0x0f, 0x55, 0x73, 0x65, + 0x72, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x0e, + 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, - 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, - 0x79, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x78, 0x0a, 0x17, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, - 0x79, 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, 0x52, 0x65, 0x76, - 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x52, 0x65, 0x76, 0x69, - 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x4b, - 0x69, 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x24, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69, - 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, 0x67, 0x65, 0x6e, 0x63, + 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0d, 0x41, + 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x23, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, + 0x6c, 0x79, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x17, 0x52, 0x65, 0x76, 0x69, 0x65, + 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x4b, 0x69, 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, + 0x6f, 0x73, 0x74, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69, 0x63, 0x6b, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, - 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x49, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, - 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 0x44, 0x12, - 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x51, 0x0a, 0x0a, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x20, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x42, 0x44, 0x73, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x42, 0x44, 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, 0x4c, 0x69, - 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x44, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x2a, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, - 0x65, 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, 0x42, 0x44, - 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, - 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x42, 0x44, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x6e, - 0x61, 0x67, 0x65, 0x72, 0x54, 0x65, 0x61, 0x6d, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, - 0x12, 0x2d, 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, 0x54, 0x65, 0x61, 0x6d, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69, 0x63, 0x6b, 0x41, 0x67, + 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x57, 0x0a, 0x0c, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, + 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x49, 0x6e, 0x76, + 0x69, 0x74, 0x65, 0x42, 0x44, 0x12, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0a, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, + 0x48, 0x6f, 0x73, 0x74, 0x12, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, + 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x48, 0x6f, 0x73, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x4c, 0x69, 0x73, + 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x44, 0x73, 0x12, 0x25, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x44, 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, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x42, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x4c, + 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x63, + 0x69, 0x65, 0x73, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x63, 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, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x54, 0x65, 0x61, 0x6d, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x6c, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, - 0x11, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 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, 0x52, - 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, - 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x47, 0x65, 0x74, - 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, - 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, - 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 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, 0x42, 0x61, 0x74, - 0x63, 0x68, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x47, 0x65, 0x74, - 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x44, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, - 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, - 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 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, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, - 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x90, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, - 0x76, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x49, 0x6e, 0x4d, - 0x79, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, - 0x76, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x49, 0x6e, 0x4d, - 0x79, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, + 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, + 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0e, + 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, - 0x6c, 0x65, 0x72, 0x73, 0x49, 0x6e, 0x4d, 0x79, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x29, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, - 0x72, 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, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, - 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x1e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, - 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x75, - 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, + 0x69, 0x73, 0x74, 0x42, 0x44, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x44, 0x41, 0x67, 0x65, 0x6e, 0x63, + 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x17, 0x4c, + 0x69, 0x73, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x54, 0x65, 0x61, 0x6d, 0x41, 0x67, + 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x2d, 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, 0x54, 0x65, 0x61, 0x6d, 0x41, 0x67, 0x65, 0x6e, 0x63, 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, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, + 0x72, 0x54, 0x65, 0x61, 0x6d, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, + 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x52, 0x6f, 0x6c, 0x65, + 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, + 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, + 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x15, 0x50, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6c, 0x65, + 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x6c, 0x65, 0x49, 0x6e, 0x76, + 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x5d, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, + 0x0a, 0x14, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, + 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x48, + 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 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, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x57, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, + 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x44, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x43, + 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, + 0x6f, 0x66, 0x69, 0x6c, 0x65, 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, + 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x90, 0x01, 0x0a, 0x1f, 0x4c, 0x69, + 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, + 0x65, 0x72, 0x73, 0x49, 0x6e, 0x4d, 0x79, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, + 0x65, 0x72, 0x73, 0x49, 0x6e, 0x4d, 0x79, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x43, + 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x49, 0x6e, 0x4d, 0x79, 0x52, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x13, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, + 0x6c, 0x65, 0x72, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, + 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 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, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x1e, 0x53, + 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, + 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, - 0x72, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x43, - 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, + 0x72, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, + 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, + 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, + 0x65, 0x72, 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, 0x53, - 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 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, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, - 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x81, 0x01, 0x0a, 0x1a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, - 0x6c, 0x65, 0x72, 0x53, 0x75, 0x62, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x75, - 0x62, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, - 0x53, 0x75, 0x62, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, - 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x1a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, + 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x75, 0x62, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, + 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x75, 0x62, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x69, 0x6e, + 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x75, 0x62, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x47, 0x65, 0x74, + 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, + 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, - 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, - 0x0a, 0x09, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1f, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, - 0x0a, 0x17, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x43, - 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, - 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x75, - 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x26, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, - 0x15, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, - 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, - 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, - 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, - 0xc1, 0x09, 0x0a, 0x14, 0x55, 0x73, 0x65, 0x72, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x64, 0x6d, 0x69, - 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 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, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x42, 0x44, 0x12, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x42, 0x44, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x42, 0x44, 0x53, 0x74, 0x61, 0x74, 0x75, 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, 0x53, 0x65, 0x74, 0x42, 0x44, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x10, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x26, + 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, + 0x79, 0x12, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x17, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x75, 0x73, + 0x69, 0x6e, 0x65, 0x73, 0x73, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, + 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x43, 0x61, 0x70, + 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x69, - 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x6c, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, - 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, - 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 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, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8d, 0x01, - 0x0a, 0x1e, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, - 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, - 0x6c, 0x6c, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, + 0x68, 0x65, 0x63, 0x6b, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x43, 0x61, 0x70, 0x61, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, + 0x0a, 0x10, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x73, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x67, + 0x65, 0x6e, 0x63, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, + 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2b, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 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, 0x47, 0x65, 0x74, 0x41, 0x67, 0x65, + 0x6e, 0x63, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x29, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc1, 0x09, 0x0a, 0x14, 0x55, 0x73, 0x65, 0x72, 0x48, 0x6f, + 0x73, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, + 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x4c, 0x65, 0x61, 0x64, 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, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x4c, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, + 0x08, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x44, 0x12, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x42, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x42, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x53, 0x65, + 0x74, 0x42, 0x44, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x42, 0x44, 0x53, + 0x74, 0x61, 0x74, 0x75, 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, 0x53, 0x65, 0x74, + 0x42, 0x44, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x63, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, + 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, + 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, + 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x29, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, + 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 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, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, + 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x1e, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x53, 0x75, + 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, - 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x22, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x41, - 0x64, 0x64, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x28, 0x2e, 0x68, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, + 0x69, 0x65, 0x77, 0x53, 0x75, 0x62, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, + 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, + 0x6e, 0x63, 0x79, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x67, + 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, + 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x41, 0x64, 0x64, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, + 0x73, 0x74, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x41, 0x64, 0x64, 0x41, 0x67, 0x65, 0x6e, 0x63, + 0x79, 0x48, 0x6f, 0x73, 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, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x41, 0x64, 0x64, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 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, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x41, 0x64, 0x64, 0x41, - 0x67, 0x65, 0x6e, 0x63, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, - 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 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, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x60, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x53, 0x65, 0x74, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4a, - 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x67, - 0x65, 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 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, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, - 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 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, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x43, 0x6c, 0x6f, 0x73, 0x65, + 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, + 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, 0x67, 0x65, 0x6e, + 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x41, + 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, + 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x22, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 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, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, + 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, + 0x6e, 0x63, 0x79, 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, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x53, 0x65, 0x74, 0x41, + 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x64, 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, 0x74, + 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 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, } var ( diff --git a/api/proto/user/v1/host.proto b/api/proto/user/v1/host.proto index e15fd8a4..ed9fe554 100644 --- a/api/proto/user/v1/host.proto +++ b/api/proto/user/v1/host.proto @@ -124,6 +124,8 @@ message UserRoleSummary { string coin_seller_status = 11; int64 pending_role_invitations = 12; bool is_manager = 13; + // roles 给后台等需要多身份并列展示的调用方提供稳定字符串集合;原布尔字段继续兼容 App 入口显隐。 + repeated string roles = 14; } // AgencyMembership 是 host 与 Agency 的有时效关系事实。 diff --git a/api/proto/user/v1/user.pb.go b/api/proto/user/v1/user.pb.go index 30e86ef3..f1bb00aa 100644 --- a/api/proto/user/v1/user.pb.go +++ b/api/proto/user/v1/user.pb.go @@ -1304,6 +1304,7 @@ type CronBatchRequest struct { 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"` } func (x *CronBatchRequest) Reset() { @@ -1385,6 +1386,13 @@ func (x *CronBatchRequest) GetPublishingSessionMaxAgeMs() int64 { return 0 } +func (x *CronBatchRequest) GetOpenSessionMaxAgeMs() int64 { + if x != nil { + return x.OpenSessionMaxAgeMs + } + return 0 +} + // CronBatchResponse 返回一个批处理 run 的执行摘要。 type CronBatchResponse struct { state protoimpl.MessageState @@ -6322,6 +6330,350 @@ func (x *BatchGetUsersResponse) GetUsers() map[int64]*User { return nil } +// 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"` +} + +func (x *ActiveUserBanSummary) Reset() { + *x = ActiveUserBanSummary{} + mi := &file_proto_user_v1_user_proto_msgTypes[82] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ActiveUserBanSummary) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ActiveUserBanSummary) ProtoMessage() {} + +func (x *ActiveUserBanSummary) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_user_proto_msgTypes[82] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ActiveUserBanSummary.ProtoReflect.Descriptor instead. +func (*ActiveUserBanSummary) Descriptor() ([]byte, []int) { + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{82} +} + +func (x *ActiveUserBanSummary) GetActive() bool { + if x != nil { + return x.Active + } + return false +} + +func (x *ActiveUserBanSummary) GetSource() string { + if x != nil { + return x.Source + } + return "" +} + +func (x *ActiveUserBanSummary) GetBanId() string { + if x != nil { + return x.BanId + } + return "" +} + +func (x *ActiveUserBanSummary) GetPermanent() bool { + if x != nil { + return x.Permanent + } + return false +} + +func (x *ActiveUserBanSummary) GetExpiresAtMs() int64 { + if x != nil { + return x.ExpiresAtMs + } + return 0 +} + +func (x *ActiveUserBanSummary) GetUserStatus() UserStatus { + if x != nil { + return x.UserStatus + } + return UserStatus_USER_STATUS_UNSPECIFIED +} + +func (x *ActiveUserBanSummary) GetOperatorType() string { + if x != nil { + return x.OperatorType + } + return "" +} + +func (x *ActiveUserBanSummary) GetOperatorUserId() int64 { + if x != nil { + return x.OperatorUserId + } + return 0 +} + +func (x *ActiveUserBanSummary) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *ActiveUserBanSummary) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *ActiveUserBanSummary) GetActiveBanCount() int32 { + if x != nil { + return x.ActiveBanCount + } + return 0 +} + +// 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"` +} + +func (x *UserAdminProfile) Reset() { + *x = UserAdminProfile{} + mi := &file_proto_user_v1_user_proto_msgTypes[83] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UserAdminProfile) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserAdminProfile) ProtoMessage() {} + +func (x *UserAdminProfile) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_user_proto_msgTypes[83] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UserAdminProfile.ProtoReflect.Descriptor instead. +func (*UserAdminProfile) Descriptor() ([]byte, []int) { + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{83} +} + +func (x *UserAdminProfile) GetUser() *User { + if x != nil { + return x.User + } + return nil +} + +func (x *UserAdminProfile) GetBirth() string { + if x != nil { + return x.Birth + } + return "" +} + +func (x *UserAdminProfile) GetRegisterDevice() string { + if x != nil { + return x.RegisterDevice + } + return "" +} + +func (x *UserAdminProfile) GetLastSuccessLoginAtMs() int64 { + if x != nil { + return x.LastSuccessLoginAtMs + } + return 0 +} + +func (x *UserAdminProfile) GetRoles() []string { + if x != nil { + return x.Roles + } + return nil +} + +func (x *UserAdminProfile) GetBan() *ActiveUserBanSummary { + if x != nil { + return x.Ban + } + return nil +} + +func (x *UserAdminProfile) GetLastOperatorType() string { + if x != nil { + return x.LastOperatorType + } + return "" +} + +func (x *UserAdminProfile) GetLastOperatorUserId() int64 { + if x != nil { + return x.LastOperatorUserId + } + return 0 +} + +func (x *UserAdminProfile) GetLastOperationReason() string { + if x != nil { + return x.LastOperationReason + } + return "" +} + +func (x *UserAdminProfile) GetLastOperationAtMs() int64 { + if x != nil { + return x.LastOperationAtMs + } + return 0 +} + +type BatchGetUserAdminProfilesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *BatchGetUserAdminProfilesRequest) Reset() { + *x = BatchGetUserAdminProfilesRequest{} + mi := &file_proto_user_v1_user_proto_msgTypes[84] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BatchGetUserAdminProfilesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BatchGetUserAdminProfilesRequest) ProtoMessage() {} + +func (x *BatchGetUserAdminProfilesRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_user_proto_msgTypes[84] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BatchGetUserAdminProfilesRequest.ProtoReflect.Descriptor instead. +func (*BatchGetUserAdminProfilesRequest) Descriptor() ([]byte, []int) { + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{84} +} + +func (x *BatchGetUserAdminProfilesRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *BatchGetUserAdminProfilesRequest) GetUserIds() []int64 { + if x != nil { + return x.UserIds + } + return nil +} + +type BatchGetUserAdminProfilesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *BatchGetUserAdminProfilesResponse) Reset() { + *x = BatchGetUserAdminProfilesResponse{} + mi := &file_proto_user_v1_user_proto_msgTypes[85] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BatchGetUserAdminProfilesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BatchGetUserAdminProfilesResponse) ProtoMessage() {} + +func (x *BatchGetUserAdminProfilesResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_user_proto_msgTypes[85] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BatchGetUserAdminProfilesResponse.ProtoReflect.Descriptor instead. +func (*BatchGetUserAdminProfilesResponse) Descriptor() ([]byte, []int) { + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{85} +} + +func (x *BatchGetUserAdminProfilesResponse) GetProfiles() map[int64]*UserAdminProfile { + if x != nil { + return x.Profiles + } + return nil +} + // RoomBasicUser 是房间首屏只需要的用户展示基础资料。 type RoomBasicUser struct { state protoimpl.MessageState @@ -6336,7 +6688,7 @@ type RoomBasicUser struct { func (x *RoomBasicUser) Reset() { *x = RoomBasicUser{} - mi := &file_proto_user_v1_user_proto_msgTypes[82] + mi := &file_proto_user_v1_user_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6348,7 +6700,7 @@ func (x *RoomBasicUser) String() string { func (*RoomBasicUser) ProtoMessage() {} func (x *RoomBasicUser) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[82] + mi := &file_proto_user_v1_user_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6361,7 +6713,7 @@ func (x *RoomBasicUser) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomBasicUser.ProtoReflect.Descriptor instead. func (*RoomBasicUser) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{82} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{86} } func (x *RoomBasicUser) GetUserId() int64 { @@ -6404,7 +6756,7 @@ type BatchGetRoomBasicUsersRequest struct { func (x *BatchGetRoomBasicUsersRequest) Reset() { *x = BatchGetRoomBasicUsersRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[83] + mi := &file_proto_user_v1_user_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6416,7 +6768,7 @@ func (x *BatchGetRoomBasicUsersRequest) String() string { func (*BatchGetRoomBasicUsersRequest) ProtoMessage() {} func (x *BatchGetRoomBasicUsersRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[83] + mi := &file_proto_user_v1_user_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6429,7 +6781,7 @@ func (x *BatchGetRoomBasicUsersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BatchGetRoomBasicUsersRequest.ProtoReflect.Descriptor instead. func (*BatchGetRoomBasicUsersRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{83} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{87} } func (x *BatchGetRoomBasicUsersRequest) GetMeta() *RequestMeta { @@ -6457,7 +6809,7 @@ type BatchGetRoomBasicUsersResponse struct { func (x *BatchGetRoomBasicUsersResponse) Reset() { *x = BatchGetRoomBasicUsersResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[84] + mi := &file_proto_user_v1_user_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6469,7 +6821,7 @@ func (x *BatchGetRoomBasicUsersResponse) String() string { func (*BatchGetRoomBasicUsersResponse) ProtoMessage() {} func (x *BatchGetRoomBasicUsersResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[84] + mi := &file_proto_user_v1_user_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6482,7 +6834,7 @@ func (x *BatchGetRoomBasicUsersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BatchGetRoomBasicUsersResponse.ProtoReflect.Descriptor instead. func (*BatchGetRoomBasicUsersResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{84} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{88} } func (x *BatchGetRoomBasicUsersResponse) GetUsers() map[int64]*RoomBasicUser { @@ -6508,7 +6860,7 @@ type ListUserIDsRequest struct { func (x *ListUserIDsRequest) Reset() { *x = ListUserIDsRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[85] + mi := &file_proto_user_v1_user_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6520,7 +6872,7 @@ func (x *ListUserIDsRequest) String() string { func (*ListUserIDsRequest) ProtoMessage() {} func (x *ListUserIDsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[85] + mi := &file_proto_user_v1_user_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6533,7 +6885,7 @@ func (x *ListUserIDsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserIDsRequest.ProtoReflect.Descriptor instead. func (*ListUserIDsRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{85} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{89} } func (x *ListUserIDsRequest) GetMeta() *RequestMeta { @@ -6591,7 +6943,7 @@ type ListUserIDsResponse struct { func (x *ListUserIDsResponse) Reset() { *x = ListUserIDsResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[86] + mi := &file_proto_user_v1_user_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6603,7 +6955,7 @@ func (x *ListUserIDsResponse) String() string { func (*ListUserIDsResponse) ProtoMessage() {} func (x *ListUserIDsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[86] + mi := &file_proto_user_v1_user_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6616,7 +6968,7 @@ func (x *ListUserIDsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserIDsResponse.ProtoReflect.Descriptor instead. func (*ListUserIDsResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{86} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{90} } func (x *ListUserIDsResponse) GetUserIds() []int64 { @@ -6656,7 +7008,7 @@ type UpdateUserProfileRequest struct { func (x *UpdateUserProfileRequest) Reset() { *x = UpdateUserProfileRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[87] + mi := &file_proto_user_v1_user_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6668,7 +7020,7 @@ func (x *UpdateUserProfileRequest) String() string { func (*UpdateUserProfileRequest) ProtoMessage() {} func (x *UpdateUserProfileRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[87] + mi := &file_proto_user_v1_user_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6681,7 +7033,7 @@ func (x *UpdateUserProfileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateUserProfileRequest.ProtoReflect.Descriptor instead. func (*UpdateUserProfileRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{87} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{91} } func (x *UpdateUserProfileRequest) GetMeta() *RequestMeta { @@ -6737,7 +7089,7 @@ type UpdateUserProfileResponse struct { func (x *UpdateUserProfileResponse) Reset() { *x = UpdateUserProfileResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[88] + mi := &file_proto_user_v1_user_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6749,7 +7101,7 @@ func (x *UpdateUserProfileResponse) String() string { func (*UpdateUserProfileResponse) ProtoMessage() {} func (x *UpdateUserProfileResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[88] + mi := &file_proto_user_v1_user_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6762,7 +7114,7 @@ func (x *UpdateUserProfileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateUserProfileResponse.ProtoReflect.Descriptor instead. func (*UpdateUserProfileResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{88} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{92} } func (x *UpdateUserProfileResponse) GetUser() *User { @@ -6785,7 +7137,7 @@ type UpdateUserProfileBackgroundRequest struct { func (x *UpdateUserProfileBackgroundRequest) Reset() { *x = UpdateUserProfileBackgroundRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[89] + mi := &file_proto_user_v1_user_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6797,7 +7149,7 @@ func (x *UpdateUserProfileBackgroundRequest) String() string { func (*UpdateUserProfileBackgroundRequest) ProtoMessage() {} func (x *UpdateUserProfileBackgroundRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[89] + mi := &file_proto_user_v1_user_proto_msgTypes[93] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6810,7 +7162,7 @@ func (x *UpdateUserProfileBackgroundRequest) ProtoReflect() protoreflect.Message // Deprecated: Use UpdateUserProfileBackgroundRequest.ProtoReflect.Descriptor instead. func (*UpdateUserProfileBackgroundRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{89} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{93} } func (x *UpdateUserProfileBackgroundRequest) GetMeta() *RequestMeta { @@ -6845,7 +7197,7 @@ type UpdateUserProfileBackgroundResponse struct { func (x *UpdateUserProfileBackgroundResponse) Reset() { *x = UpdateUserProfileBackgroundResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[90] + mi := &file_proto_user_v1_user_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6857,7 +7209,7 @@ func (x *UpdateUserProfileBackgroundResponse) String() string { func (*UpdateUserProfileBackgroundResponse) ProtoMessage() {} func (x *UpdateUserProfileBackgroundResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[90] + mi := &file_proto_user_v1_user_proto_msgTypes[94] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6870,7 +7222,7 @@ func (x *UpdateUserProfileBackgroundResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use UpdateUserProfileBackgroundResponse.ProtoReflect.Descriptor instead. func (*UpdateUserProfileBackgroundResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{90} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{94} } func (x *UpdateUserProfileBackgroundResponse) GetUser() *User { @@ -6893,7 +7245,7 @@ type UpdateUserContactInfoRequest struct { func (x *UpdateUserContactInfoRequest) Reset() { *x = UpdateUserContactInfoRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[91] + mi := &file_proto_user_v1_user_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6905,7 +7257,7 @@ func (x *UpdateUserContactInfoRequest) String() string { func (*UpdateUserContactInfoRequest) ProtoMessage() {} func (x *UpdateUserContactInfoRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[91] + mi := &file_proto_user_v1_user_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6918,7 +7270,7 @@ func (x *UpdateUserContactInfoRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateUserContactInfoRequest.ProtoReflect.Descriptor instead. func (*UpdateUserContactInfoRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{91} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{95} } func (x *UpdateUserContactInfoRequest) GetMeta() *RequestMeta { @@ -6953,7 +7305,7 @@ type UpdateUserContactInfoResponse struct { func (x *UpdateUserContactInfoResponse) Reset() { *x = UpdateUserContactInfoResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[92] + mi := &file_proto_user_v1_user_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6965,7 +7317,7 @@ func (x *UpdateUserContactInfoResponse) String() string { func (*UpdateUserContactInfoResponse) ProtoMessage() {} func (x *UpdateUserContactInfoResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[92] + mi := &file_proto_user_v1_user_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6978,7 +7330,7 @@ func (x *UpdateUserContactInfoResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateUserContactInfoResponse.ProtoReflect.Descriptor instead. func (*UpdateUserContactInfoResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{92} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{96} } func (x *UpdateUserContactInfoResponse) GetUser() *User { @@ -7001,7 +7353,7 @@ type UpdateUserWithdrawAddressRequest struct { func (x *UpdateUserWithdrawAddressRequest) Reset() { *x = UpdateUserWithdrawAddressRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[93] + mi := &file_proto_user_v1_user_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7013,7 +7365,7 @@ func (x *UpdateUserWithdrawAddressRequest) String() string { func (*UpdateUserWithdrawAddressRequest) ProtoMessage() {} func (x *UpdateUserWithdrawAddressRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[93] + mi := &file_proto_user_v1_user_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7026,7 +7378,7 @@ func (x *UpdateUserWithdrawAddressRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateUserWithdrawAddressRequest.ProtoReflect.Descriptor instead. func (*UpdateUserWithdrawAddressRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{93} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{97} } func (x *UpdateUserWithdrawAddressRequest) GetMeta() *RequestMeta { @@ -7061,7 +7413,7 @@ type UpdateUserWithdrawAddressResponse struct { func (x *UpdateUserWithdrawAddressResponse) Reset() { *x = UpdateUserWithdrawAddressResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[94] + mi := &file_proto_user_v1_user_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7073,7 +7425,7 @@ func (x *UpdateUserWithdrawAddressResponse) String() string { func (*UpdateUserWithdrawAddressResponse) ProtoMessage() {} func (x *UpdateUserWithdrawAddressResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[94] + mi := &file_proto_user_v1_user_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7086,7 +7438,7 @@ func (x *UpdateUserWithdrawAddressResponse) ProtoReflect() protoreflect.Message // Deprecated: Use UpdateUserWithdrawAddressResponse.ProtoReflect.Descriptor instead. func (*UpdateUserWithdrawAddressResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{94} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{98} } func (x *UpdateUserWithdrawAddressResponse) GetUser() *User { @@ -7109,7 +7461,7 @@ type ChangeUserCountryRequest struct { func (x *ChangeUserCountryRequest) Reset() { *x = ChangeUserCountryRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[95] + mi := &file_proto_user_v1_user_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7121,7 +7473,7 @@ func (x *ChangeUserCountryRequest) String() string { func (*ChangeUserCountryRequest) ProtoMessage() {} func (x *ChangeUserCountryRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[95] + mi := &file_proto_user_v1_user_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7134,7 +7486,7 @@ func (x *ChangeUserCountryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeUserCountryRequest.ProtoReflect.Descriptor instead. func (*ChangeUserCountryRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{95} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{99} } func (x *ChangeUserCountryRequest) GetMeta() *RequestMeta { @@ -7173,7 +7525,7 @@ type AdminChangeUserCountryRequest struct { func (x *AdminChangeUserCountryRequest) Reset() { *x = AdminChangeUserCountryRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[96] + mi := &file_proto_user_v1_user_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7185,7 +7537,7 @@ func (x *AdminChangeUserCountryRequest) String() string { func (*AdminChangeUserCountryRequest) ProtoMessage() {} func (x *AdminChangeUserCountryRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[96] + mi := &file_proto_user_v1_user_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7198,7 +7550,7 @@ func (x *AdminChangeUserCountryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminChangeUserCountryRequest.ProtoReflect.Descriptor instead. func (*AdminChangeUserCountryRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{96} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{100} } func (x *AdminChangeUserCountryRequest) GetMeta() *RequestMeta { @@ -7251,7 +7603,7 @@ type ChangeUserCountryResponse struct { func (x *ChangeUserCountryResponse) Reset() { *x = ChangeUserCountryResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[97] + mi := &file_proto_user_v1_user_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7263,7 +7615,7 @@ func (x *ChangeUserCountryResponse) String() string { func (*ChangeUserCountryResponse) ProtoMessage() {} func (x *ChangeUserCountryResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[97] + mi := &file_proto_user_v1_user_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7276,7 +7628,7 @@ func (x *ChangeUserCountryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeUserCountryResponse.ProtoReflect.Descriptor instead. func (*ChangeUserCountryResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{97} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{101} } func (x *ChangeUserCountryResponse) GetUser() *User { @@ -7332,7 +7684,7 @@ type SetUserStatusRequest struct { func (x *SetUserStatusRequest) Reset() { *x = SetUserStatusRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[98] + mi := &file_proto_user_v1_user_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7344,7 +7696,7 @@ func (x *SetUserStatusRequest) String() string { func (*SetUserStatusRequest) ProtoMessage() {} func (x *SetUserStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[98] + mi := &file_proto_user_v1_user_proto_msgTypes[102] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7357,7 +7709,7 @@ func (x *SetUserStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetUserStatusRequest.ProtoReflect.Descriptor instead. func (*SetUserStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{98} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{102} } func (x *SetUserStatusRequest) GetMeta() *RequestMeta { @@ -7424,7 +7776,7 @@ type SetUserStatusResponse struct { func (x *SetUserStatusResponse) Reset() { *x = SetUserStatusResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[99] + mi := &file_proto_user_v1_user_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7436,7 +7788,7 @@ func (x *SetUserStatusResponse) String() string { func (*SetUserStatusResponse) ProtoMessage() {} func (x *SetUserStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[99] + mi := &file_proto_user_v1_user_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7449,7 +7801,7 @@ func (x *SetUserStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetUserStatusResponse.ProtoReflect.Descriptor instead. func (*SetUserStatusResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{99} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{103} } func (x *SetUserStatusResponse) GetUser() *User { @@ -7529,6 +7881,417 @@ func (x *SetUserStatusResponse) GetAccessTokenRevokeError() string { return "" } +// 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"` +} + +func (x *AdminUserBan) Reset() { + *x = AdminUserBan{} + mi := &file_proto_user_v1_user_proto_msgTypes[104] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdminUserBan) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdminUserBan) ProtoMessage() {} + +func (x *AdminUserBan) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_user_proto_msgTypes[104] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AdminUserBan.ProtoReflect.Descriptor instead. +func (*AdminUserBan) Descriptor() ([]byte, []int) { + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{104} +} + +func (x *AdminUserBan) GetBanId() string { + if x != nil { + return x.BanId + } + return "" +} + +func (x *AdminUserBan) GetCommandId() string { + if x != nil { + return x.CommandId + } + return "" +} + +func (x *AdminUserBan) GetTargetUserId() int64 { + if x != nil { + return x.TargetUserId + } + return 0 +} + +func (x *AdminUserBan) GetExpiresAtMs() int64 { + if x != nil { + return x.ExpiresAtMs + } + return 0 +} + +func (x *AdminUserBan) GetPermanent() bool { + if x != nil { + return x.Permanent + } + return false +} + +func (x *AdminUserBan) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *AdminUserBan) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *AdminUserBan) GetOperatorAdminId() int64 { + if x != nil { + return x.OperatorAdminId + } + return 0 +} + +func (x *AdminUserBan) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *AdminUserBan) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +func (x *AdminUserBan) GetReleasedByAdminId() int64 { + if x != nil { + return x.ReleasedByAdminId + } + return 0 +} + +func (x *AdminUserBan) GetReleasedReason() string { + if x != nil { + return x.ReleasedReason + } + return "" +} + +func (x *AdminUserBan) GetReleasedAtMs() int64 { + if x != nil { + return x.ReleasedAtMs + } + return 0 +} + +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"` +} + +func (x *AdminBanUserRequest) Reset() { + *x = AdminBanUserRequest{} + mi := &file_proto_user_v1_user_proto_msgTypes[105] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdminBanUserRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdminBanUserRequest) ProtoMessage() {} + +func (x *AdminBanUserRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_user_proto_msgTypes[105] + 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 AdminBanUserRequest.ProtoReflect.Descriptor instead. +func (*AdminBanUserRequest) Descriptor() ([]byte, []int) { + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{105} +} + +func (x *AdminBanUserRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *AdminBanUserRequest) GetCommandId() string { + if x != nil { + return x.CommandId + } + return "" +} + +func (x *AdminBanUserRequest) GetTargetUserId() int64 { + if x != nil { + return x.TargetUserId + } + return 0 +} + +func (x *AdminBanUserRequest) GetExpiresAtMs() int64 { + if x != nil { + return x.ExpiresAtMs + } + return 0 +} + +func (x *AdminBanUserRequest) GetOperatorAdminId() int64 { + if x != nil { + return x.OperatorAdminId + } + return 0 +} + +func (x *AdminBanUserRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type AdminBanUserResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *AdminBanUserResponse) Reset() { + *x = AdminBanUserResponse{} + mi := &file_proto_user_v1_user_proto_msgTypes[106] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdminBanUserResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdminBanUserResponse) ProtoMessage() {} + +func (x *AdminBanUserResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_user_proto_msgTypes[106] + 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 AdminBanUserResponse.ProtoReflect.Descriptor instead. +func (*AdminBanUserResponse) Descriptor() ([]byte, []int) { + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{106} +} + +func (x *AdminBanUserResponse) GetBan() *AdminUserBan { + if x != nil { + return x.Ban + } + return nil +} + +func (x *AdminBanUserResponse) GetStatus() *SetUserStatusResponse { + if x != nil { + return x.Status + } + return nil +} + +// AdminUnbanUserRequest 释放一条管理员封禁;ban_id 留空时按目标用户释放最新一条,其他管理员或经理封禁仍会阻止账号恢复。 +type AdminUnbanUserRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + 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"` +} + +func (x *AdminUnbanUserRequest) Reset() { + *x = AdminUnbanUserRequest{} + mi := &file_proto_user_v1_user_proto_msgTypes[107] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdminUnbanUserRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdminUnbanUserRequest) ProtoMessage() {} + +func (x *AdminUnbanUserRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_user_proto_msgTypes[107] + 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 AdminUnbanUserRequest.ProtoReflect.Descriptor instead. +func (*AdminUnbanUserRequest) Descriptor() ([]byte, []int) { + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{107} +} + +func (x *AdminUnbanUserRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *AdminUnbanUserRequest) GetBanId() string { + if x != nil { + return x.BanId + } + return "" +} + +func (x *AdminUnbanUserRequest) GetTargetUserId() int64 { + if x != nil { + return x.TargetUserId + } + return 0 +} + +func (x *AdminUnbanUserRequest) GetOperatorAdminId() int64 { + if x != nil { + return x.OperatorAdminId + } + return 0 +} + +func (x *AdminUnbanUserRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type AdminUnbanUserResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *AdminUnbanUserResponse) Reset() { + *x = AdminUnbanUserResponse{} + mi := &file_proto_user_v1_user_proto_msgTypes[108] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdminUnbanUserResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdminUnbanUserResponse) ProtoMessage() {} + +func (x *AdminUnbanUserResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_user_proto_msgTypes[108] + 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 AdminUnbanUserResponse.ProtoReflect.Descriptor instead. +func (*AdminUnbanUserResponse) Descriptor() ([]byte, []int) { + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{108} +} + +func (x *AdminUnbanUserResponse) GetBan() *AdminUserBan { + if x != nil { + return x.Ban + } + return nil +} + +func (x *AdminUnbanUserResponse) GetStatus() *SetUserStatusResponse { + if x != nil { + return x.Status + } + return nil +} + type ManagerUserBlock struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -7550,7 +8313,7 @@ type ManagerUserBlock struct { func (x *ManagerUserBlock) Reset() { *x = ManagerUserBlock{} - mi := &file_proto_user_v1_user_proto_msgTypes[100] + mi := &file_proto_user_v1_user_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7562,7 +8325,7 @@ func (x *ManagerUserBlock) String() string { func (*ManagerUserBlock) ProtoMessage() {} func (x *ManagerUserBlock) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[100] + mi := &file_proto_user_v1_user_proto_msgTypes[109] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7575,7 +8338,7 @@ func (x *ManagerUserBlock) ProtoReflect() protoreflect.Message { // Deprecated: Use ManagerUserBlock.ProtoReflect.Descriptor instead. func (*ManagerUserBlock) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{100} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{109} } func (x *ManagerUserBlock) GetBlockId() string { @@ -7677,7 +8440,7 @@ type CreateManagerUserBlockRequest struct { func (x *CreateManagerUserBlockRequest) Reset() { *x = CreateManagerUserBlockRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[101] + mi := &file_proto_user_v1_user_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7689,7 +8452,7 @@ func (x *CreateManagerUserBlockRequest) String() string { func (*CreateManagerUserBlockRequest) ProtoMessage() {} func (x *CreateManagerUserBlockRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[101] + mi := &file_proto_user_v1_user_proto_msgTypes[110] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7702,7 +8465,7 @@ func (x *CreateManagerUserBlockRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateManagerUserBlockRequest.ProtoReflect.Descriptor instead. func (*CreateManagerUserBlockRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{101} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{110} } func (x *CreateManagerUserBlockRequest) GetMeta() *RequestMeta { @@ -7758,7 +8521,7 @@ type CreateManagerUserBlockResponse struct { func (x *CreateManagerUserBlockResponse) Reset() { *x = CreateManagerUserBlockResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[102] + mi := &file_proto_user_v1_user_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7770,7 +8533,7 @@ func (x *CreateManagerUserBlockResponse) String() string { func (*CreateManagerUserBlockResponse) ProtoMessage() {} func (x *CreateManagerUserBlockResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[102] + mi := &file_proto_user_v1_user_proto_msgTypes[111] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7783,7 +8546,7 @@ func (x *CreateManagerUserBlockResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateManagerUserBlockResponse.ProtoReflect.Descriptor instead. func (*CreateManagerUserBlockResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{102} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{111} } func (x *CreateManagerUserBlockResponse) GetBlock() *ManagerUserBlock { @@ -7813,7 +8576,7 @@ type ListManagerUserBlocksRequest struct { func (x *ListManagerUserBlocksRequest) Reset() { *x = ListManagerUserBlocksRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[103] + mi := &file_proto_user_v1_user_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7825,7 +8588,7 @@ func (x *ListManagerUserBlocksRequest) String() string { func (*ListManagerUserBlocksRequest) ProtoMessage() {} func (x *ListManagerUserBlocksRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[103] + mi := &file_proto_user_v1_user_proto_msgTypes[112] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7838,7 +8601,7 @@ func (x *ListManagerUserBlocksRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListManagerUserBlocksRequest.ProtoReflect.Descriptor instead. func (*ListManagerUserBlocksRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{103} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{112} } func (x *ListManagerUserBlocksRequest) GetMeta() *RequestMeta { @@ -7879,7 +8642,7 @@ type ListManagerUserBlocksResponse struct { func (x *ListManagerUserBlocksResponse) Reset() { *x = ListManagerUserBlocksResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[104] + mi := &file_proto_user_v1_user_proto_msgTypes[113] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7891,7 +8654,7 @@ func (x *ListManagerUserBlocksResponse) String() string { func (*ListManagerUserBlocksResponse) ProtoMessage() {} func (x *ListManagerUserBlocksResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[104] + mi := &file_proto_user_v1_user_proto_msgTypes[113] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7904,7 +8667,7 @@ func (x *ListManagerUserBlocksResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListManagerUserBlocksResponse.ProtoReflect.Descriptor instead. func (*ListManagerUserBlocksResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{104} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{113} } func (x *ListManagerUserBlocksResponse) GetBlocks() []*ManagerUserBlock { @@ -7927,7 +8690,7 @@ type UnblockManagerUserRequest struct { func (x *UnblockManagerUserRequest) Reset() { *x = UnblockManagerUserRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[105] + mi := &file_proto_user_v1_user_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7939,7 +8702,7 @@ func (x *UnblockManagerUserRequest) String() string { func (*UnblockManagerUserRequest) ProtoMessage() {} func (x *UnblockManagerUserRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[105] + mi := &file_proto_user_v1_user_proto_msgTypes[114] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7952,7 +8715,7 @@ func (x *UnblockManagerUserRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnblockManagerUserRequest.ProtoReflect.Descriptor instead. func (*UnblockManagerUserRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{105} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{114} } func (x *UnblockManagerUserRequest) GetMeta() *RequestMeta { @@ -7994,7 +8757,7 @@ type UnblockManagerUserResponse struct { func (x *UnblockManagerUserResponse) Reset() { *x = UnblockManagerUserResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[106] + mi := &file_proto_user_v1_user_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8006,7 +8769,7 @@ func (x *UnblockManagerUserResponse) String() string { func (*UnblockManagerUserResponse) ProtoMessage() {} func (x *UnblockManagerUserResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[106] + mi := &file_proto_user_v1_user_proto_msgTypes[115] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8019,7 +8782,7 @@ func (x *UnblockManagerUserResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnblockManagerUserResponse.ProtoReflect.Descriptor instead. func (*UnblockManagerUserResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{106} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{115} } func (x *UnblockManagerUserResponse) GetBlock() *ManagerUserBlock { @@ -8053,7 +8816,7 @@ type CompleteOnboardingRequest struct { func (x *CompleteOnboardingRequest) Reset() { *x = CompleteOnboardingRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[107] + mi := &file_proto_user_v1_user_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8065,7 +8828,7 @@ func (x *CompleteOnboardingRequest) String() string { func (*CompleteOnboardingRequest) ProtoMessage() {} func (x *CompleteOnboardingRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[107] + mi := &file_proto_user_v1_user_proto_msgTypes[116] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8078,7 +8841,7 @@ func (x *CompleteOnboardingRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CompleteOnboardingRequest.ProtoReflect.Descriptor instead. func (*CompleteOnboardingRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{107} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{116} } func (x *CompleteOnboardingRequest) GetMeta() *RequestMeta { @@ -8146,7 +8909,7 @@ type CompleteOnboardingResponse struct { func (x *CompleteOnboardingResponse) Reset() { *x = CompleteOnboardingResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[108] + mi := &file_proto_user_v1_user_proto_msgTypes[117] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8158,7 +8921,7 @@ func (x *CompleteOnboardingResponse) String() string { func (*CompleteOnboardingResponse) ProtoMessage() {} func (x *CompleteOnboardingResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[108] + mi := &file_proto_user_v1_user_proto_msgTypes[117] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8171,7 +8934,7 @@ func (x *CompleteOnboardingResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CompleteOnboardingResponse.ProtoReflect.Descriptor instead. func (*CompleteOnboardingResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{108} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{117} } func (x *CompleteOnboardingResponse) GetUser() *User { @@ -8229,7 +8992,7 @@ type SearchInviteReferrerRequest struct { func (x *SearchInviteReferrerRequest) Reset() { *x = SearchInviteReferrerRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[109] + mi := &file_proto_user_v1_user_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8241,7 +9004,7 @@ func (x *SearchInviteReferrerRequest) String() string { func (*SearchInviteReferrerRequest) ProtoMessage() {} func (x *SearchInviteReferrerRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[109] + mi := &file_proto_user_v1_user_proto_msgTypes[118] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8254,7 +9017,7 @@ func (x *SearchInviteReferrerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SearchInviteReferrerRequest.ProtoReflect.Descriptor instead. func (*SearchInviteReferrerRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{109} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{118} } func (x *SearchInviteReferrerRequest) GetMeta() *RequestMeta { @@ -8288,7 +9051,7 @@ type SearchInviteReferrerResponse struct { func (x *SearchInviteReferrerResponse) Reset() { *x = SearchInviteReferrerResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[110] + mi := &file_proto_user_v1_user_proto_msgTypes[119] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8300,7 +9063,7 @@ func (x *SearchInviteReferrerResponse) String() string { func (*SearchInviteReferrerResponse) ProtoMessage() {} func (x *SearchInviteReferrerResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[110] + mi := &file_proto_user_v1_user_proto_msgTypes[119] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8313,7 +9076,7 @@ func (x *SearchInviteReferrerResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SearchInviteReferrerResponse.ProtoReflect.Descriptor instead. func (*SearchInviteReferrerResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{110} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{119} } func (x *SearchInviteReferrerResponse) GetInviter() *User { @@ -8336,7 +9099,7 @@ type BindInviteReferrerRequest struct { func (x *BindInviteReferrerRequest) Reset() { *x = BindInviteReferrerRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[111] + mi := &file_proto_user_v1_user_proto_msgTypes[120] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8348,7 +9111,7 @@ func (x *BindInviteReferrerRequest) String() string { func (*BindInviteReferrerRequest) ProtoMessage() {} func (x *BindInviteReferrerRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[111] + mi := &file_proto_user_v1_user_proto_msgTypes[120] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8361,7 +9124,7 @@ func (x *BindInviteReferrerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BindInviteReferrerRequest.ProtoReflect.Descriptor instead. func (*BindInviteReferrerRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{111} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{120} } func (x *BindInviteReferrerRequest) GetMeta() *RequestMeta { @@ -8396,7 +9159,7 @@ type BindInviteReferrerResponse struct { func (x *BindInviteReferrerResponse) Reset() { *x = BindInviteReferrerResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[112] + mi := &file_proto_user_v1_user_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8408,7 +9171,7 @@ func (x *BindInviteReferrerResponse) String() string { func (*BindInviteReferrerResponse) ProtoMessage() {} func (x *BindInviteReferrerResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[112] + mi := &file_proto_user_v1_user_proto_msgTypes[121] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8421,7 +9184,7 @@ func (x *BindInviteReferrerResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BindInviteReferrerResponse.ProtoReflect.Descriptor instead. func (*BindInviteReferrerResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{112} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{121} } func (x *BindInviteReferrerResponse) GetInvite() *InviteBinding { @@ -8458,7 +9221,7 @@ type BindPushTokenRequest struct { func (x *BindPushTokenRequest) Reset() { *x = BindPushTokenRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[113] + mi := &file_proto_user_v1_user_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8470,7 +9233,7 @@ func (x *BindPushTokenRequest) String() string { func (*BindPushTokenRequest) ProtoMessage() {} func (x *BindPushTokenRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[113] + mi := &file_proto_user_v1_user_proto_msgTypes[122] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8483,7 +9246,7 @@ func (x *BindPushTokenRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BindPushTokenRequest.ProtoReflect.Descriptor instead. func (*BindPushTokenRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{113} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{122} } func (x *BindPushTokenRequest) GetMeta() *RequestMeta { @@ -8560,7 +9323,7 @@ type BindPushTokenResponse struct { func (x *BindPushTokenResponse) Reset() { *x = BindPushTokenResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[114] + mi := &file_proto_user_v1_user_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8572,7 +9335,7 @@ func (x *BindPushTokenResponse) String() string { func (*BindPushTokenResponse) ProtoMessage() {} func (x *BindPushTokenResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[114] + mi := &file_proto_user_v1_user_proto_msgTypes[123] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8585,7 +9348,7 @@ func (x *BindPushTokenResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BindPushTokenResponse.ProtoReflect.Descriptor instead. func (*BindPushTokenResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{114} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{123} } func (x *BindPushTokenResponse) GetBound() bool { @@ -8617,7 +9380,7 @@ type DeletePushTokenRequest struct { func (x *DeletePushTokenRequest) Reset() { *x = DeletePushTokenRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[115] + mi := &file_proto_user_v1_user_proto_msgTypes[124] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8629,7 +9392,7 @@ func (x *DeletePushTokenRequest) String() string { func (*DeletePushTokenRequest) ProtoMessage() {} func (x *DeletePushTokenRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[115] + mi := &file_proto_user_v1_user_proto_msgTypes[124] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8642,7 +9405,7 @@ func (x *DeletePushTokenRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeletePushTokenRequest.ProtoReflect.Descriptor instead. func (*DeletePushTokenRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{115} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{124} } func (x *DeletePushTokenRequest) GetMeta() *RequestMeta { @@ -8684,7 +9447,7 @@ type DeletePushTokenResponse struct { func (x *DeletePushTokenResponse) Reset() { *x = DeletePushTokenResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[116] + mi := &file_proto_user_v1_user_proto_msgTypes[125] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8696,7 +9459,7 @@ func (x *DeletePushTokenResponse) String() string { func (*DeletePushTokenResponse) ProtoMessage() {} func (x *DeletePushTokenResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[116] + mi := &file_proto_user_v1_user_proto_msgTypes[125] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8709,7 +9472,7 @@ func (x *DeletePushTokenResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeletePushTokenResponse.ProtoReflect.Descriptor instead. func (*DeletePushTokenResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{116} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{125} } func (x *DeletePushTokenResponse) GetDeleted() bool { @@ -8749,7 +9512,7 @@ type Country struct { func (x *Country) Reset() { *x = Country{} - mi := &file_proto_user_v1_user_proto_msgTypes[117] + mi := &file_proto_user_v1_user_proto_msgTypes[126] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8761,7 +9524,7 @@ func (x *Country) String() string { func (*Country) ProtoMessage() {} func (x *Country) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[117] + mi := &file_proto_user_v1_user_proto_msgTypes[126] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8774,7 +9537,7 @@ func (x *Country) ProtoReflect() protoreflect.Message { // Deprecated: Use Country.ProtoReflect.Descriptor instead. func (*Country) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{117} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{126} } func (x *Country) GetCountryId() int64 { @@ -8887,7 +9650,7 @@ type Region struct { func (x *Region) Reset() { *x = Region{} - mi := &file_proto_user_v1_user_proto_msgTypes[118] + mi := &file_proto_user_v1_user_proto_msgTypes[127] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8899,7 +9662,7 @@ func (x *Region) String() string { func (*Region) ProtoMessage() {} func (x *Region) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[118] + mi := &file_proto_user_v1_user_proto_msgTypes[127] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8912,7 +9675,7 @@ func (x *Region) ProtoReflect() protoreflect.Message { // Deprecated: Use Region.ProtoReflect.Descriptor instead. func (*Region) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{118} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{127} } func (x *Region) GetRegionId() int64 { @@ -8989,7 +9752,7 @@ type ListCountriesRequest struct { func (x *ListCountriesRequest) Reset() { *x = ListCountriesRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[119] + mi := &file_proto_user_v1_user_proto_msgTypes[128] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9001,7 +9764,7 @@ func (x *ListCountriesRequest) String() string { func (*ListCountriesRequest) ProtoMessage() {} func (x *ListCountriesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[119] + mi := &file_proto_user_v1_user_proto_msgTypes[128] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9014,7 +9777,7 @@ func (x *ListCountriesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListCountriesRequest.ProtoReflect.Descriptor instead. func (*ListCountriesRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{119} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{128} } func (x *ListCountriesRequest) GetMeta() *RequestMeta { @@ -9041,7 +9804,7 @@ type ListCountriesResponse struct { func (x *ListCountriesResponse) Reset() { *x = ListCountriesResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[120] + mi := &file_proto_user_v1_user_proto_msgTypes[129] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9053,7 +9816,7 @@ func (x *ListCountriesResponse) String() string { func (*ListCountriesResponse) ProtoMessage() {} func (x *ListCountriesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[120] + mi := &file_proto_user_v1_user_proto_msgTypes[129] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9066,7 +9829,7 @@ func (x *ListCountriesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListCountriesResponse.ProtoReflect.Descriptor instead. func (*ListCountriesResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{120} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{129} } func (x *ListCountriesResponse) GetCountries() []*Country { @@ -9096,7 +9859,7 @@ type UpdateCountryRequest struct { func (x *UpdateCountryRequest) Reset() { *x = UpdateCountryRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[121] + mi := &file_proto_user_v1_user_proto_msgTypes[130] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9108,7 +9871,7 @@ func (x *UpdateCountryRequest) String() string { func (*UpdateCountryRequest) ProtoMessage() {} func (x *UpdateCountryRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[121] + mi := &file_proto_user_v1_user_proto_msgTypes[130] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9121,7 +9884,7 @@ func (x *UpdateCountryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateCountryRequest.ProtoReflect.Descriptor instead. func (*UpdateCountryRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{121} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{130} } func (x *UpdateCountryRequest) GetMeta() *RequestMeta { @@ -9204,7 +9967,7 @@ type CountryResponse struct { func (x *CountryResponse) Reset() { *x = CountryResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[122] + mi := &file_proto_user_v1_user_proto_msgTypes[131] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9216,7 +9979,7 @@ func (x *CountryResponse) String() string { func (*CountryResponse) ProtoMessage() {} func (x *CountryResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[122] + mi := &file_proto_user_v1_user_proto_msgTypes[131] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9229,7 +9992,7 @@ func (x *CountryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CountryResponse.ProtoReflect.Descriptor instead. func (*CountryResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{122} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{131} } func (x *CountryResponse) GetCountry() *Country { @@ -9249,7 +10012,7 @@ type ListRegistrationCountriesRequest struct { func (x *ListRegistrationCountriesRequest) Reset() { *x = ListRegistrationCountriesRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[123] + mi := &file_proto_user_v1_user_proto_msgTypes[132] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9261,7 +10024,7 @@ func (x *ListRegistrationCountriesRequest) String() string { func (*ListRegistrationCountriesRequest) ProtoMessage() {} func (x *ListRegistrationCountriesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[123] + mi := &file_proto_user_v1_user_proto_msgTypes[132] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9274,7 +10037,7 @@ func (x *ListRegistrationCountriesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRegistrationCountriesRequest.ProtoReflect.Descriptor instead. func (*ListRegistrationCountriesRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{123} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{132} } func (x *ListRegistrationCountriesRequest) GetMeta() *RequestMeta { @@ -9294,7 +10057,7 @@ type ListRegistrationCountriesResponse struct { func (x *ListRegistrationCountriesResponse) Reset() { *x = ListRegistrationCountriesResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[124] + mi := &file_proto_user_v1_user_proto_msgTypes[133] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9306,7 +10069,7 @@ func (x *ListRegistrationCountriesResponse) String() string { func (*ListRegistrationCountriesResponse) ProtoMessage() {} func (x *ListRegistrationCountriesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[124] + mi := &file_proto_user_v1_user_proto_msgTypes[133] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9319,7 +10082,7 @@ func (x *ListRegistrationCountriesResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ListRegistrationCountriesResponse.ProtoReflect.Descriptor instead. func (*ListRegistrationCountriesResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{124} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{133} } func (x *ListRegistrationCountriesResponse) GetCountries() []*Country { @@ -9341,7 +10104,7 @@ type LoginRiskBlockedCountry struct { func (x *LoginRiskBlockedCountry) Reset() { *x = LoginRiskBlockedCountry{} - mi := &file_proto_user_v1_user_proto_msgTypes[125] + mi := &file_proto_user_v1_user_proto_msgTypes[134] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9353,7 +10116,7 @@ func (x *LoginRiskBlockedCountry) String() string { func (*LoginRiskBlockedCountry) ProtoMessage() {} func (x *LoginRiskBlockedCountry) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[125] + mi := &file_proto_user_v1_user_proto_msgTypes[134] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9366,7 +10129,7 @@ func (x *LoginRiskBlockedCountry) ProtoReflect() protoreflect.Message { // Deprecated: Use LoginRiskBlockedCountry.ProtoReflect.Descriptor instead. func (*LoginRiskBlockedCountry) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{125} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{134} } func (x *LoginRiskBlockedCountry) GetCountryCode() string { @@ -9400,7 +10163,7 @@ type ListLoginRiskBlockedCountriesRequest struct { func (x *ListLoginRiskBlockedCountriesRequest) Reset() { *x = ListLoginRiskBlockedCountriesRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[126] + mi := &file_proto_user_v1_user_proto_msgTypes[135] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9412,7 +10175,7 @@ func (x *ListLoginRiskBlockedCountriesRequest) String() string { func (*ListLoginRiskBlockedCountriesRequest) ProtoMessage() {} func (x *ListLoginRiskBlockedCountriesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[126] + mi := &file_proto_user_v1_user_proto_msgTypes[135] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9425,7 +10188,7 @@ func (x *ListLoginRiskBlockedCountriesRequest) ProtoReflect() protoreflect.Messa // Deprecated: Use ListLoginRiskBlockedCountriesRequest.ProtoReflect.Descriptor instead. func (*ListLoginRiskBlockedCountriesRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{126} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{135} } func (x *ListLoginRiskBlockedCountriesRequest) GetMeta() *RequestMeta { @@ -9446,7 +10209,7 @@ type ListLoginRiskBlockedCountriesResponse struct { func (x *ListLoginRiskBlockedCountriesResponse) Reset() { *x = ListLoginRiskBlockedCountriesResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[127] + mi := &file_proto_user_v1_user_proto_msgTypes[136] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9458,7 +10221,7 @@ func (x *ListLoginRiskBlockedCountriesResponse) String() string { func (*ListLoginRiskBlockedCountriesResponse) ProtoMessage() {} func (x *ListLoginRiskBlockedCountriesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[127] + mi := &file_proto_user_v1_user_proto_msgTypes[136] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9471,7 +10234,7 @@ func (x *ListLoginRiskBlockedCountriesResponse) ProtoReflect() protoreflect.Mess // Deprecated: Use ListLoginRiskBlockedCountriesResponse.ProtoReflect.Descriptor instead. func (*ListLoginRiskBlockedCountriesResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{127} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{136} } func (x *ListLoginRiskBlockedCountriesResponse) GetCountries() []*LoginRiskBlockedCountry { @@ -9499,7 +10262,7 @@ type ListRegionsRequest struct { func (x *ListRegionsRequest) Reset() { *x = ListRegionsRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[128] + mi := &file_proto_user_v1_user_proto_msgTypes[137] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9511,7 +10274,7 @@ func (x *ListRegionsRequest) String() string { func (*ListRegionsRequest) ProtoMessage() {} func (x *ListRegionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[128] + mi := &file_proto_user_v1_user_proto_msgTypes[137] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9524,7 +10287,7 @@ func (x *ListRegionsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRegionsRequest.ProtoReflect.Descriptor instead. func (*ListRegionsRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{128} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{137} } func (x *ListRegionsRequest) GetMeta() *RequestMeta { @@ -9551,7 +10314,7 @@ type ListRegionsResponse struct { func (x *ListRegionsResponse) Reset() { *x = ListRegionsResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[129] + mi := &file_proto_user_v1_user_proto_msgTypes[138] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9563,7 +10326,7 @@ func (x *ListRegionsResponse) String() string { func (*ListRegionsResponse) ProtoMessage() {} func (x *ListRegionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[129] + mi := &file_proto_user_v1_user_proto_msgTypes[138] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9576,7 +10339,7 @@ func (x *ListRegionsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRegionsResponse.ProtoReflect.Descriptor instead. func (*ListRegionsResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{129} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{138} } func (x *ListRegionsResponse) GetRegions() []*Region { @@ -9597,7 +10360,7 @@ type GetRegionRequest struct { func (x *GetRegionRequest) Reset() { *x = GetRegionRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[130] + mi := &file_proto_user_v1_user_proto_msgTypes[139] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9609,7 +10372,7 @@ func (x *GetRegionRequest) String() string { func (*GetRegionRequest) ProtoMessage() {} func (x *GetRegionRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[130] + mi := &file_proto_user_v1_user_proto_msgTypes[139] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9622,7 +10385,7 @@ func (x *GetRegionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRegionRequest.ProtoReflect.Descriptor instead. func (*GetRegionRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{130} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{139} } func (x *GetRegionRequest) GetMeta() *RequestMeta { @@ -9655,7 +10418,7 @@ type UpdateRegionRequest struct { func (x *UpdateRegionRequest) Reset() { *x = UpdateRegionRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[131] + mi := &file_proto_user_v1_user_proto_msgTypes[140] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9667,7 +10430,7 @@ func (x *UpdateRegionRequest) String() string { func (*UpdateRegionRequest) ProtoMessage() {} func (x *UpdateRegionRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[131] + mi := &file_proto_user_v1_user_proto_msgTypes[140] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9680,7 +10443,7 @@ func (x *UpdateRegionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRegionRequest.ProtoReflect.Descriptor instead. func (*UpdateRegionRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{131} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{140} } func (x *UpdateRegionRequest) GetMeta() *RequestMeta { @@ -9738,7 +10501,7 @@ type ReplaceRegionCountriesRequest struct { func (x *ReplaceRegionCountriesRequest) Reset() { *x = ReplaceRegionCountriesRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[132] + mi := &file_proto_user_v1_user_proto_msgTypes[141] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9750,7 +10513,7 @@ func (x *ReplaceRegionCountriesRequest) String() string { func (*ReplaceRegionCountriesRequest) ProtoMessage() {} func (x *ReplaceRegionCountriesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[132] + mi := &file_proto_user_v1_user_proto_msgTypes[141] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9763,7 +10526,7 @@ func (x *ReplaceRegionCountriesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReplaceRegionCountriesRequest.ProtoReflect.Descriptor instead. func (*ReplaceRegionCountriesRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{132} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{141} } func (x *ReplaceRegionCountriesRequest) GetMeta() *RequestMeta { @@ -9804,7 +10567,7 @@ type RegionResponse struct { func (x *RegionResponse) Reset() { *x = RegionResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[133] + mi := &file_proto_user_v1_user_proto_msgTypes[142] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9816,7 +10579,7 @@ func (x *RegionResponse) String() string { func (*RegionResponse) ProtoMessage() {} func (x *RegionResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[133] + mi := &file_proto_user_v1_user_proto_msgTypes[142] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9829,7 +10592,7 @@ func (x *RegionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RegionResponse.ProtoReflect.Descriptor instead. func (*RegionResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{133} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{142} } func (x *RegionResponse) GetRegion() *Region { @@ -9858,7 +10621,7 @@ type UserIdentity struct { func (x *UserIdentity) Reset() { *x = UserIdentity{} - mi := &file_proto_user_v1_user_proto_msgTypes[134] + mi := &file_proto_user_v1_user_proto_msgTypes[143] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9870,7 +10633,7 @@ func (x *UserIdentity) String() string { func (*UserIdentity) ProtoMessage() {} func (x *UserIdentity) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[134] + mi := &file_proto_user_v1_user_proto_msgTypes[143] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9883,7 +10646,7 @@ func (x *UserIdentity) ProtoReflect() protoreflect.Message { // Deprecated: Use UserIdentity.ProtoReflect.Descriptor instead. func (*UserIdentity) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{134} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{143} } func (x *UserIdentity) GetUserId() int64 { @@ -9961,7 +10724,7 @@ type GetUserIdentityRequest struct { func (x *GetUserIdentityRequest) Reset() { *x = GetUserIdentityRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[135] + mi := &file_proto_user_v1_user_proto_msgTypes[144] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9973,7 +10736,7 @@ func (x *GetUserIdentityRequest) String() string { func (*GetUserIdentityRequest) ProtoMessage() {} func (x *GetUserIdentityRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[135] + mi := &file_proto_user_v1_user_proto_msgTypes[144] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9986,7 +10749,7 @@ func (x *GetUserIdentityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserIdentityRequest.ProtoReflect.Descriptor instead. func (*GetUserIdentityRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{135} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{144} } func (x *GetUserIdentityRequest) GetMeta() *RequestMeta { @@ -10014,7 +10777,7 @@ type GetUserIdentityResponse struct { func (x *GetUserIdentityResponse) Reset() { *x = GetUserIdentityResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[136] + mi := &file_proto_user_v1_user_proto_msgTypes[145] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10026,7 +10789,7 @@ func (x *GetUserIdentityResponse) String() string { func (*GetUserIdentityResponse) ProtoMessage() {} func (x *GetUserIdentityResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[136] + mi := &file_proto_user_v1_user_proto_msgTypes[145] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10039,7 +10802,7 @@ func (x *GetUserIdentityResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserIdentityResponse.ProtoReflect.Descriptor instead. func (*GetUserIdentityResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{136} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{145} } func (x *GetUserIdentityResponse) GetIdentity() *UserIdentity { @@ -10061,7 +10824,7 @@ type ResolveDisplayUserIDRequest struct { func (x *ResolveDisplayUserIDRequest) Reset() { *x = ResolveDisplayUserIDRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[137] + mi := &file_proto_user_v1_user_proto_msgTypes[146] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10073,7 +10836,7 @@ func (x *ResolveDisplayUserIDRequest) String() string { func (*ResolveDisplayUserIDRequest) ProtoMessage() {} func (x *ResolveDisplayUserIDRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[137] + mi := &file_proto_user_v1_user_proto_msgTypes[146] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10086,7 +10849,7 @@ func (x *ResolveDisplayUserIDRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveDisplayUserIDRequest.ProtoReflect.Descriptor instead. func (*ResolveDisplayUserIDRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{137} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{146} } func (x *ResolveDisplayUserIDRequest) GetMeta() *RequestMeta { @@ -10114,7 +10877,7 @@ type ResolveDisplayUserIDResponse struct { func (x *ResolveDisplayUserIDResponse) Reset() { *x = ResolveDisplayUserIDResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[138] + mi := &file_proto_user_v1_user_proto_msgTypes[147] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10126,7 +10889,7 @@ func (x *ResolveDisplayUserIDResponse) String() string { func (*ResolveDisplayUserIDResponse) ProtoMessage() {} func (x *ResolveDisplayUserIDResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[138] + mi := &file_proto_user_v1_user_proto_msgTypes[147] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10139,7 +10902,7 @@ func (x *ResolveDisplayUserIDResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveDisplayUserIDResponse.ProtoReflect.Descriptor instead. func (*ResolveDisplayUserIDResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{138} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{147} } func (x *ResolveDisplayUserIDResponse) GetIdentity() *UserIdentity { @@ -10164,7 +10927,7 @@ type ChangeDisplayUserIDRequest struct { func (x *ChangeDisplayUserIDRequest) Reset() { *x = ChangeDisplayUserIDRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[139] + mi := &file_proto_user_v1_user_proto_msgTypes[148] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10176,7 +10939,7 @@ func (x *ChangeDisplayUserIDRequest) String() string { func (*ChangeDisplayUserIDRequest) ProtoMessage() {} func (x *ChangeDisplayUserIDRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[139] + mi := &file_proto_user_v1_user_proto_msgTypes[148] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10189,7 +10952,7 @@ func (x *ChangeDisplayUserIDRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeDisplayUserIDRequest.ProtoReflect.Descriptor instead. func (*ChangeDisplayUserIDRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{139} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{148} } func (x *ChangeDisplayUserIDRequest) GetMeta() *RequestMeta { @@ -10238,7 +11001,7 @@ type ChangeDisplayUserIDResponse struct { func (x *ChangeDisplayUserIDResponse) Reset() { *x = ChangeDisplayUserIDResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[140] + mi := &file_proto_user_v1_user_proto_msgTypes[149] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10250,7 +11013,7 @@ func (x *ChangeDisplayUserIDResponse) String() string { func (*ChangeDisplayUserIDResponse) ProtoMessage() {} func (x *ChangeDisplayUserIDResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[140] + mi := &file_proto_user_v1_user_proto_msgTypes[149] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10263,7 +11026,7 @@ func (x *ChangeDisplayUserIDResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeDisplayUserIDResponse.ProtoReflect.Descriptor instead. func (*ChangeDisplayUserIDResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{140} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{149} } func (x *ChangeDisplayUserIDResponse) GetIdentity() *UserIdentity { @@ -10288,7 +11051,7 @@ type ApplyPrettyDisplayUserIDRequest struct { func (x *ApplyPrettyDisplayUserIDRequest) Reset() { *x = ApplyPrettyDisplayUserIDRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[141] + mi := &file_proto_user_v1_user_proto_msgTypes[150] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10300,7 +11063,7 @@ func (x *ApplyPrettyDisplayUserIDRequest) String() string { func (*ApplyPrettyDisplayUserIDRequest) ProtoMessage() {} func (x *ApplyPrettyDisplayUserIDRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[141] + mi := &file_proto_user_v1_user_proto_msgTypes[150] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10313,7 +11076,7 @@ func (x *ApplyPrettyDisplayUserIDRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyPrettyDisplayUserIDRequest.ProtoReflect.Descriptor instead. func (*ApplyPrettyDisplayUserIDRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{141} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{150} } func (x *ApplyPrettyDisplayUserIDRequest) GetMeta() *RequestMeta { @@ -10363,7 +11126,7 @@ type ApplyPrettyDisplayUserIDResponse struct { func (x *ApplyPrettyDisplayUserIDResponse) Reset() { *x = ApplyPrettyDisplayUserIDResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[142] + mi := &file_proto_user_v1_user_proto_msgTypes[151] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10375,7 +11138,7 @@ func (x *ApplyPrettyDisplayUserIDResponse) String() string { func (*ApplyPrettyDisplayUserIDResponse) ProtoMessage() {} func (x *ApplyPrettyDisplayUserIDResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[142] + mi := &file_proto_user_v1_user_proto_msgTypes[151] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10388,7 +11151,7 @@ func (x *ApplyPrettyDisplayUserIDResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyPrettyDisplayUserIDResponse.ProtoReflect.Descriptor instead. func (*ApplyPrettyDisplayUserIDResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{142} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{151} } func (x *ApplyPrettyDisplayUserIDResponse) GetIdentity() *UserIdentity { @@ -10418,7 +11181,7 @@ type ExpirePrettyDisplayUserIDRequest struct { func (x *ExpirePrettyDisplayUserIDRequest) Reset() { *x = ExpirePrettyDisplayUserIDRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[143] + mi := &file_proto_user_v1_user_proto_msgTypes[152] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10430,7 +11193,7 @@ func (x *ExpirePrettyDisplayUserIDRequest) String() string { func (*ExpirePrettyDisplayUserIDRequest) ProtoMessage() {} func (x *ExpirePrettyDisplayUserIDRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[143] + mi := &file_proto_user_v1_user_proto_msgTypes[152] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10443,7 +11206,7 @@ func (x *ExpirePrettyDisplayUserIDRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExpirePrettyDisplayUserIDRequest.ProtoReflect.Descriptor instead. func (*ExpirePrettyDisplayUserIDRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{143} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{152} } func (x *ExpirePrettyDisplayUserIDRequest) GetMeta() *RequestMeta { @@ -10478,7 +11241,7 @@ type ExpirePrettyDisplayUserIDResponse struct { func (x *ExpirePrettyDisplayUserIDResponse) Reset() { *x = ExpirePrettyDisplayUserIDResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[144] + mi := &file_proto_user_v1_user_proto_msgTypes[153] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10490,7 +11253,7 @@ func (x *ExpirePrettyDisplayUserIDResponse) String() string { func (*ExpirePrettyDisplayUserIDResponse) ProtoMessage() {} func (x *ExpirePrettyDisplayUserIDResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[144] + mi := &file_proto_user_v1_user_proto_msgTypes[153] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10503,7 +11266,7 @@ func (x *ExpirePrettyDisplayUserIDResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ExpirePrettyDisplayUserIDResponse.ProtoReflect.Descriptor instead. func (*ExpirePrettyDisplayUserIDResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{144} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{153} } func (x *ExpirePrettyDisplayUserIDResponse) GetIdentity() *UserIdentity { @@ -10537,7 +11300,7 @@ type PrettyDisplayIDPool struct { func (x *PrettyDisplayIDPool) Reset() { *x = PrettyDisplayIDPool{} - mi := &file_proto_user_v1_user_proto_msgTypes[145] + mi := &file_proto_user_v1_user_proto_msgTypes[154] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10549,7 +11312,7 @@ func (x *PrettyDisplayIDPool) String() string { func (*PrettyDisplayIDPool) ProtoMessage() {} func (x *PrettyDisplayIDPool) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[145] + mi := &file_proto_user_v1_user_proto_msgTypes[154] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10562,7 +11325,7 @@ func (x *PrettyDisplayIDPool) ProtoReflect() protoreflect.Message { // Deprecated: Use PrettyDisplayIDPool.ProtoReflect.Descriptor instead. func (*PrettyDisplayIDPool) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{145} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{154} } func (x *PrettyDisplayIDPool) GetAppCode() string { @@ -10689,7 +11452,7 @@ type PrettyDisplayID struct { func (x *PrettyDisplayID) Reset() { *x = PrettyDisplayID{} - mi := &file_proto_user_v1_user_proto_msgTypes[146] + mi := &file_proto_user_v1_user_proto_msgTypes[155] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10701,7 +11464,7 @@ func (x *PrettyDisplayID) String() string { func (*PrettyDisplayID) ProtoMessage() {} func (x *PrettyDisplayID) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[146] + mi := &file_proto_user_v1_user_proto_msgTypes[155] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10714,7 +11477,7 @@ func (x *PrettyDisplayID) ProtoReflect() protoreflect.Message { // Deprecated: Use PrettyDisplayID.ProtoReflect.Descriptor instead. func (*PrettyDisplayID) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{146} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{155} } func (x *PrettyDisplayID) GetAppCode() string { @@ -10851,7 +11614,7 @@ type PrettyDisplayIDGenerationBatch struct { func (x *PrettyDisplayIDGenerationBatch) Reset() { *x = PrettyDisplayIDGenerationBatch{} - mi := &file_proto_user_v1_user_proto_msgTypes[147] + mi := &file_proto_user_v1_user_proto_msgTypes[156] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10863,7 +11626,7 @@ func (x *PrettyDisplayIDGenerationBatch) String() string { func (*PrettyDisplayIDGenerationBatch) ProtoMessage() {} func (x *PrettyDisplayIDGenerationBatch) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[147] + mi := &file_proto_user_v1_user_proto_msgTypes[156] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10876,7 +11639,7 @@ func (x *PrettyDisplayIDGenerationBatch) ProtoReflect() protoreflect.Message { // Deprecated: Use PrettyDisplayIDGenerationBatch.ProtoReflect.Descriptor instead. func (*PrettyDisplayIDGenerationBatch) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{147} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{156} } func (x *PrettyDisplayIDGenerationBatch) GetAppCode() string { @@ -10983,7 +11746,7 @@ type ListAvailablePrettyDisplayIDsRequest struct { func (x *ListAvailablePrettyDisplayIDsRequest) Reset() { *x = ListAvailablePrettyDisplayIDsRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[148] + mi := &file_proto_user_v1_user_proto_msgTypes[157] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10995,7 +11758,7 @@ func (x *ListAvailablePrettyDisplayIDsRequest) String() string { func (*ListAvailablePrettyDisplayIDsRequest) ProtoMessage() {} func (x *ListAvailablePrettyDisplayIDsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[148] + mi := &file_proto_user_v1_user_proto_msgTypes[157] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11008,7 +11771,7 @@ func (x *ListAvailablePrettyDisplayIDsRequest) ProtoReflect() protoreflect.Messa // Deprecated: Use ListAvailablePrettyDisplayIDsRequest.ProtoReflect.Descriptor instead. func (*ListAvailablePrettyDisplayIDsRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{148} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{157} } func (x *ListAvailablePrettyDisplayIDsRequest) GetMeta() *RequestMeta { @@ -11050,7 +11813,7 @@ type ListAvailablePrettyDisplayIDsResponse struct { func (x *ListAvailablePrettyDisplayIDsResponse) Reset() { *x = ListAvailablePrettyDisplayIDsResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[149] + mi := &file_proto_user_v1_user_proto_msgTypes[158] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11062,7 +11825,7 @@ func (x *ListAvailablePrettyDisplayIDsResponse) String() string { func (*ListAvailablePrettyDisplayIDsResponse) ProtoMessage() {} func (x *ListAvailablePrettyDisplayIDsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[149] + mi := &file_proto_user_v1_user_proto_msgTypes[158] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11075,7 +11838,7 @@ func (x *ListAvailablePrettyDisplayIDsResponse) ProtoReflect() protoreflect.Mess // Deprecated: Use ListAvailablePrettyDisplayIDsResponse.ProtoReflect.Descriptor instead. func (*ListAvailablePrettyDisplayIDsResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{149} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{158} } func (x *ListAvailablePrettyDisplayIDsResponse) GetItems() []*PrettyDisplayID { @@ -11104,7 +11867,7 @@ type ApplyPrettyDisplayIDFromPoolRequest struct { func (x *ApplyPrettyDisplayIDFromPoolRequest) Reset() { *x = ApplyPrettyDisplayIDFromPoolRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[150] + mi := &file_proto_user_v1_user_proto_msgTypes[159] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11116,7 +11879,7 @@ func (x *ApplyPrettyDisplayIDFromPoolRequest) String() string { func (*ApplyPrettyDisplayIDFromPoolRequest) ProtoMessage() {} func (x *ApplyPrettyDisplayIDFromPoolRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[150] + mi := &file_proto_user_v1_user_proto_msgTypes[159] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11129,7 +11892,7 @@ func (x *ApplyPrettyDisplayIDFromPoolRequest) ProtoReflect() protoreflect.Messag // Deprecated: Use ApplyPrettyDisplayIDFromPoolRequest.ProtoReflect.Descriptor instead. func (*ApplyPrettyDisplayIDFromPoolRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{150} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{159} } func (x *ApplyPrettyDisplayIDFromPoolRequest) GetMeta() *RequestMeta { @@ -11165,7 +11928,7 @@ type ApplyPrettyDisplayIDFromPoolResponse struct { func (x *ApplyPrettyDisplayIDFromPoolResponse) Reset() { *x = ApplyPrettyDisplayIDFromPoolResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[151] + mi := &file_proto_user_v1_user_proto_msgTypes[160] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11177,7 +11940,7 @@ func (x *ApplyPrettyDisplayIDFromPoolResponse) String() string { func (*ApplyPrettyDisplayIDFromPoolResponse) ProtoMessage() {} func (x *ApplyPrettyDisplayIDFromPoolResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[151] + mi := &file_proto_user_v1_user_proto_msgTypes[160] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11190,7 +11953,7 @@ func (x *ApplyPrettyDisplayIDFromPoolResponse) ProtoReflect() protoreflect.Messa // Deprecated: Use ApplyPrettyDisplayIDFromPoolResponse.ProtoReflect.Descriptor instead. func (*ApplyPrettyDisplayIDFromPoolResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{151} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{160} } func (x *ApplyPrettyDisplayIDFromPoolResponse) GetIdentity() *UserIdentity { @@ -11228,7 +11991,7 @@ type ListPrettyDisplayIDPoolsRequest struct { func (x *ListPrettyDisplayIDPoolsRequest) Reset() { *x = ListPrettyDisplayIDPoolsRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[152] + mi := &file_proto_user_v1_user_proto_msgTypes[161] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11240,7 +12003,7 @@ func (x *ListPrettyDisplayIDPoolsRequest) String() string { func (*ListPrettyDisplayIDPoolsRequest) ProtoMessage() {} func (x *ListPrettyDisplayIDPoolsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[152] + mi := &file_proto_user_v1_user_proto_msgTypes[161] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11253,7 +12016,7 @@ func (x *ListPrettyDisplayIDPoolsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListPrettyDisplayIDPoolsRequest.ProtoReflect.Descriptor instead. func (*ListPrettyDisplayIDPoolsRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{152} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{161} } func (x *ListPrettyDisplayIDPoolsRequest) GetMeta() *RequestMeta { @@ -11302,7 +12065,7 @@ type ListPrettyDisplayIDPoolsResponse struct { func (x *ListPrettyDisplayIDPoolsResponse) Reset() { *x = ListPrettyDisplayIDPoolsResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[153] + mi := &file_proto_user_v1_user_proto_msgTypes[162] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11314,7 +12077,7 @@ func (x *ListPrettyDisplayIDPoolsResponse) String() string { func (*ListPrettyDisplayIDPoolsResponse) ProtoMessage() {} func (x *ListPrettyDisplayIDPoolsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[153] + mi := &file_proto_user_v1_user_proto_msgTypes[162] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11327,7 +12090,7 @@ func (x *ListPrettyDisplayIDPoolsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListPrettyDisplayIDPoolsResponse.ProtoReflect.Descriptor instead. func (*ListPrettyDisplayIDPoolsResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{153} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{162} } func (x *ListPrettyDisplayIDPoolsResponse) GetItems() []*PrettyDisplayIDPool { @@ -11363,7 +12126,7 @@ type CreatePrettyDisplayIDPoolRequest struct { func (x *CreatePrettyDisplayIDPoolRequest) Reset() { *x = CreatePrettyDisplayIDPoolRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[154] + mi := &file_proto_user_v1_user_proto_msgTypes[163] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11375,7 +12138,7 @@ func (x *CreatePrettyDisplayIDPoolRequest) String() string { func (*CreatePrettyDisplayIDPoolRequest) ProtoMessage() {} func (x *CreatePrettyDisplayIDPoolRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[154] + mi := &file_proto_user_v1_user_proto_msgTypes[163] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11388,7 +12151,7 @@ func (x *CreatePrettyDisplayIDPoolRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreatePrettyDisplayIDPoolRequest.ProtoReflect.Descriptor instead. func (*CreatePrettyDisplayIDPoolRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{154} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{163} } func (x *CreatePrettyDisplayIDPoolRequest) GetMeta() *RequestMeta { @@ -11481,7 +12244,7 @@ type UpdatePrettyDisplayIDPoolRequest struct { func (x *UpdatePrettyDisplayIDPoolRequest) Reset() { *x = UpdatePrettyDisplayIDPoolRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[155] + mi := &file_proto_user_v1_user_proto_msgTypes[164] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11493,7 +12256,7 @@ func (x *UpdatePrettyDisplayIDPoolRequest) String() string { func (*UpdatePrettyDisplayIDPoolRequest) ProtoMessage() {} func (x *UpdatePrettyDisplayIDPoolRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[155] + mi := &file_proto_user_v1_user_proto_msgTypes[164] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11506,7 +12269,7 @@ func (x *UpdatePrettyDisplayIDPoolRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdatePrettyDisplayIDPoolRequest.ProtoReflect.Descriptor instead. func (*UpdatePrettyDisplayIDPoolRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{155} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{164} } func (x *UpdatePrettyDisplayIDPoolRequest) GetMeta() *RequestMeta { @@ -11596,7 +12359,7 @@ type PrettyDisplayIDPoolResponse struct { func (x *PrettyDisplayIDPoolResponse) Reset() { *x = PrettyDisplayIDPoolResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[156] + mi := &file_proto_user_v1_user_proto_msgTypes[165] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11608,7 +12371,7 @@ func (x *PrettyDisplayIDPoolResponse) String() string { func (*PrettyDisplayIDPoolResponse) ProtoMessage() {} func (x *PrettyDisplayIDPoolResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[156] + mi := &file_proto_user_v1_user_proto_msgTypes[165] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11621,7 +12384,7 @@ func (x *PrettyDisplayIDPoolResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PrettyDisplayIDPoolResponse.ProtoReflect.Descriptor instead. func (*PrettyDisplayIDPoolResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{156} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{165} } func (x *PrettyDisplayIDPoolResponse) GetPool() *PrettyDisplayIDPool { @@ -11646,7 +12409,7 @@ type GeneratePrettyDisplayIDsRequest struct { func (x *GeneratePrettyDisplayIDsRequest) Reset() { *x = GeneratePrettyDisplayIDsRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[157] + mi := &file_proto_user_v1_user_proto_msgTypes[166] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11658,7 +12421,7 @@ func (x *GeneratePrettyDisplayIDsRequest) String() string { func (*GeneratePrettyDisplayIDsRequest) ProtoMessage() {} func (x *GeneratePrettyDisplayIDsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[157] + mi := &file_proto_user_v1_user_proto_msgTypes[166] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11671,7 +12434,7 @@ func (x *GeneratePrettyDisplayIDsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GeneratePrettyDisplayIDsRequest.ProtoReflect.Descriptor instead. func (*GeneratePrettyDisplayIDsRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{157} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{166} } func (x *GeneratePrettyDisplayIDsRequest) GetMeta() *RequestMeta { @@ -11726,7 +12489,7 @@ type GeneratePrettyDisplayIDsResponse struct { func (x *GeneratePrettyDisplayIDsResponse) Reset() { *x = GeneratePrettyDisplayIDsResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[158] + mi := &file_proto_user_v1_user_proto_msgTypes[167] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11738,7 +12501,7 @@ func (x *GeneratePrettyDisplayIDsResponse) String() string { func (*GeneratePrettyDisplayIDsResponse) ProtoMessage() {} func (x *GeneratePrettyDisplayIDsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[158] + mi := &file_proto_user_v1_user_proto_msgTypes[167] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11751,7 +12514,7 @@ func (x *GeneratePrettyDisplayIDsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GeneratePrettyDisplayIDsResponse.ProtoReflect.Descriptor instead. func (*GeneratePrettyDisplayIDsResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{158} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{167} } func (x *GeneratePrettyDisplayIDsResponse) GetBatch() *PrettyDisplayIDGenerationBatch { @@ -11778,7 +12541,7 @@ type ListPrettyDisplayIDsRequest struct { func (x *ListPrettyDisplayIDsRequest) Reset() { *x = ListPrettyDisplayIDsRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[159] + mi := &file_proto_user_v1_user_proto_msgTypes[168] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11790,7 +12553,7 @@ func (x *ListPrettyDisplayIDsRequest) String() string { func (*ListPrettyDisplayIDsRequest) ProtoMessage() {} func (x *ListPrettyDisplayIDsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[159] + mi := &file_proto_user_v1_user_proto_msgTypes[168] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11803,7 +12566,7 @@ func (x *ListPrettyDisplayIDsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListPrettyDisplayIDsRequest.ProtoReflect.Descriptor instead. func (*ListPrettyDisplayIDsRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{159} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{168} } func (x *ListPrettyDisplayIDsRequest) GetMeta() *RequestMeta { @@ -11873,7 +12636,7 @@ type ListPrettyDisplayIDsResponse struct { func (x *ListPrettyDisplayIDsResponse) Reset() { *x = ListPrettyDisplayIDsResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[160] + mi := &file_proto_user_v1_user_proto_msgTypes[169] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11885,7 +12648,7 @@ func (x *ListPrettyDisplayIDsResponse) String() string { func (*ListPrettyDisplayIDsResponse) ProtoMessage() {} func (x *ListPrettyDisplayIDsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[160] + mi := &file_proto_user_v1_user_proto_msgTypes[169] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11898,7 +12661,7 @@ func (x *ListPrettyDisplayIDsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListPrettyDisplayIDsResponse.ProtoReflect.Descriptor instead. func (*ListPrettyDisplayIDsResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{160} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{169} } func (x *ListPrettyDisplayIDsResponse) GetItems() []*PrettyDisplayID { @@ -11929,7 +12692,7 @@ type SetPrettyDisplayIDStatusRequest struct { func (x *SetPrettyDisplayIDStatusRequest) Reset() { *x = SetPrettyDisplayIDStatusRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[161] + mi := &file_proto_user_v1_user_proto_msgTypes[170] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11941,7 +12704,7 @@ func (x *SetPrettyDisplayIDStatusRequest) String() string { func (*SetPrettyDisplayIDStatusRequest) ProtoMessage() {} func (x *SetPrettyDisplayIDStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[161] + mi := &file_proto_user_v1_user_proto_msgTypes[170] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11954,7 +12717,7 @@ func (x *SetPrettyDisplayIDStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetPrettyDisplayIDStatusRequest.ProtoReflect.Descriptor instead. func (*SetPrettyDisplayIDStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{161} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{170} } func (x *SetPrettyDisplayIDStatusRequest) GetMeta() *RequestMeta { @@ -12005,7 +12768,7 @@ type RecyclePrettyDisplayIDRequest struct { func (x *RecyclePrettyDisplayIDRequest) Reset() { *x = RecyclePrettyDisplayIDRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[162] + mi := &file_proto_user_v1_user_proto_msgTypes[171] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12017,7 +12780,7 @@ func (x *RecyclePrettyDisplayIDRequest) String() string { func (*RecyclePrettyDisplayIDRequest) ProtoMessage() {} func (x *RecyclePrettyDisplayIDRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[162] + mi := &file_proto_user_v1_user_proto_msgTypes[171] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12030,7 +12793,7 @@ func (x *RecyclePrettyDisplayIDRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RecyclePrettyDisplayIDRequest.ProtoReflect.Descriptor instead. func (*RecyclePrettyDisplayIDRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{162} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{171} } func (x *RecyclePrettyDisplayIDRequest) GetMeta() *RequestMeta { @@ -12071,7 +12834,7 @@ type PrettyDisplayIDResponse struct { func (x *PrettyDisplayIDResponse) Reset() { *x = PrettyDisplayIDResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[163] + mi := &file_proto_user_v1_user_proto_msgTypes[172] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12083,7 +12846,7 @@ func (x *PrettyDisplayIDResponse) String() string { func (*PrettyDisplayIDResponse) ProtoMessage() {} func (x *PrettyDisplayIDResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[163] + mi := &file_proto_user_v1_user_proto_msgTypes[172] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12096,7 +12859,7 @@ func (x *PrettyDisplayIDResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PrettyDisplayIDResponse.ProtoReflect.Descriptor instead. func (*PrettyDisplayIDResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{163} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{172} } func (x *PrettyDisplayIDResponse) GetItem() *PrettyDisplayID { @@ -12121,7 +12884,7 @@ type AdminGrantPrettyDisplayIDRequest struct { func (x *AdminGrantPrettyDisplayIDRequest) Reset() { *x = AdminGrantPrettyDisplayIDRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[164] + mi := &file_proto_user_v1_user_proto_msgTypes[173] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12133,7 +12896,7 @@ func (x *AdminGrantPrettyDisplayIDRequest) String() string { func (*AdminGrantPrettyDisplayIDRequest) ProtoMessage() {} func (x *AdminGrantPrettyDisplayIDRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[164] + mi := &file_proto_user_v1_user_proto_msgTypes[173] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12146,7 +12909,7 @@ func (x *AdminGrantPrettyDisplayIDRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminGrantPrettyDisplayIDRequest.ProtoReflect.Descriptor instead. func (*AdminGrantPrettyDisplayIDRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{164} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{173} } func (x *AdminGrantPrettyDisplayIDRequest) GetMeta() *RequestMeta { @@ -12203,7 +12966,7 @@ type AdminGrantPrettyDisplayIDResponse struct { func (x *AdminGrantPrettyDisplayIDResponse) Reset() { *x = AdminGrantPrettyDisplayIDResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[165] + mi := &file_proto_user_v1_user_proto_msgTypes[174] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12215,7 +12978,7 @@ func (x *AdminGrantPrettyDisplayIDResponse) String() string { func (*AdminGrantPrettyDisplayIDResponse) ProtoMessage() {} func (x *AdminGrantPrettyDisplayIDResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[165] + mi := &file_proto_user_v1_user_proto_msgTypes[174] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12228,7 +12991,7 @@ func (x *AdminGrantPrettyDisplayIDResponse) ProtoReflect() protoreflect.Message // Deprecated: Use AdminGrantPrettyDisplayIDResponse.ProtoReflect.Descriptor instead. func (*AdminGrantPrettyDisplayIDResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{165} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{174} } func (x *AdminGrantPrettyDisplayIDResponse) GetIdentity() *UserIdentity { @@ -12487,7 +13250,7 @@ var file_proto_user_v1_user_proto_rawDesc = []byte{ 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, 0xb3, 0x02, 0x0a, 0x10, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, + 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, @@ -12506,179 +13269,200 @@ var file_proto_user_v1_user_proto_rawDesc = []byte{ 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, 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, + 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, 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, + 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, 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, + 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, @@ -12686,667 +13470,724 @@ var file_proto_user_v1_user_proto_rawDesc = []byte{ 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, + 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, 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, + 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, 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, + 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, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, + 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, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x66, + 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, 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, + 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, 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, + 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, 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, 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, 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, + 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, 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, + 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, 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, @@ -13541,1302 +14382,1407 @@ var file_proto_user_v1_user_proto_rawDesc = []byte{ 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, 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, + 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, 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, + 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, + 0x85, 0x01, 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, 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, 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, + 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, - 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, + 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, - 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, + 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, 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, + 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, 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, 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, 0xf4, 0x11, 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, 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, + 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, 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, 0x14, 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, 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, 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, + 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, - 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, + 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, 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, + 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, 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, 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, 0xf0, - 0x03, 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, 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, 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, 0x67, 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, 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, 0xea, 0x06, 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, + 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, - 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, 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, + 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, - 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, + 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, 0x67, 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, 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, 0xea, 0x06, 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, 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, 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, + 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, - 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, + 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, - 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, + 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, } var ( @@ -14852,7 +15798,7 @@ func file_proto_user_v1_user_proto_rawDescGZIP() []byte { } var file_proto_user_v1_user_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_proto_user_v1_user_proto_msgTypes = make([]protoimpl.MessageInfo, 168) +var file_proto_user_v1_user_proto_msgTypes = make([]protoimpl.MessageInfo, 178) var file_proto_user_v1_user_proto_goTypes = []any{ (UserStatus)(0), // 0: hyapp.user.v1.UserStatus (*RequestMeta)(nil), // 1: hyapp.user.v1.RequestMeta @@ -14937,92 +15883,102 @@ var file_proto_user_v1_user_proto_goTypes = []any{ (*SubmitReportResponse)(nil), // 80: hyapp.user.v1.SubmitReportResponse (*BatchGetUsersRequest)(nil), // 81: hyapp.user.v1.BatchGetUsersRequest (*BatchGetUsersResponse)(nil), // 82: hyapp.user.v1.BatchGetUsersResponse - (*RoomBasicUser)(nil), // 83: hyapp.user.v1.RoomBasicUser - (*BatchGetRoomBasicUsersRequest)(nil), // 84: hyapp.user.v1.BatchGetRoomBasicUsersRequest - (*BatchGetRoomBasicUsersResponse)(nil), // 85: hyapp.user.v1.BatchGetRoomBasicUsersResponse - (*ListUserIDsRequest)(nil), // 86: hyapp.user.v1.ListUserIDsRequest - (*ListUserIDsResponse)(nil), // 87: hyapp.user.v1.ListUserIDsResponse - (*UpdateUserProfileRequest)(nil), // 88: hyapp.user.v1.UpdateUserProfileRequest - (*UpdateUserProfileResponse)(nil), // 89: hyapp.user.v1.UpdateUserProfileResponse - (*UpdateUserProfileBackgroundRequest)(nil), // 90: hyapp.user.v1.UpdateUserProfileBackgroundRequest - (*UpdateUserProfileBackgroundResponse)(nil), // 91: hyapp.user.v1.UpdateUserProfileBackgroundResponse - (*UpdateUserContactInfoRequest)(nil), // 92: hyapp.user.v1.UpdateUserContactInfoRequest - (*UpdateUserContactInfoResponse)(nil), // 93: hyapp.user.v1.UpdateUserContactInfoResponse - (*UpdateUserWithdrawAddressRequest)(nil), // 94: hyapp.user.v1.UpdateUserWithdrawAddressRequest - (*UpdateUserWithdrawAddressResponse)(nil), // 95: hyapp.user.v1.UpdateUserWithdrawAddressResponse - (*ChangeUserCountryRequest)(nil), // 96: hyapp.user.v1.ChangeUserCountryRequest - (*AdminChangeUserCountryRequest)(nil), // 97: hyapp.user.v1.AdminChangeUserCountryRequest - (*ChangeUserCountryResponse)(nil), // 98: hyapp.user.v1.ChangeUserCountryResponse - (*SetUserStatusRequest)(nil), // 99: hyapp.user.v1.SetUserStatusRequest - (*SetUserStatusResponse)(nil), // 100: hyapp.user.v1.SetUserStatusResponse - (*ManagerUserBlock)(nil), // 101: hyapp.user.v1.ManagerUserBlock - (*CreateManagerUserBlockRequest)(nil), // 102: hyapp.user.v1.CreateManagerUserBlockRequest - (*CreateManagerUserBlockResponse)(nil), // 103: hyapp.user.v1.CreateManagerUserBlockResponse - (*ListManagerUserBlocksRequest)(nil), // 104: hyapp.user.v1.ListManagerUserBlocksRequest - (*ListManagerUserBlocksResponse)(nil), // 105: hyapp.user.v1.ListManagerUserBlocksResponse - (*UnblockManagerUserRequest)(nil), // 106: hyapp.user.v1.UnblockManagerUserRequest - (*UnblockManagerUserResponse)(nil), // 107: hyapp.user.v1.UnblockManagerUserResponse - (*CompleteOnboardingRequest)(nil), // 108: hyapp.user.v1.CompleteOnboardingRequest - (*CompleteOnboardingResponse)(nil), // 109: hyapp.user.v1.CompleteOnboardingResponse - (*SearchInviteReferrerRequest)(nil), // 110: hyapp.user.v1.SearchInviteReferrerRequest - (*SearchInviteReferrerResponse)(nil), // 111: hyapp.user.v1.SearchInviteReferrerResponse - (*BindInviteReferrerRequest)(nil), // 112: hyapp.user.v1.BindInviteReferrerRequest - (*BindInviteReferrerResponse)(nil), // 113: hyapp.user.v1.BindInviteReferrerResponse - (*BindPushTokenRequest)(nil), // 114: hyapp.user.v1.BindPushTokenRequest - (*BindPushTokenResponse)(nil), // 115: hyapp.user.v1.BindPushTokenResponse - (*DeletePushTokenRequest)(nil), // 116: hyapp.user.v1.DeletePushTokenRequest - (*DeletePushTokenResponse)(nil), // 117: hyapp.user.v1.DeletePushTokenResponse - (*Country)(nil), // 118: hyapp.user.v1.Country - (*Region)(nil), // 119: hyapp.user.v1.Region - (*ListCountriesRequest)(nil), // 120: hyapp.user.v1.ListCountriesRequest - (*ListCountriesResponse)(nil), // 121: hyapp.user.v1.ListCountriesResponse - (*UpdateCountryRequest)(nil), // 122: hyapp.user.v1.UpdateCountryRequest - (*CountryResponse)(nil), // 123: hyapp.user.v1.CountryResponse - (*ListRegistrationCountriesRequest)(nil), // 124: hyapp.user.v1.ListRegistrationCountriesRequest - (*ListRegistrationCountriesResponse)(nil), // 125: hyapp.user.v1.ListRegistrationCountriesResponse - (*LoginRiskBlockedCountry)(nil), // 126: hyapp.user.v1.LoginRiskBlockedCountry - (*ListLoginRiskBlockedCountriesRequest)(nil), // 127: hyapp.user.v1.ListLoginRiskBlockedCountriesRequest - (*ListLoginRiskBlockedCountriesResponse)(nil), // 128: hyapp.user.v1.ListLoginRiskBlockedCountriesResponse - (*ListRegionsRequest)(nil), // 129: hyapp.user.v1.ListRegionsRequest - (*ListRegionsResponse)(nil), // 130: hyapp.user.v1.ListRegionsResponse - (*GetRegionRequest)(nil), // 131: hyapp.user.v1.GetRegionRequest - (*UpdateRegionRequest)(nil), // 132: hyapp.user.v1.UpdateRegionRequest - (*ReplaceRegionCountriesRequest)(nil), // 133: hyapp.user.v1.ReplaceRegionCountriesRequest - (*RegionResponse)(nil), // 134: hyapp.user.v1.RegionResponse - (*UserIdentity)(nil), // 135: hyapp.user.v1.UserIdentity - (*GetUserIdentityRequest)(nil), // 136: hyapp.user.v1.GetUserIdentityRequest - (*GetUserIdentityResponse)(nil), // 137: hyapp.user.v1.GetUserIdentityResponse - (*ResolveDisplayUserIDRequest)(nil), // 138: hyapp.user.v1.ResolveDisplayUserIDRequest - (*ResolveDisplayUserIDResponse)(nil), // 139: hyapp.user.v1.ResolveDisplayUserIDResponse - (*ChangeDisplayUserIDRequest)(nil), // 140: hyapp.user.v1.ChangeDisplayUserIDRequest - (*ChangeDisplayUserIDResponse)(nil), // 141: hyapp.user.v1.ChangeDisplayUserIDResponse - (*ApplyPrettyDisplayUserIDRequest)(nil), // 142: hyapp.user.v1.ApplyPrettyDisplayUserIDRequest - (*ApplyPrettyDisplayUserIDResponse)(nil), // 143: hyapp.user.v1.ApplyPrettyDisplayUserIDResponse - (*ExpirePrettyDisplayUserIDRequest)(nil), // 144: hyapp.user.v1.ExpirePrettyDisplayUserIDRequest - (*ExpirePrettyDisplayUserIDResponse)(nil), // 145: hyapp.user.v1.ExpirePrettyDisplayUserIDResponse - (*PrettyDisplayIDPool)(nil), // 146: hyapp.user.v1.PrettyDisplayIDPool - (*PrettyDisplayID)(nil), // 147: hyapp.user.v1.PrettyDisplayID - (*PrettyDisplayIDGenerationBatch)(nil), // 148: hyapp.user.v1.PrettyDisplayIDGenerationBatch - (*ListAvailablePrettyDisplayIDsRequest)(nil), // 149: hyapp.user.v1.ListAvailablePrettyDisplayIDsRequest - (*ListAvailablePrettyDisplayIDsResponse)(nil), // 150: hyapp.user.v1.ListAvailablePrettyDisplayIDsResponse - (*ApplyPrettyDisplayIDFromPoolRequest)(nil), // 151: hyapp.user.v1.ApplyPrettyDisplayIDFromPoolRequest - (*ApplyPrettyDisplayIDFromPoolResponse)(nil), // 152: hyapp.user.v1.ApplyPrettyDisplayIDFromPoolResponse - (*ListPrettyDisplayIDPoolsRequest)(nil), // 153: hyapp.user.v1.ListPrettyDisplayIDPoolsRequest - (*ListPrettyDisplayIDPoolsResponse)(nil), // 154: hyapp.user.v1.ListPrettyDisplayIDPoolsResponse - (*CreatePrettyDisplayIDPoolRequest)(nil), // 155: hyapp.user.v1.CreatePrettyDisplayIDPoolRequest - (*UpdatePrettyDisplayIDPoolRequest)(nil), // 156: hyapp.user.v1.UpdatePrettyDisplayIDPoolRequest - (*PrettyDisplayIDPoolResponse)(nil), // 157: hyapp.user.v1.PrettyDisplayIDPoolResponse - (*GeneratePrettyDisplayIDsRequest)(nil), // 158: hyapp.user.v1.GeneratePrettyDisplayIDsRequest - (*GeneratePrettyDisplayIDsResponse)(nil), // 159: hyapp.user.v1.GeneratePrettyDisplayIDsResponse - (*ListPrettyDisplayIDsRequest)(nil), // 160: hyapp.user.v1.ListPrettyDisplayIDsRequest - (*ListPrettyDisplayIDsResponse)(nil), // 161: hyapp.user.v1.ListPrettyDisplayIDsResponse - (*SetPrettyDisplayIDStatusRequest)(nil), // 162: hyapp.user.v1.SetPrettyDisplayIDStatusRequest - (*RecyclePrettyDisplayIDRequest)(nil), // 163: hyapp.user.v1.RecyclePrettyDisplayIDRequest - (*PrettyDisplayIDResponse)(nil), // 164: hyapp.user.v1.PrettyDisplayIDResponse - (*AdminGrantPrettyDisplayIDRequest)(nil), // 165: hyapp.user.v1.AdminGrantPrettyDisplayIDRequest - (*AdminGrantPrettyDisplayIDResponse)(nil), // 166: hyapp.user.v1.AdminGrantPrettyDisplayIDResponse - nil, // 167: hyapp.user.v1.BatchGetUsersResponse.UsersEntry - nil, // 168: hyapp.user.v1.BatchGetRoomBasicUsersResponse.UsersEntry + (*ActiveUserBanSummary)(nil), // 83: hyapp.user.v1.ActiveUserBanSummary + (*UserAdminProfile)(nil), // 84: hyapp.user.v1.UserAdminProfile + (*BatchGetUserAdminProfilesRequest)(nil), // 85: hyapp.user.v1.BatchGetUserAdminProfilesRequest + (*BatchGetUserAdminProfilesResponse)(nil), // 86: hyapp.user.v1.BatchGetUserAdminProfilesResponse + (*RoomBasicUser)(nil), // 87: hyapp.user.v1.RoomBasicUser + (*BatchGetRoomBasicUsersRequest)(nil), // 88: hyapp.user.v1.BatchGetRoomBasicUsersRequest + (*BatchGetRoomBasicUsersResponse)(nil), // 89: hyapp.user.v1.BatchGetRoomBasicUsersResponse + (*ListUserIDsRequest)(nil), // 90: hyapp.user.v1.ListUserIDsRequest + (*ListUserIDsResponse)(nil), // 91: hyapp.user.v1.ListUserIDsResponse + (*UpdateUserProfileRequest)(nil), // 92: hyapp.user.v1.UpdateUserProfileRequest + (*UpdateUserProfileResponse)(nil), // 93: hyapp.user.v1.UpdateUserProfileResponse + (*UpdateUserProfileBackgroundRequest)(nil), // 94: hyapp.user.v1.UpdateUserProfileBackgroundRequest + (*UpdateUserProfileBackgroundResponse)(nil), // 95: hyapp.user.v1.UpdateUserProfileBackgroundResponse + (*UpdateUserContactInfoRequest)(nil), // 96: hyapp.user.v1.UpdateUserContactInfoRequest + (*UpdateUserContactInfoResponse)(nil), // 97: hyapp.user.v1.UpdateUserContactInfoResponse + (*UpdateUserWithdrawAddressRequest)(nil), // 98: hyapp.user.v1.UpdateUserWithdrawAddressRequest + (*UpdateUserWithdrawAddressResponse)(nil), // 99: hyapp.user.v1.UpdateUserWithdrawAddressResponse + (*ChangeUserCountryRequest)(nil), // 100: hyapp.user.v1.ChangeUserCountryRequest + (*AdminChangeUserCountryRequest)(nil), // 101: hyapp.user.v1.AdminChangeUserCountryRequest + (*ChangeUserCountryResponse)(nil), // 102: hyapp.user.v1.ChangeUserCountryResponse + (*SetUserStatusRequest)(nil), // 103: hyapp.user.v1.SetUserStatusRequest + (*SetUserStatusResponse)(nil), // 104: hyapp.user.v1.SetUserStatusResponse + (*AdminUserBan)(nil), // 105: hyapp.user.v1.AdminUserBan + (*AdminBanUserRequest)(nil), // 106: hyapp.user.v1.AdminBanUserRequest + (*AdminBanUserResponse)(nil), // 107: hyapp.user.v1.AdminBanUserResponse + (*AdminUnbanUserRequest)(nil), // 108: hyapp.user.v1.AdminUnbanUserRequest + (*AdminUnbanUserResponse)(nil), // 109: hyapp.user.v1.AdminUnbanUserResponse + (*ManagerUserBlock)(nil), // 110: hyapp.user.v1.ManagerUserBlock + (*CreateManagerUserBlockRequest)(nil), // 111: hyapp.user.v1.CreateManagerUserBlockRequest + (*CreateManagerUserBlockResponse)(nil), // 112: hyapp.user.v1.CreateManagerUserBlockResponse + (*ListManagerUserBlocksRequest)(nil), // 113: hyapp.user.v1.ListManagerUserBlocksRequest + (*ListManagerUserBlocksResponse)(nil), // 114: hyapp.user.v1.ListManagerUserBlocksResponse + (*UnblockManagerUserRequest)(nil), // 115: hyapp.user.v1.UnblockManagerUserRequest + (*UnblockManagerUserResponse)(nil), // 116: hyapp.user.v1.UnblockManagerUserResponse + (*CompleteOnboardingRequest)(nil), // 117: hyapp.user.v1.CompleteOnboardingRequest + (*CompleteOnboardingResponse)(nil), // 118: hyapp.user.v1.CompleteOnboardingResponse + (*SearchInviteReferrerRequest)(nil), // 119: hyapp.user.v1.SearchInviteReferrerRequest + (*SearchInviteReferrerResponse)(nil), // 120: hyapp.user.v1.SearchInviteReferrerResponse + (*BindInviteReferrerRequest)(nil), // 121: hyapp.user.v1.BindInviteReferrerRequest + (*BindInviteReferrerResponse)(nil), // 122: hyapp.user.v1.BindInviteReferrerResponse + (*BindPushTokenRequest)(nil), // 123: hyapp.user.v1.BindPushTokenRequest + (*BindPushTokenResponse)(nil), // 124: hyapp.user.v1.BindPushTokenResponse + (*DeletePushTokenRequest)(nil), // 125: hyapp.user.v1.DeletePushTokenRequest + (*DeletePushTokenResponse)(nil), // 126: hyapp.user.v1.DeletePushTokenResponse + (*Country)(nil), // 127: hyapp.user.v1.Country + (*Region)(nil), // 128: hyapp.user.v1.Region + (*ListCountriesRequest)(nil), // 129: hyapp.user.v1.ListCountriesRequest + (*ListCountriesResponse)(nil), // 130: hyapp.user.v1.ListCountriesResponse + (*UpdateCountryRequest)(nil), // 131: hyapp.user.v1.UpdateCountryRequest + (*CountryResponse)(nil), // 132: hyapp.user.v1.CountryResponse + (*ListRegistrationCountriesRequest)(nil), // 133: hyapp.user.v1.ListRegistrationCountriesRequest + (*ListRegistrationCountriesResponse)(nil), // 134: hyapp.user.v1.ListRegistrationCountriesResponse + (*LoginRiskBlockedCountry)(nil), // 135: hyapp.user.v1.LoginRiskBlockedCountry + (*ListLoginRiskBlockedCountriesRequest)(nil), // 136: hyapp.user.v1.ListLoginRiskBlockedCountriesRequest + (*ListLoginRiskBlockedCountriesResponse)(nil), // 137: hyapp.user.v1.ListLoginRiskBlockedCountriesResponse + (*ListRegionsRequest)(nil), // 138: hyapp.user.v1.ListRegionsRequest + (*ListRegionsResponse)(nil), // 139: hyapp.user.v1.ListRegionsResponse + (*GetRegionRequest)(nil), // 140: hyapp.user.v1.GetRegionRequest + (*UpdateRegionRequest)(nil), // 141: hyapp.user.v1.UpdateRegionRequest + (*ReplaceRegionCountriesRequest)(nil), // 142: hyapp.user.v1.ReplaceRegionCountriesRequest + (*RegionResponse)(nil), // 143: hyapp.user.v1.RegionResponse + (*UserIdentity)(nil), // 144: hyapp.user.v1.UserIdentity + (*GetUserIdentityRequest)(nil), // 145: hyapp.user.v1.GetUserIdentityRequest + (*GetUserIdentityResponse)(nil), // 146: hyapp.user.v1.GetUserIdentityResponse + (*ResolveDisplayUserIDRequest)(nil), // 147: hyapp.user.v1.ResolveDisplayUserIDRequest + (*ResolveDisplayUserIDResponse)(nil), // 148: hyapp.user.v1.ResolveDisplayUserIDResponse + (*ChangeDisplayUserIDRequest)(nil), // 149: hyapp.user.v1.ChangeDisplayUserIDRequest + (*ChangeDisplayUserIDResponse)(nil), // 150: hyapp.user.v1.ChangeDisplayUserIDResponse + (*ApplyPrettyDisplayUserIDRequest)(nil), // 151: hyapp.user.v1.ApplyPrettyDisplayUserIDRequest + (*ApplyPrettyDisplayUserIDResponse)(nil), // 152: hyapp.user.v1.ApplyPrettyDisplayUserIDResponse + (*ExpirePrettyDisplayUserIDRequest)(nil), // 153: hyapp.user.v1.ExpirePrettyDisplayUserIDRequest + (*ExpirePrettyDisplayUserIDResponse)(nil), // 154: hyapp.user.v1.ExpirePrettyDisplayUserIDResponse + (*PrettyDisplayIDPool)(nil), // 155: hyapp.user.v1.PrettyDisplayIDPool + (*PrettyDisplayID)(nil), // 156: hyapp.user.v1.PrettyDisplayID + (*PrettyDisplayIDGenerationBatch)(nil), // 157: hyapp.user.v1.PrettyDisplayIDGenerationBatch + (*ListAvailablePrettyDisplayIDsRequest)(nil), // 158: hyapp.user.v1.ListAvailablePrettyDisplayIDsRequest + (*ListAvailablePrettyDisplayIDsResponse)(nil), // 159: hyapp.user.v1.ListAvailablePrettyDisplayIDsResponse + (*ApplyPrettyDisplayIDFromPoolRequest)(nil), // 160: hyapp.user.v1.ApplyPrettyDisplayIDFromPoolRequest + (*ApplyPrettyDisplayIDFromPoolResponse)(nil), // 161: hyapp.user.v1.ApplyPrettyDisplayIDFromPoolResponse + (*ListPrettyDisplayIDPoolsRequest)(nil), // 162: hyapp.user.v1.ListPrettyDisplayIDPoolsRequest + (*ListPrettyDisplayIDPoolsResponse)(nil), // 163: hyapp.user.v1.ListPrettyDisplayIDPoolsResponse + (*CreatePrettyDisplayIDPoolRequest)(nil), // 164: hyapp.user.v1.CreatePrettyDisplayIDPoolRequest + (*UpdatePrettyDisplayIDPoolRequest)(nil), // 165: hyapp.user.v1.UpdatePrettyDisplayIDPoolRequest + (*PrettyDisplayIDPoolResponse)(nil), // 166: hyapp.user.v1.PrettyDisplayIDPoolResponse + (*GeneratePrettyDisplayIDsRequest)(nil), // 167: hyapp.user.v1.GeneratePrettyDisplayIDsRequest + (*GeneratePrettyDisplayIDsResponse)(nil), // 168: hyapp.user.v1.GeneratePrettyDisplayIDsResponse + (*ListPrettyDisplayIDsRequest)(nil), // 169: hyapp.user.v1.ListPrettyDisplayIDsRequest + (*ListPrettyDisplayIDsResponse)(nil), // 170: hyapp.user.v1.ListPrettyDisplayIDsResponse + (*SetPrettyDisplayIDStatusRequest)(nil), // 171: hyapp.user.v1.SetPrettyDisplayIDStatusRequest + (*RecyclePrettyDisplayIDRequest)(nil), // 172: hyapp.user.v1.RecyclePrettyDisplayIDRequest + (*PrettyDisplayIDResponse)(nil), // 173: hyapp.user.v1.PrettyDisplayIDResponse + (*AdminGrantPrettyDisplayIDRequest)(nil), // 174: hyapp.user.v1.AdminGrantPrettyDisplayIDRequest + (*AdminGrantPrettyDisplayIDResponse)(nil), // 175: hyapp.user.v1.AdminGrantPrettyDisplayIDResponse + nil, // 176: hyapp.user.v1.BatchGetUsersResponse.UsersEntry + nil, // 177: hyapp.user.v1.BatchGetUserAdminProfilesResponse.ProfilesEntry + nil, // 178: 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 @@ -15096,239 +16052,261 @@ 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 - 167, // 71: hyapp.user.v1.BatchGetUsersResponse.users:type_name -> hyapp.user.v1.BatchGetUsersResponse.UsersEntry - 1, // 72: hyapp.user.v1.BatchGetRoomBasicUsersRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 168, // 73: hyapp.user.v1.BatchGetRoomBasicUsersResponse.users:type_name -> hyapp.user.v1.BatchGetRoomBasicUsersResponse.UsersEntry - 1, // 74: hyapp.user.v1.ListUserIDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 75: hyapp.user.v1.UpdateUserProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 5, // 76: hyapp.user.v1.UpdateUserProfileResponse.user:type_name -> hyapp.user.v1.User - 1, // 77: hyapp.user.v1.UpdateUserProfileBackgroundRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 5, // 78: hyapp.user.v1.UpdateUserProfileBackgroundResponse.user:type_name -> hyapp.user.v1.User - 1, // 79: hyapp.user.v1.UpdateUserContactInfoRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 5, // 80: hyapp.user.v1.UpdateUserContactInfoResponse.user:type_name -> hyapp.user.v1.User - 1, // 81: hyapp.user.v1.UpdateUserWithdrawAddressRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 5, // 82: hyapp.user.v1.UpdateUserWithdrawAddressResponse.user:type_name -> hyapp.user.v1.User - 1, // 83: hyapp.user.v1.ChangeUserCountryRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 84: hyapp.user.v1.AdminChangeUserCountryRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 5, // 85: hyapp.user.v1.ChangeUserCountryResponse.user:type_name -> hyapp.user.v1.User - 1, // 86: hyapp.user.v1.SetUserStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 0, // 87: hyapp.user.v1.SetUserStatusRequest.status:type_name -> hyapp.user.v1.UserStatus - 5, // 88: hyapp.user.v1.SetUserStatusResponse.user:type_name -> hyapp.user.v1.User - 1, // 89: hyapp.user.v1.CreateManagerUserBlockRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 101, // 90: hyapp.user.v1.CreateManagerUserBlockResponse.block:type_name -> hyapp.user.v1.ManagerUserBlock - 100, // 91: hyapp.user.v1.CreateManagerUserBlockResponse.status:type_name -> hyapp.user.v1.SetUserStatusResponse - 1, // 92: hyapp.user.v1.ListManagerUserBlocksRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 101, // 93: hyapp.user.v1.ListManagerUserBlocksResponse.blocks:type_name -> hyapp.user.v1.ManagerUserBlock - 1, // 94: hyapp.user.v1.UnblockManagerUserRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 101, // 95: hyapp.user.v1.UnblockManagerUserResponse.block:type_name -> hyapp.user.v1.ManagerUserBlock - 100, // 96: hyapp.user.v1.UnblockManagerUserResponse.status:type_name -> hyapp.user.v1.SetUserStatusResponse - 1, // 97: hyapp.user.v1.CompleteOnboardingRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 5, // 98: hyapp.user.v1.CompleteOnboardingResponse.user:type_name -> hyapp.user.v1.User - 16, // 99: hyapp.user.v1.CompleteOnboardingResponse.token:type_name -> hyapp.user.v1.AuthToken - 7, // 100: hyapp.user.v1.CompleteOnboardingResponse.invite:type_name -> hyapp.user.v1.InviteBinding - 1, // 101: hyapp.user.v1.SearchInviteReferrerRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 5, // 102: hyapp.user.v1.SearchInviteReferrerResponse.inviter:type_name -> hyapp.user.v1.User - 1, // 103: hyapp.user.v1.BindInviteReferrerRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 7, // 104: hyapp.user.v1.BindInviteReferrerResponse.invite:type_name -> hyapp.user.v1.InviteBinding - 5, // 105: hyapp.user.v1.BindInviteReferrerResponse.inviter:type_name -> hyapp.user.v1.User - 1, // 106: hyapp.user.v1.BindPushTokenRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 107: hyapp.user.v1.DeletePushTokenRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 108: hyapp.user.v1.ListCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 118, // 109: hyapp.user.v1.ListCountriesResponse.countries:type_name -> hyapp.user.v1.Country - 1, // 110: hyapp.user.v1.UpdateCountryRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 118, // 111: hyapp.user.v1.CountryResponse.country:type_name -> hyapp.user.v1.Country - 1, // 112: hyapp.user.v1.ListRegistrationCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 118, // 113: hyapp.user.v1.ListRegistrationCountriesResponse.countries:type_name -> hyapp.user.v1.Country - 1, // 114: hyapp.user.v1.ListLoginRiskBlockedCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 126, // 115: hyapp.user.v1.ListLoginRiskBlockedCountriesResponse.countries:type_name -> hyapp.user.v1.LoginRiskBlockedCountry - 1, // 116: hyapp.user.v1.ListRegionsRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 119, // 117: hyapp.user.v1.ListRegionsResponse.regions:type_name -> hyapp.user.v1.Region - 1, // 118: hyapp.user.v1.GetRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 119: hyapp.user.v1.UpdateRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 120: hyapp.user.v1.ReplaceRegionCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 119, // 121: hyapp.user.v1.RegionResponse.region:type_name -> hyapp.user.v1.Region - 1, // 122: hyapp.user.v1.GetUserIdentityRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 135, // 123: hyapp.user.v1.GetUserIdentityResponse.identity:type_name -> hyapp.user.v1.UserIdentity - 1, // 124: hyapp.user.v1.ResolveDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 135, // 125: hyapp.user.v1.ResolveDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity - 1, // 126: hyapp.user.v1.ChangeDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 135, // 127: hyapp.user.v1.ChangeDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity - 1, // 128: hyapp.user.v1.ApplyPrettyDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 135, // 129: hyapp.user.v1.ApplyPrettyDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity - 1, // 130: hyapp.user.v1.ExpirePrettyDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 135, // 131: hyapp.user.v1.ExpirePrettyDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity - 146, // 132: hyapp.user.v1.PrettyDisplayID.pool:type_name -> hyapp.user.v1.PrettyDisplayIDPool - 1, // 133: hyapp.user.v1.ListAvailablePrettyDisplayIDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 147, // 134: hyapp.user.v1.ListAvailablePrettyDisplayIDsResponse.items:type_name -> hyapp.user.v1.PrettyDisplayID - 1, // 135: hyapp.user.v1.ApplyPrettyDisplayIDFromPoolRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 135, // 136: hyapp.user.v1.ApplyPrettyDisplayIDFromPoolResponse.identity:type_name -> hyapp.user.v1.UserIdentity - 1, // 137: hyapp.user.v1.ListPrettyDisplayIDPoolsRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 146, // 138: hyapp.user.v1.ListPrettyDisplayIDPoolsResponse.items:type_name -> hyapp.user.v1.PrettyDisplayIDPool - 1, // 139: hyapp.user.v1.CreatePrettyDisplayIDPoolRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 140: hyapp.user.v1.UpdatePrettyDisplayIDPoolRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 146, // 141: hyapp.user.v1.PrettyDisplayIDPoolResponse.pool:type_name -> hyapp.user.v1.PrettyDisplayIDPool - 1, // 142: hyapp.user.v1.GeneratePrettyDisplayIDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 148, // 143: hyapp.user.v1.GeneratePrettyDisplayIDsResponse.batch:type_name -> hyapp.user.v1.PrettyDisplayIDGenerationBatch - 1, // 144: hyapp.user.v1.ListPrettyDisplayIDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 147, // 145: hyapp.user.v1.ListPrettyDisplayIDsResponse.items:type_name -> hyapp.user.v1.PrettyDisplayID - 1, // 146: hyapp.user.v1.SetPrettyDisplayIDStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 147: hyapp.user.v1.RecyclePrettyDisplayIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 147, // 148: hyapp.user.v1.PrettyDisplayIDResponse.item:type_name -> hyapp.user.v1.PrettyDisplayID - 1, // 149: hyapp.user.v1.AdminGrantPrettyDisplayIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 135, // 150: hyapp.user.v1.AdminGrantPrettyDisplayIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity - 5, // 151: hyapp.user.v1.BatchGetUsersResponse.UsersEntry.value:type_name -> hyapp.user.v1.User - 83, // 152: hyapp.user.v1.BatchGetRoomBasicUsersResponse.UsersEntry.value:type_name -> hyapp.user.v1.RoomBasicUser - 17, // 153: hyapp.user.v1.UserService.GetUser:input_type -> hyapp.user.v1.GetUserRequest - 9, // 154: hyapp.user.v1.UserService.GetInviteAttribution:input_type -> hyapp.user.v1.GetInviteAttributionRequest - 19, // 155: hyapp.user.v1.UserService.BusinessUserLookup:input_type -> hyapp.user.v1.BusinessUserLookupRequest - 23, // 156: hyapp.user.v1.UserService.GetMyProfileStats:input_type -> hyapp.user.v1.GetMyProfileStatsRequest - 81, // 157: hyapp.user.v1.UserService.BatchGetUsers:input_type -> hyapp.user.v1.BatchGetUsersRequest - 84, // 158: hyapp.user.v1.UserService.BatchGetRoomBasicUsers:input_type -> hyapp.user.v1.BatchGetRoomBasicUsersRequest - 86, // 159: hyapp.user.v1.UserService.ListUserIDs:input_type -> hyapp.user.v1.ListUserIDsRequest - 12, // 160: hyapp.user.v1.UserService.GetUserMicLifetimeStats:input_type -> hyapp.user.v1.GetUserMicLifetimeStatsRequest - 88, // 161: hyapp.user.v1.UserService.UpdateUserProfile:input_type -> hyapp.user.v1.UpdateUserProfileRequest - 90, // 162: hyapp.user.v1.UserService.UpdateUserProfileBackground:input_type -> hyapp.user.v1.UpdateUserProfileBackgroundRequest - 92, // 163: hyapp.user.v1.UserService.UpdateUserContactInfo:input_type -> hyapp.user.v1.UpdateUserContactInfoRequest - 94, // 164: hyapp.user.v1.UserService.UpdateUserWithdrawAddress:input_type -> hyapp.user.v1.UpdateUserWithdrawAddressRequest - 96, // 165: hyapp.user.v1.UserService.ChangeUserCountry:input_type -> hyapp.user.v1.ChangeUserCountryRequest - 97, // 166: hyapp.user.v1.UserService.AdminChangeUserCountry:input_type -> hyapp.user.v1.AdminChangeUserCountryRequest - 99, // 167: hyapp.user.v1.UserService.SetUserStatus:input_type -> hyapp.user.v1.SetUserStatusRequest - 102, // 168: hyapp.user.v1.UserService.CreateManagerUserBlock:input_type -> hyapp.user.v1.CreateManagerUserBlockRequest - 104, // 169: hyapp.user.v1.UserService.ListManagerUserBlocks:input_type -> hyapp.user.v1.ListManagerUserBlocksRequest - 106, // 170: hyapp.user.v1.UserService.UnblockManagerUser:input_type -> hyapp.user.v1.UnblockManagerUserRequest - 108, // 171: hyapp.user.v1.UserService.CompleteOnboarding:input_type -> hyapp.user.v1.CompleteOnboardingRequest - 110, // 172: hyapp.user.v1.UserService.SearchInviteReferrer:input_type -> hyapp.user.v1.SearchInviteReferrerRequest - 112, // 173: hyapp.user.v1.UserService.BindInviteReferrer:input_type -> hyapp.user.v1.BindInviteReferrerRequest - 25, // 174: hyapp.user.v1.UserSocialService.RecordProfileVisit:input_type -> hyapp.user.v1.RecordProfileVisitRequest - 28, // 175: hyapp.user.v1.UserSocialService.ListProfileVisitors:input_type -> hyapp.user.v1.ListProfileVisitorsRequest - 30, // 176: hyapp.user.v1.UserSocialService.FollowUser:input_type -> hyapp.user.v1.FollowUserRequest - 32, // 177: hyapp.user.v1.UserSocialService.UnfollowUser:input_type -> hyapp.user.v1.UnfollowUserRequest - 35, // 178: hyapp.user.v1.UserSocialService.ListFollowing:input_type -> hyapp.user.v1.ListFollowingRequest - 37, // 179: hyapp.user.v1.UserSocialService.ApplyFriend:input_type -> hyapp.user.v1.ApplyFriendRequest - 39, // 180: hyapp.user.v1.UserSocialService.AcceptFriendApplication:input_type -> hyapp.user.v1.AcceptFriendApplicationRequest - 41, // 181: hyapp.user.v1.UserSocialService.DeleteFriend:input_type -> hyapp.user.v1.DeleteFriendRequest - 44, // 182: hyapp.user.v1.UserSocialService.ListFriends:input_type -> hyapp.user.v1.ListFriendsRequest - 47, // 183: hyapp.user.v1.UserSocialService.ListFriendApplications:input_type -> hyapp.user.v1.ListFriendApplicationsRequest - 79, // 184: hyapp.user.v1.UserSocialService.SubmitReport:input_type -> hyapp.user.v1.SubmitReportRequest - 59, // 185: hyapp.user.v1.UserCPService.ListCPApplications:input_type -> hyapp.user.v1.ListCPApplicationsRequest - 61, // 186: hyapp.user.v1.UserCPService.AcceptCPApplication:input_type -> hyapp.user.v1.AcceptCPApplicationRequest - 63, // 187: hyapp.user.v1.UserCPService.RejectCPApplication:input_type -> hyapp.user.v1.RejectCPApplicationRequest - 65, // 188: hyapp.user.v1.UserCPService.ListCPRelationships:input_type -> hyapp.user.v1.ListCPRelationshipsRequest - 67, // 189: hyapp.user.v1.UserCPService.ListCPIntimacyLeaderboard:input_type -> hyapp.user.v1.ListCPIntimacyLeaderboardRequest - 69, // 190: hyapp.user.v1.UserCPService.PrepareBreakCPRelationship:input_type -> hyapp.user.v1.PrepareBreakCPRelationshipRequest - 71, // 191: hyapp.user.v1.UserCPService.ConfirmBreakCPRelationship:input_type -> hyapp.user.v1.ConfirmBreakCPRelationshipRequest - 73, // 192: hyapp.user.v1.UserCPService.CancelBreakCPRelationship:input_type -> hyapp.user.v1.CancelBreakCPRelationshipRequest - 76, // 193: hyapp.user.v1.UserCPInternalService.ConsumeRoomGiftCPEvent:input_type -> hyapp.user.v1.ConsumeRoomGiftCPEventRequest - 57, // 194: hyapp.user.v1.UserCPInternalService.ListCPWeeklyRankEntries:input_type -> hyapp.user.v1.ListCPWeeklyRankEntriesRequest - 14, // 195: hyapp.user.v1.UserCronService.ProcessLoginIPRiskBatch:input_type -> hyapp.user.v1.CronBatchRequest - 14, // 196: hyapp.user.v1.UserCronService.ProcessRegionRebuildBatch:input_type -> hyapp.user.v1.CronBatchRequest - 14, // 197: hyapp.user.v1.UserCronService.CompensateMicOpenSessions:input_type -> hyapp.user.v1.CronBatchRequest - 14, // 198: hyapp.user.v1.UserCronService.ExpireManagerUserBlocks:input_type -> hyapp.user.v1.CronBatchRequest - 14, // 199: hyapp.user.v1.UserCronService.RefreshCPIntimacyLeaderboard:input_type -> hyapp.user.v1.CronBatchRequest - 114, // 200: hyapp.user.v1.UserDeviceService.BindPushToken:input_type -> hyapp.user.v1.BindPushTokenRequest - 116, // 201: hyapp.user.v1.UserDeviceService.DeletePushToken:input_type -> hyapp.user.v1.DeletePushTokenRequest - 3, // 202: hyapp.user.v1.AppRegistryService.ResolveApp:input_type -> hyapp.user.v1.ResolveAppRequest - 120, // 203: hyapp.user.v1.CountryAdminService.ListCountries:input_type -> hyapp.user.v1.ListCountriesRequest - 122, // 204: hyapp.user.v1.CountryAdminService.UpdateCountry:input_type -> hyapp.user.v1.UpdateCountryRequest - 124, // 205: hyapp.user.v1.CountryQueryService.ListRegistrationCountries:input_type -> hyapp.user.v1.ListRegistrationCountriesRequest - 127, // 206: hyapp.user.v1.CountryQueryService.ListLoginRiskBlockedCountries:input_type -> hyapp.user.v1.ListLoginRiskBlockedCountriesRequest - 129, // 207: hyapp.user.v1.RegionAdminService.ListRegions:input_type -> hyapp.user.v1.ListRegionsRequest - 131, // 208: hyapp.user.v1.RegionAdminService.GetRegion:input_type -> hyapp.user.v1.GetRegionRequest - 132, // 209: hyapp.user.v1.RegionAdminService.UpdateRegion:input_type -> hyapp.user.v1.UpdateRegionRequest - 133, // 210: hyapp.user.v1.RegionAdminService.ReplaceRegionCountries:input_type -> hyapp.user.v1.ReplaceRegionCountriesRequest - 136, // 211: hyapp.user.v1.UserIdentityService.GetUserIdentity:input_type -> hyapp.user.v1.GetUserIdentityRequest - 138, // 212: hyapp.user.v1.UserIdentityService.ResolveDisplayUserID:input_type -> hyapp.user.v1.ResolveDisplayUserIDRequest - 140, // 213: hyapp.user.v1.UserIdentityService.ChangeDisplayUserID:input_type -> hyapp.user.v1.ChangeDisplayUserIDRequest - 142, // 214: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayUserID:input_type -> hyapp.user.v1.ApplyPrettyDisplayUserIDRequest - 149, // 215: hyapp.user.v1.UserIdentityService.ListAvailablePrettyDisplayIDs:input_type -> hyapp.user.v1.ListAvailablePrettyDisplayIDsRequest - 151, // 216: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayIDFromPool:input_type -> hyapp.user.v1.ApplyPrettyDisplayIDFromPoolRequest - 144, // 217: hyapp.user.v1.UserIdentityService.ExpirePrettyDisplayUserID:input_type -> hyapp.user.v1.ExpirePrettyDisplayUserIDRequest - 153, // 218: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDPools:input_type -> hyapp.user.v1.ListPrettyDisplayIDPoolsRequest - 155, // 219: hyapp.user.v1.UserPrettyDisplayIDAdminService.CreatePrettyDisplayIDPool:input_type -> hyapp.user.v1.CreatePrettyDisplayIDPoolRequest - 156, // 220: hyapp.user.v1.UserPrettyDisplayIDAdminService.UpdatePrettyDisplayIDPool:input_type -> hyapp.user.v1.UpdatePrettyDisplayIDPoolRequest - 158, // 221: hyapp.user.v1.UserPrettyDisplayIDAdminService.GeneratePrettyDisplayIDs:input_type -> hyapp.user.v1.GeneratePrettyDisplayIDsRequest - 160, // 222: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDs:input_type -> hyapp.user.v1.ListPrettyDisplayIDsRequest - 162, // 223: hyapp.user.v1.UserPrettyDisplayIDAdminService.SetPrettyDisplayIDStatus:input_type -> hyapp.user.v1.SetPrettyDisplayIDStatusRequest - 163, // 224: hyapp.user.v1.UserPrettyDisplayIDAdminService.RecyclePrettyDisplayID:input_type -> hyapp.user.v1.RecyclePrettyDisplayIDRequest - 165, // 225: hyapp.user.v1.UserPrettyDisplayIDAdminService.AdminGrantPrettyDisplayID:input_type -> hyapp.user.v1.AdminGrantPrettyDisplayIDRequest - 18, // 226: hyapp.user.v1.UserService.GetUser:output_type -> hyapp.user.v1.GetUserResponse - 10, // 227: hyapp.user.v1.UserService.GetInviteAttribution:output_type -> hyapp.user.v1.GetInviteAttributionResponse - 21, // 228: hyapp.user.v1.UserService.BusinessUserLookup:output_type -> hyapp.user.v1.BusinessUserLookupResponse - 24, // 229: hyapp.user.v1.UserService.GetMyProfileStats:output_type -> hyapp.user.v1.GetMyProfileStatsResponse - 82, // 230: hyapp.user.v1.UserService.BatchGetUsers:output_type -> hyapp.user.v1.BatchGetUsersResponse - 85, // 231: hyapp.user.v1.UserService.BatchGetRoomBasicUsers:output_type -> hyapp.user.v1.BatchGetRoomBasicUsersResponse - 87, // 232: hyapp.user.v1.UserService.ListUserIDs:output_type -> hyapp.user.v1.ListUserIDsResponse - 13, // 233: hyapp.user.v1.UserService.GetUserMicLifetimeStats:output_type -> hyapp.user.v1.GetUserMicLifetimeStatsResponse - 89, // 234: hyapp.user.v1.UserService.UpdateUserProfile:output_type -> hyapp.user.v1.UpdateUserProfileResponse - 91, // 235: hyapp.user.v1.UserService.UpdateUserProfileBackground:output_type -> hyapp.user.v1.UpdateUserProfileBackgroundResponse - 93, // 236: hyapp.user.v1.UserService.UpdateUserContactInfo:output_type -> hyapp.user.v1.UpdateUserContactInfoResponse - 95, // 237: hyapp.user.v1.UserService.UpdateUserWithdrawAddress:output_type -> hyapp.user.v1.UpdateUserWithdrawAddressResponse - 98, // 238: hyapp.user.v1.UserService.ChangeUserCountry:output_type -> hyapp.user.v1.ChangeUserCountryResponse - 98, // 239: hyapp.user.v1.UserService.AdminChangeUserCountry:output_type -> hyapp.user.v1.ChangeUserCountryResponse - 100, // 240: hyapp.user.v1.UserService.SetUserStatus:output_type -> hyapp.user.v1.SetUserStatusResponse - 103, // 241: hyapp.user.v1.UserService.CreateManagerUserBlock:output_type -> hyapp.user.v1.CreateManagerUserBlockResponse - 105, // 242: hyapp.user.v1.UserService.ListManagerUserBlocks:output_type -> hyapp.user.v1.ListManagerUserBlocksResponse - 107, // 243: hyapp.user.v1.UserService.UnblockManagerUser:output_type -> hyapp.user.v1.UnblockManagerUserResponse - 109, // 244: hyapp.user.v1.UserService.CompleteOnboarding:output_type -> hyapp.user.v1.CompleteOnboardingResponse - 111, // 245: hyapp.user.v1.UserService.SearchInviteReferrer:output_type -> hyapp.user.v1.SearchInviteReferrerResponse - 113, // 246: hyapp.user.v1.UserService.BindInviteReferrer:output_type -> hyapp.user.v1.BindInviteReferrerResponse - 26, // 247: hyapp.user.v1.UserSocialService.RecordProfileVisit:output_type -> hyapp.user.v1.RecordProfileVisitResponse - 29, // 248: hyapp.user.v1.UserSocialService.ListProfileVisitors:output_type -> hyapp.user.v1.ListProfileVisitorsResponse - 31, // 249: hyapp.user.v1.UserSocialService.FollowUser:output_type -> hyapp.user.v1.FollowUserResponse - 33, // 250: hyapp.user.v1.UserSocialService.UnfollowUser:output_type -> hyapp.user.v1.UnfollowUserResponse - 36, // 251: hyapp.user.v1.UserSocialService.ListFollowing:output_type -> hyapp.user.v1.ListFollowingResponse - 38, // 252: hyapp.user.v1.UserSocialService.ApplyFriend:output_type -> hyapp.user.v1.ApplyFriendResponse - 40, // 253: hyapp.user.v1.UserSocialService.AcceptFriendApplication:output_type -> hyapp.user.v1.AcceptFriendApplicationResponse - 42, // 254: hyapp.user.v1.UserSocialService.DeleteFriend:output_type -> hyapp.user.v1.DeleteFriendResponse - 45, // 255: hyapp.user.v1.UserSocialService.ListFriends:output_type -> hyapp.user.v1.ListFriendsResponse - 48, // 256: hyapp.user.v1.UserSocialService.ListFriendApplications:output_type -> hyapp.user.v1.ListFriendApplicationsResponse - 80, // 257: hyapp.user.v1.UserSocialService.SubmitReport:output_type -> hyapp.user.v1.SubmitReportResponse - 60, // 258: hyapp.user.v1.UserCPService.ListCPApplications:output_type -> hyapp.user.v1.ListCPApplicationsResponse - 62, // 259: hyapp.user.v1.UserCPService.AcceptCPApplication:output_type -> hyapp.user.v1.AcceptCPApplicationResponse - 64, // 260: hyapp.user.v1.UserCPService.RejectCPApplication:output_type -> hyapp.user.v1.RejectCPApplicationResponse - 66, // 261: hyapp.user.v1.UserCPService.ListCPRelationships:output_type -> hyapp.user.v1.ListCPRelationshipsResponse - 68, // 262: hyapp.user.v1.UserCPService.ListCPIntimacyLeaderboard:output_type -> hyapp.user.v1.ListCPIntimacyLeaderboardResponse - 70, // 263: hyapp.user.v1.UserCPService.PrepareBreakCPRelationship:output_type -> hyapp.user.v1.PrepareBreakCPRelationshipResponse - 72, // 264: hyapp.user.v1.UserCPService.ConfirmBreakCPRelationship:output_type -> hyapp.user.v1.ConfirmBreakCPRelationshipResponse - 74, // 265: hyapp.user.v1.UserCPService.CancelBreakCPRelationship:output_type -> hyapp.user.v1.CancelBreakCPRelationshipResponse - 77, // 266: hyapp.user.v1.UserCPInternalService.ConsumeRoomGiftCPEvent:output_type -> hyapp.user.v1.ConsumeRoomGiftCPEventResponse - 58, // 267: hyapp.user.v1.UserCPInternalService.ListCPWeeklyRankEntries:output_type -> hyapp.user.v1.ListCPWeeklyRankEntriesResponse - 15, // 268: hyapp.user.v1.UserCronService.ProcessLoginIPRiskBatch:output_type -> hyapp.user.v1.CronBatchResponse - 15, // 269: hyapp.user.v1.UserCronService.ProcessRegionRebuildBatch:output_type -> hyapp.user.v1.CronBatchResponse - 15, // 270: hyapp.user.v1.UserCronService.CompensateMicOpenSessions:output_type -> hyapp.user.v1.CronBatchResponse - 15, // 271: hyapp.user.v1.UserCronService.ExpireManagerUserBlocks:output_type -> hyapp.user.v1.CronBatchResponse - 15, // 272: hyapp.user.v1.UserCronService.RefreshCPIntimacyLeaderboard:output_type -> hyapp.user.v1.CronBatchResponse - 115, // 273: hyapp.user.v1.UserDeviceService.BindPushToken:output_type -> hyapp.user.v1.BindPushTokenResponse - 117, // 274: hyapp.user.v1.UserDeviceService.DeletePushToken:output_type -> hyapp.user.v1.DeletePushTokenResponse - 4, // 275: hyapp.user.v1.AppRegistryService.ResolveApp:output_type -> hyapp.user.v1.ResolveAppResponse - 121, // 276: hyapp.user.v1.CountryAdminService.ListCountries:output_type -> hyapp.user.v1.ListCountriesResponse - 123, // 277: hyapp.user.v1.CountryAdminService.UpdateCountry:output_type -> hyapp.user.v1.CountryResponse - 125, // 278: hyapp.user.v1.CountryQueryService.ListRegistrationCountries:output_type -> hyapp.user.v1.ListRegistrationCountriesResponse - 128, // 279: hyapp.user.v1.CountryQueryService.ListLoginRiskBlockedCountries:output_type -> hyapp.user.v1.ListLoginRiskBlockedCountriesResponse - 130, // 280: hyapp.user.v1.RegionAdminService.ListRegions:output_type -> hyapp.user.v1.ListRegionsResponse - 134, // 281: hyapp.user.v1.RegionAdminService.GetRegion:output_type -> hyapp.user.v1.RegionResponse - 134, // 282: hyapp.user.v1.RegionAdminService.UpdateRegion:output_type -> hyapp.user.v1.RegionResponse - 134, // 283: hyapp.user.v1.RegionAdminService.ReplaceRegionCountries:output_type -> hyapp.user.v1.RegionResponse - 137, // 284: hyapp.user.v1.UserIdentityService.GetUserIdentity:output_type -> hyapp.user.v1.GetUserIdentityResponse - 139, // 285: hyapp.user.v1.UserIdentityService.ResolveDisplayUserID:output_type -> hyapp.user.v1.ResolveDisplayUserIDResponse - 141, // 286: hyapp.user.v1.UserIdentityService.ChangeDisplayUserID:output_type -> hyapp.user.v1.ChangeDisplayUserIDResponse - 143, // 287: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayUserID:output_type -> hyapp.user.v1.ApplyPrettyDisplayUserIDResponse - 150, // 288: hyapp.user.v1.UserIdentityService.ListAvailablePrettyDisplayIDs:output_type -> hyapp.user.v1.ListAvailablePrettyDisplayIDsResponse - 152, // 289: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayIDFromPool:output_type -> hyapp.user.v1.ApplyPrettyDisplayIDFromPoolResponse - 145, // 290: hyapp.user.v1.UserIdentityService.ExpirePrettyDisplayUserID:output_type -> hyapp.user.v1.ExpirePrettyDisplayUserIDResponse - 154, // 291: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDPools:output_type -> hyapp.user.v1.ListPrettyDisplayIDPoolsResponse - 157, // 292: hyapp.user.v1.UserPrettyDisplayIDAdminService.CreatePrettyDisplayIDPool:output_type -> hyapp.user.v1.PrettyDisplayIDPoolResponse - 157, // 293: hyapp.user.v1.UserPrettyDisplayIDAdminService.UpdatePrettyDisplayIDPool:output_type -> hyapp.user.v1.PrettyDisplayIDPoolResponse - 159, // 294: hyapp.user.v1.UserPrettyDisplayIDAdminService.GeneratePrettyDisplayIDs:output_type -> hyapp.user.v1.GeneratePrettyDisplayIDsResponse - 161, // 295: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDs:output_type -> hyapp.user.v1.ListPrettyDisplayIDsResponse - 164, // 296: hyapp.user.v1.UserPrettyDisplayIDAdminService.SetPrettyDisplayIDStatus:output_type -> hyapp.user.v1.PrettyDisplayIDResponse - 164, // 297: hyapp.user.v1.UserPrettyDisplayIDAdminService.RecyclePrettyDisplayID:output_type -> hyapp.user.v1.PrettyDisplayIDResponse - 166, // 298: hyapp.user.v1.UserPrettyDisplayIDAdminService.AdminGrantPrettyDisplayID:output_type -> hyapp.user.v1.AdminGrantPrettyDisplayIDResponse - 226, // [226:299] is the sub-list for method output_type - 153, // [153:226] is the sub-list for method input_type - 153, // [153:153] is the sub-list for extension type_name - 153, // [153:153] is the sub-list for extension extendee - 0, // [0:153] is the sub-list for field type_name + 176, // 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 + 177, // 76: hyapp.user.v1.BatchGetUserAdminProfilesResponse.profiles:type_name -> hyapp.user.v1.BatchGetUserAdminProfilesResponse.ProfilesEntry + 1, // 77: hyapp.user.v1.BatchGetRoomBasicUsersRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 178, // 78: hyapp.user.v1.BatchGetRoomBasicUsersResponse.users:type_name -> hyapp.user.v1.BatchGetRoomBasicUsersResponse.UsersEntry + 1, // 79: hyapp.user.v1.ListUserIDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 80: hyapp.user.v1.UpdateUserProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 5, // 81: hyapp.user.v1.UpdateUserProfileResponse.user:type_name -> hyapp.user.v1.User + 1, // 82: hyapp.user.v1.UpdateUserProfileBackgroundRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 5, // 83: hyapp.user.v1.UpdateUserProfileBackgroundResponse.user:type_name -> hyapp.user.v1.User + 1, // 84: hyapp.user.v1.UpdateUserContactInfoRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 5, // 85: hyapp.user.v1.UpdateUserContactInfoResponse.user:type_name -> hyapp.user.v1.User + 1, // 86: hyapp.user.v1.UpdateUserWithdrawAddressRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 5, // 87: hyapp.user.v1.UpdateUserWithdrawAddressResponse.user:type_name -> hyapp.user.v1.User + 1, // 88: hyapp.user.v1.ChangeUserCountryRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 89: hyapp.user.v1.AdminChangeUserCountryRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 5, // 90: hyapp.user.v1.ChangeUserCountryResponse.user:type_name -> hyapp.user.v1.User + 1, // 91: hyapp.user.v1.SetUserStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 0, // 92: hyapp.user.v1.SetUserStatusRequest.status:type_name -> hyapp.user.v1.UserStatus + 5, // 93: hyapp.user.v1.SetUserStatusResponse.user:type_name -> hyapp.user.v1.User + 1, // 94: hyapp.user.v1.AdminBanUserRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 105, // 95: hyapp.user.v1.AdminBanUserResponse.ban:type_name -> hyapp.user.v1.AdminUserBan + 104, // 96: hyapp.user.v1.AdminBanUserResponse.status:type_name -> hyapp.user.v1.SetUserStatusResponse + 1, // 97: hyapp.user.v1.AdminUnbanUserRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 105, // 98: hyapp.user.v1.AdminUnbanUserResponse.ban:type_name -> hyapp.user.v1.AdminUserBan + 104, // 99: hyapp.user.v1.AdminUnbanUserResponse.status:type_name -> hyapp.user.v1.SetUserStatusResponse + 1, // 100: hyapp.user.v1.CreateManagerUserBlockRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 110, // 101: hyapp.user.v1.CreateManagerUserBlockResponse.block:type_name -> hyapp.user.v1.ManagerUserBlock + 104, // 102: hyapp.user.v1.CreateManagerUserBlockResponse.status:type_name -> hyapp.user.v1.SetUserStatusResponse + 1, // 103: hyapp.user.v1.ListManagerUserBlocksRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 110, // 104: hyapp.user.v1.ListManagerUserBlocksResponse.blocks:type_name -> hyapp.user.v1.ManagerUserBlock + 1, // 105: hyapp.user.v1.UnblockManagerUserRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 110, // 106: hyapp.user.v1.UnblockManagerUserResponse.block:type_name -> hyapp.user.v1.ManagerUserBlock + 104, // 107: hyapp.user.v1.UnblockManagerUserResponse.status:type_name -> hyapp.user.v1.SetUserStatusResponse + 1, // 108: hyapp.user.v1.CompleteOnboardingRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 5, // 109: hyapp.user.v1.CompleteOnboardingResponse.user:type_name -> hyapp.user.v1.User + 16, // 110: hyapp.user.v1.CompleteOnboardingResponse.token:type_name -> hyapp.user.v1.AuthToken + 7, // 111: hyapp.user.v1.CompleteOnboardingResponse.invite:type_name -> hyapp.user.v1.InviteBinding + 1, // 112: hyapp.user.v1.SearchInviteReferrerRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 5, // 113: hyapp.user.v1.SearchInviteReferrerResponse.inviter:type_name -> hyapp.user.v1.User + 1, // 114: hyapp.user.v1.BindInviteReferrerRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 7, // 115: hyapp.user.v1.BindInviteReferrerResponse.invite:type_name -> hyapp.user.v1.InviteBinding + 5, // 116: hyapp.user.v1.BindInviteReferrerResponse.inviter:type_name -> hyapp.user.v1.User + 1, // 117: hyapp.user.v1.BindPushTokenRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 118: hyapp.user.v1.DeletePushTokenRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 119: hyapp.user.v1.ListCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 127, // 120: hyapp.user.v1.ListCountriesResponse.countries:type_name -> hyapp.user.v1.Country + 1, // 121: hyapp.user.v1.UpdateCountryRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 127, // 122: hyapp.user.v1.CountryResponse.country:type_name -> hyapp.user.v1.Country + 1, // 123: hyapp.user.v1.ListRegistrationCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 127, // 124: hyapp.user.v1.ListRegistrationCountriesResponse.countries:type_name -> hyapp.user.v1.Country + 1, // 125: hyapp.user.v1.ListLoginRiskBlockedCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 135, // 126: hyapp.user.v1.ListLoginRiskBlockedCountriesResponse.countries:type_name -> hyapp.user.v1.LoginRiskBlockedCountry + 1, // 127: hyapp.user.v1.ListRegionsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 128, // 128: hyapp.user.v1.ListRegionsResponse.regions:type_name -> hyapp.user.v1.Region + 1, // 129: hyapp.user.v1.GetRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 130: hyapp.user.v1.UpdateRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 131: hyapp.user.v1.ReplaceRegionCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 128, // 132: hyapp.user.v1.RegionResponse.region:type_name -> hyapp.user.v1.Region + 1, // 133: hyapp.user.v1.GetUserIdentityRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 144, // 134: hyapp.user.v1.GetUserIdentityResponse.identity:type_name -> hyapp.user.v1.UserIdentity + 1, // 135: hyapp.user.v1.ResolveDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 144, // 136: hyapp.user.v1.ResolveDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity + 1, // 137: hyapp.user.v1.ChangeDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 144, // 138: hyapp.user.v1.ChangeDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity + 1, // 139: hyapp.user.v1.ApplyPrettyDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 144, // 140: hyapp.user.v1.ApplyPrettyDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity + 1, // 141: hyapp.user.v1.ExpirePrettyDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 144, // 142: hyapp.user.v1.ExpirePrettyDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity + 155, // 143: hyapp.user.v1.PrettyDisplayID.pool:type_name -> hyapp.user.v1.PrettyDisplayIDPool + 1, // 144: hyapp.user.v1.ListAvailablePrettyDisplayIDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 156, // 145: hyapp.user.v1.ListAvailablePrettyDisplayIDsResponse.items:type_name -> hyapp.user.v1.PrettyDisplayID + 1, // 146: hyapp.user.v1.ApplyPrettyDisplayIDFromPoolRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 144, // 147: hyapp.user.v1.ApplyPrettyDisplayIDFromPoolResponse.identity:type_name -> hyapp.user.v1.UserIdentity + 1, // 148: hyapp.user.v1.ListPrettyDisplayIDPoolsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 155, // 149: hyapp.user.v1.ListPrettyDisplayIDPoolsResponse.items:type_name -> hyapp.user.v1.PrettyDisplayIDPool + 1, // 150: hyapp.user.v1.CreatePrettyDisplayIDPoolRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 151: hyapp.user.v1.UpdatePrettyDisplayIDPoolRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 155, // 152: hyapp.user.v1.PrettyDisplayIDPoolResponse.pool:type_name -> hyapp.user.v1.PrettyDisplayIDPool + 1, // 153: hyapp.user.v1.GeneratePrettyDisplayIDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 157, // 154: hyapp.user.v1.GeneratePrettyDisplayIDsResponse.batch:type_name -> hyapp.user.v1.PrettyDisplayIDGenerationBatch + 1, // 155: hyapp.user.v1.ListPrettyDisplayIDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 156, // 156: hyapp.user.v1.ListPrettyDisplayIDsResponse.items:type_name -> hyapp.user.v1.PrettyDisplayID + 1, // 157: hyapp.user.v1.SetPrettyDisplayIDStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 158: hyapp.user.v1.RecyclePrettyDisplayIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 156, // 159: hyapp.user.v1.PrettyDisplayIDResponse.item:type_name -> hyapp.user.v1.PrettyDisplayID + 1, // 160: hyapp.user.v1.AdminGrantPrettyDisplayIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 144, // 161: hyapp.user.v1.AdminGrantPrettyDisplayIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity + 5, // 162: hyapp.user.v1.BatchGetUsersResponse.UsersEntry.value:type_name -> hyapp.user.v1.User + 84, // 163: hyapp.user.v1.BatchGetUserAdminProfilesResponse.ProfilesEntry.value:type_name -> hyapp.user.v1.UserAdminProfile + 87, // 164: hyapp.user.v1.BatchGetRoomBasicUsersResponse.UsersEntry.value:type_name -> hyapp.user.v1.RoomBasicUser + 17, // 165: hyapp.user.v1.UserService.GetUser:input_type -> hyapp.user.v1.GetUserRequest + 9, // 166: hyapp.user.v1.UserService.GetInviteAttribution:input_type -> hyapp.user.v1.GetInviteAttributionRequest + 19, // 167: hyapp.user.v1.UserService.BusinessUserLookup:input_type -> hyapp.user.v1.BusinessUserLookupRequest + 23, // 168: hyapp.user.v1.UserService.GetMyProfileStats:input_type -> hyapp.user.v1.GetMyProfileStatsRequest + 81, // 169: hyapp.user.v1.UserService.BatchGetUsers:input_type -> hyapp.user.v1.BatchGetUsersRequest + 85, // 170: hyapp.user.v1.UserService.BatchGetUserAdminProfiles:input_type -> hyapp.user.v1.BatchGetUserAdminProfilesRequest + 88, // 171: hyapp.user.v1.UserService.BatchGetRoomBasicUsers:input_type -> hyapp.user.v1.BatchGetRoomBasicUsersRequest + 90, // 172: hyapp.user.v1.UserService.ListUserIDs:input_type -> hyapp.user.v1.ListUserIDsRequest + 12, // 173: hyapp.user.v1.UserService.GetUserMicLifetimeStats:input_type -> hyapp.user.v1.GetUserMicLifetimeStatsRequest + 92, // 174: hyapp.user.v1.UserService.UpdateUserProfile:input_type -> hyapp.user.v1.UpdateUserProfileRequest + 94, // 175: hyapp.user.v1.UserService.UpdateUserProfileBackground:input_type -> hyapp.user.v1.UpdateUserProfileBackgroundRequest + 96, // 176: hyapp.user.v1.UserService.UpdateUserContactInfo:input_type -> hyapp.user.v1.UpdateUserContactInfoRequest + 98, // 177: hyapp.user.v1.UserService.UpdateUserWithdrawAddress:input_type -> hyapp.user.v1.UpdateUserWithdrawAddressRequest + 100, // 178: hyapp.user.v1.UserService.ChangeUserCountry:input_type -> hyapp.user.v1.ChangeUserCountryRequest + 101, // 179: hyapp.user.v1.UserService.AdminChangeUserCountry:input_type -> hyapp.user.v1.AdminChangeUserCountryRequest + 103, // 180: hyapp.user.v1.UserService.SetUserStatus:input_type -> hyapp.user.v1.SetUserStatusRequest + 106, // 181: hyapp.user.v1.UserService.AdminBanUser:input_type -> hyapp.user.v1.AdminBanUserRequest + 108, // 182: hyapp.user.v1.UserService.AdminUnbanUser:input_type -> hyapp.user.v1.AdminUnbanUserRequest + 111, // 183: hyapp.user.v1.UserService.CreateManagerUserBlock:input_type -> hyapp.user.v1.CreateManagerUserBlockRequest + 113, // 184: hyapp.user.v1.UserService.ListManagerUserBlocks:input_type -> hyapp.user.v1.ListManagerUserBlocksRequest + 115, // 185: hyapp.user.v1.UserService.UnblockManagerUser:input_type -> hyapp.user.v1.UnblockManagerUserRequest + 117, // 186: hyapp.user.v1.UserService.CompleteOnboarding:input_type -> hyapp.user.v1.CompleteOnboardingRequest + 119, // 187: hyapp.user.v1.UserService.SearchInviteReferrer:input_type -> hyapp.user.v1.SearchInviteReferrerRequest + 121, // 188: hyapp.user.v1.UserService.BindInviteReferrer:input_type -> hyapp.user.v1.BindInviteReferrerRequest + 25, // 189: hyapp.user.v1.UserSocialService.RecordProfileVisit:input_type -> hyapp.user.v1.RecordProfileVisitRequest + 28, // 190: hyapp.user.v1.UserSocialService.ListProfileVisitors:input_type -> hyapp.user.v1.ListProfileVisitorsRequest + 30, // 191: hyapp.user.v1.UserSocialService.FollowUser:input_type -> hyapp.user.v1.FollowUserRequest + 32, // 192: hyapp.user.v1.UserSocialService.UnfollowUser:input_type -> hyapp.user.v1.UnfollowUserRequest + 35, // 193: hyapp.user.v1.UserSocialService.ListFollowing:input_type -> hyapp.user.v1.ListFollowingRequest + 37, // 194: hyapp.user.v1.UserSocialService.ApplyFriend:input_type -> hyapp.user.v1.ApplyFriendRequest + 39, // 195: hyapp.user.v1.UserSocialService.AcceptFriendApplication:input_type -> hyapp.user.v1.AcceptFriendApplicationRequest + 41, // 196: hyapp.user.v1.UserSocialService.DeleteFriend:input_type -> hyapp.user.v1.DeleteFriendRequest + 44, // 197: hyapp.user.v1.UserSocialService.ListFriends:input_type -> hyapp.user.v1.ListFriendsRequest + 47, // 198: hyapp.user.v1.UserSocialService.ListFriendApplications:input_type -> hyapp.user.v1.ListFriendApplicationsRequest + 79, // 199: hyapp.user.v1.UserSocialService.SubmitReport:input_type -> hyapp.user.v1.SubmitReportRequest + 59, // 200: hyapp.user.v1.UserCPService.ListCPApplications:input_type -> hyapp.user.v1.ListCPApplicationsRequest + 61, // 201: hyapp.user.v1.UserCPService.AcceptCPApplication:input_type -> hyapp.user.v1.AcceptCPApplicationRequest + 63, // 202: hyapp.user.v1.UserCPService.RejectCPApplication:input_type -> hyapp.user.v1.RejectCPApplicationRequest + 65, // 203: hyapp.user.v1.UserCPService.ListCPRelationships:input_type -> hyapp.user.v1.ListCPRelationshipsRequest + 67, // 204: hyapp.user.v1.UserCPService.ListCPIntimacyLeaderboard:input_type -> hyapp.user.v1.ListCPIntimacyLeaderboardRequest + 69, // 205: hyapp.user.v1.UserCPService.PrepareBreakCPRelationship:input_type -> hyapp.user.v1.PrepareBreakCPRelationshipRequest + 71, // 206: hyapp.user.v1.UserCPService.ConfirmBreakCPRelationship:input_type -> hyapp.user.v1.ConfirmBreakCPRelationshipRequest + 73, // 207: hyapp.user.v1.UserCPService.CancelBreakCPRelationship:input_type -> hyapp.user.v1.CancelBreakCPRelationshipRequest + 76, // 208: hyapp.user.v1.UserCPInternalService.ConsumeRoomGiftCPEvent:input_type -> hyapp.user.v1.ConsumeRoomGiftCPEventRequest + 57, // 209: hyapp.user.v1.UserCPInternalService.ListCPWeeklyRankEntries:input_type -> hyapp.user.v1.ListCPWeeklyRankEntriesRequest + 14, // 210: hyapp.user.v1.UserCronService.ProcessLoginIPRiskBatch:input_type -> hyapp.user.v1.CronBatchRequest + 14, // 211: hyapp.user.v1.UserCronService.ProcessRegionRebuildBatch:input_type -> hyapp.user.v1.CronBatchRequest + 14, // 212: hyapp.user.v1.UserCronService.CompensateMicOpenSessions:input_type -> hyapp.user.v1.CronBatchRequest + 14, // 213: hyapp.user.v1.UserCronService.CompensateRoomOpenSessions:input_type -> hyapp.user.v1.CronBatchRequest + 14, // 214: hyapp.user.v1.UserCronService.ExpireManagerUserBlocks:input_type -> hyapp.user.v1.CronBatchRequest + 14, // 215: hyapp.user.v1.UserCronService.ExpireAdminUserBans:input_type -> hyapp.user.v1.CronBatchRequest + 14, // 216: hyapp.user.v1.UserCronService.RefreshCPIntimacyLeaderboard:input_type -> hyapp.user.v1.CronBatchRequest + 123, // 217: hyapp.user.v1.UserDeviceService.BindPushToken:input_type -> hyapp.user.v1.BindPushTokenRequest + 125, // 218: hyapp.user.v1.UserDeviceService.DeletePushToken:input_type -> hyapp.user.v1.DeletePushTokenRequest + 3, // 219: hyapp.user.v1.AppRegistryService.ResolveApp:input_type -> hyapp.user.v1.ResolveAppRequest + 129, // 220: hyapp.user.v1.CountryAdminService.ListCountries:input_type -> hyapp.user.v1.ListCountriesRequest + 131, // 221: hyapp.user.v1.CountryAdminService.UpdateCountry:input_type -> hyapp.user.v1.UpdateCountryRequest + 133, // 222: hyapp.user.v1.CountryQueryService.ListRegistrationCountries:input_type -> hyapp.user.v1.ListRegistrationCountriesRequest + 136, // 223: hyapp.user.v1.CountryQueryService.ListLoginRiskBlockedCountries:input_type -> hyapp.user.v1.ListLoginRiskBlockedCountriesRequest + 138, // 224: hyapp.user.v1.RegionAdminService.ListRegions:input_type -> hyapp.user.v1.ListRegionsRequest + 140, // 225: hyapp.user.v1.RegionAdminService.GetRegion:input_type -> hyapp.user.v1.GetRegionRequest + 141, // 226: hyapp.user.v1.RegionAdminService.UpdateRegion:input_type -> hyapp.user.v1.UpdateRegionRequest + 142, // 227: hyapp.user.v1.RegionAdminService.ReplaceRegionCountries:input_type -> hyapp.user.v1.ReplaceRegionCountriesRequest + 145, // 228: hyapp.user.v1.UserIdentityService.GetUserIdentity:input_type -> hyapp.user.v1.GetUserIdentityRequest + 147, // 229: hyapp.user.v1.UserIdentityService.ResolveDisplayUserID:input_type -> hyapp.user.v1.ResolveDisplayUserIDRequest + 149, // 230: hyapp.user.v1.UserIdentityService.ChangeDisplayUserID:input_type -> hyapp.user.v1.ChangeDisplayUserIDRequest + 151, // 231: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayUserID:input_type -> hyapp.user.v1.ApplyPrettyDisplayUserIDRequest + 158, // 232: hyapp.user.v1.UserIdentityService.ListAvailablePrettyDisplayIDs:input_type -> hyapp.user.v1.ListAvailablePrettyDisplayIDsRequest + 160, // 233: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayIDFromPool:input_type -> hyapp.user.v1.ApplyPrettyDisplayIDFromPoolRequest + 153, // 234: hyapp.user.v1.UserIdentityService.ExpirePrettyDisplayUserID:input_type -> hyapp.user.v1.ExpirePrettyDisplayUserIDRequest + 162, // 235: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDPools:input_type -> hyapp.user.v1.ListPrettyDisplayIDPoolsRequest + 164, // 236: hyapp.user.v1.UserPrettyDisplayIDAdminService.CreatePrettyDisplayIDPool:input_type -> hyapp.user.v1.CreatePrettyDisplayIDPoolRequest + 165, // 237: hyapp.user.v1.UserPrettyDisplayIDAdminService.UpdatePrettyDisplayIDPool:input_type -> hyapp.user.v1.UpdatePrettyDisplayIDPoolRequest + 167, // 238: hyapp.user.v1.UserPrettyDisplayIDAdminService.GeneratePrettyDisplayIDs:input_type -> hyapp.user.v1.GeneratePrettyDisplayIDsRequest + 169, // 239: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDs:input_type -> hyapp.user.v1.ListPrettyDisplayIDsRequest + 171, // 240: hyapp.user.v1.UserPrettyDisplayIDAdminService.SetPrettyDisplayIDStatus:input_type -> hyapp.user.v1.SetPrettyDisplayIDStatusRequest + 172, // 241: hyapp.user.v1.UserPrettyDisplayIDAdminService.RecyclePrettyDisplayID:input_type -> hyapp.user.v1.RecyclePrettyDisplayIDRequest + 174, // 242: hyapp.user.v1.UserPrettyDisplayIDAdminService.AdminGrantPrettyDisplayID:input_type -> hyapp.user.v1.AdminGrantPrettyDisplayIDRequest + 18, // 243: hyapp.user.v1.UserService.GetUser:output_type -> hyapp.user.v1.GetUserResponse + 10, // 244: hyapp.user.v1.UserService.GetInviteAttribution:output_type -> hyapp.user.v1.GetInviteAttributionResponse + 21, // 245: hyapp.user.v1.UserService.BusinessUserLookup:output_type -> hyapp.user.v1.BusinessUserLookupResponse + 24, // 246: hyapp.user.v1.UserService.GetMyProfileStats:output_type -> hyapp.user.v1.GetMyProfileStatsResponse + 82, // 247: hyapp.user.v1.UserService.BatchGetUsers:output_type -> hyapp.user.v1.BatchGetUsersResponse + 86, // 248: hyapp.user.v1.UserService.BatchGetUserAdminProfiles:output_type -> hyapp.user.v1.BatchGetUserAdminProfilesResponse + 89, // 249: hyapp.user.v1.UserService.BatchGetRoomBasicUsers:output_type -> hyapp.user.v1.BatchGetRoomBasicUsersResponse + 91, // 250: hyapp.user.v1.UserService.ListUserIDs:output_type -> hyapp.user.v1.ListUserIDsResponse + 13, // 251: hyapp.user.v1.UserService.GetUserMicLifetimeStats:output_type -> hyapp.user.v1.GetUserMicLifetimeStatsResponse + 93, // 252: hyapp.user.v1.UserService.UpdateUserProfile:output_type -> hyapp.user.v1.UpdateUserProfileResponse + 95, // 253: hyapp.user.v1.UserService.UpdateUserProfileBackground:output_type -> hyapp.user.v1.UpdateUserProfileBackgroundResponse + 97, // 254: hyapp.user.v1.UserService.UpdateUserContactInfo:output_type -> hyapp.user.v1.UpdateUserContactInfoResponse + 99, // 255: hyapp.user.v1.UserService.UpdateUserWithdrawAddress:output_type -> hyapp.user.v1.UpdateUserWithdrawAddressResponse + 102, // 256: hyapp.user.v1.UserService.ChangeUserCountry:output_type -> hyapp.user.v1.ChangeUserCountryResponse + 102, // 257: hyapp.user.v1.UserService.AdminChangeUserCountry:output_type -> hyapp.user.v1.ChangeUserCountryResponse + 104, // 258: hyapp.user.v1.UserService.SetUserStatus:output_type -> hyapp.user.v1.SetUserStatusResponse + 107, // 259: hyapp.user.v1.UserService.AdminBanUser:output_type -> hyapp.user.v1.AdminBanUserResponse + 109, // 260: hyapp.user.v1.UserService.AdminUnbanUser:output_type -> hyapp.user.v1.AdminUnbanUserResponse + 112, // 261: hyapp.user.v1.UserService.CreateManagerUserBlock:output_type -> hyapp.user.v1.CreateManagerUserBlockResponse + 114, // 262: hyapp.user.v1.UserService.ListManagerUserBlocks:output_type -> hyapp.user.v1.ListManagerUserBlocksResponse + 116, // 263: hyapp.user.v1.UserService.UnblockManagerUser:output_type -> hyapp.user.v1.UnblockManagerUserResponse + 118, // 264: hyapp.user.v1.UserService.CompleteOnboarding:output_type -> hyapp.user.v1.CompleteOnboardingResponse + 120, // 265: hyapp.user.v1.UserService.SearchInviteReferrer:output_type -> hyapp.user.v1.SearchInviteReferrerResponse + 122, // 266: hyapp.user.v1.UserService.BindInviteReferrer:output_type -> hyapp.user.v1.BindInviteReferrerResponse + 26, // 267: hyapp.user.v1.UserSocialService.RecordProfileVisit:output_type -> hyapp.user.v1.RecordProfileVisitResponse + 29, // 268: hyapp.user.v1.UserSocialService.ListProfileVisitors:output_type -> hyapp.user.v1.ListProfileVisitorsResponse + 31, // 269: hyapp.user.v1.UserSocialService.FollowUser:output_type -> hyapp.user.v1.FollowUserResponse + 33, // 270: hyapp.user.v1.UserSocialService.UnfollowUser:output_type -> hyapp.user.v1.UnfollowUserResponse + 36, // 271: hyapp.user.v1.UserSocialService.ListFollowing:output_type -> hyapp.user.v1.ListFollowingResponse + 38, // 272: hyapp.user.v1.UserSocialService.ApplyFriend:output_type -> hyapp.user.v1.ApplyFriendResponse + 40, // 273: hyapp.user.v1.UserSocialService.AcceptFriendApplication:output_type -> hyapp.user.v1.AcceptFriendApplicationResponse + 42, // 274: hyapp.user.v1.UserSocialService.DeleteFriend:output_type -> hyapp.user.v1.DeleteFriendResponse + 45, // 275: hyapp.user.v1.UserSocialService.ListFriends:output_type -> hyapp.user.v1.ListFriendsResponse + 48, // 276: hyapp.user.v1.UserSocialService.ListFriendApplications:output_type -> hyapp.user.v1.ListFriendApplicationsResponse + 80, // 277: hyapp.user.v1.UserSocialService.SubmitReport:output_type -> hyapp.user.v1.SubmitReportResponse + 60, // 278: hyapp.user.v1.UserCPService.ListCPApplications:output_type -> hyapp.user.v1.ListCPApplicationsResponse + 62, // 279: hyapp.user.v1.UserCPService.AcceptCPApplication:output_type -> hyapp.user.v1.AcceptCPApplicationResponse + 64, // 280: hyapp.user.v1.UserCPService.RejectCPApplication:output_type -> hyapp.user.v1.RejectCPApplicationResponse + 66, // 281: hyapp.user.v1.UserCPService.ListCPRelationships:output_type -> hyapp.user.v1.ListCPRelationshipsResponse + 68, // 282: hyapp.user.v1.UserCPService.ListCPIntimacyLeaderboard:output_type -> hyapp.user.v1.ListCPIntimacyLeaderboardResponse + 70, // 283: hyapp.user.v1.UserCPService.PrepareBreakCPRelationship:output_type -> hyapp.user.v1.PrepareBreakCPRelationshipResponse + 72, // 284: hyapp.user.v1.UserCPService.ConfirmBreakCPRelationship:output_type -> hyapp.user.v1.ConfirmBreakCPRelationshipResponse + 74, // 285: hyapp.user.v1.UserCPService.CancelBreakCPRelationship:output_type -> hyapp.user.v1.CancelBreakCPRelationshipResponse + 77, // 286: hyapp.user.v1.UserCPInternalService.ConsumeRoomGiftCPEvent:output_type -> hyapp.user.v1.ConsumeRoomGiftCPEventResponse + 58, // 287: hyapp.user.v1.UserCPInternalService.ListCPWeeklyRankEntries:output_type -> hyapp.user.v1.ListCPWeeklyRankEntriesResponse + 15, // 288: hyapp.user.v1.UserCronService.ProcessLoginIPRiskBatch:output_type -> hyapp.user.v1.CronBatchResponse + 15, // 289: hyapp.user.v1.UserCronService.ProcessRegionRebuildBatch:output_type -> hyapp.user.v1.CronBatchResponse + 15, // 290: hyapp.user.v1.UserCronService.CompensateMicOpenSessions:output_type -> hyapp.user.v1.CronBatchResponse + 15, // 291: hyapp.user.v1.UserCronService.CompensateRoomOpenSessions:output_type -> hyapp.user.v1.CronBatchResponse + 15, // 292: hyapp.user.v1.UserCronService.ExpireManagerUserBlocks:output_type -> hyapp.user.v1.CronBatchResponse + 15, // 293: hyapp.user.v1.UserCronService.ExpireAdminUserBans:output_type -> hyapp.user.v1.CronBatchResponse + 15, // 294: hyapp.user.v1.UserCronService.RefreshCPIntimacyLeaderboard:output_type -> hyapp.user.v1.CronBatchResponse + 124, // 295: hyapp.user.v1.UserDeviceService.BindPushToken:output_type -> hyapp.user.v1.BindPushTokenResponse + 126, // 296: hyapp.user.v1.UserDeviceService.DeletePushToken:output_type -> hyapp.user.v1.DeletePushTokenResponse + 4, // 297: hyapp.user.v1.AppRegistryService.ResolveApp:output_type -> hyapp.user.v1.ResolveAppResponse + 130, // 298: hyapp.user.v1.CountryAdminService.ListCountries:output_type -> hyapp.user.v1.ListCountriesResponse + 132, // 299: hyapp.user.v1.CountryAdminService.UpdateCountry:output_type -> hyapp.user.v1.CountryResponse + 134, // 300: hyapp.user.v1.CountryQueryService.ListRegistrationCountries:output_type -> hyapp.user.v1.ListRegistrationCountriesResponse + 137, // 301: hyapp.user.v1.CountryQueryService.ListLoginRiskBlockedCountries:output_type -> hyapp.user.v1.ListLoginRiskBlockedCountriesResponse + 139, // 302: hyapp.user.v1.RegionAdminService.ListRegions:output_type -> hyapp.user.v1.ListRegionsResponse + 143, // 303: hyapp.user.v1.RegionAdminService.GetRegion:output_type -> hyapp.user.v1.RegionResponse + 143, // 304: hyapp.user.v1.RegionAdminService.UpdateRegion:output_type -> hyapp.user.v1.RegionResponse + 143, // 305: hyapp.user.v1.RegionAdminService.ReplaceRegionCountries:output_type -> hyapp.user.v1.RegionResponse + 146, // 306: hyapp.user.v1.UserIdentityService.GetUserIdentity:output_type -> hyapp.user.v1.GetUserIdentityResponse + 148, // 307: hyapp.user.v1.UserIdentityService.ResolveDisplayUserID:output_type -> hyapp.user.v1.ResolveDisplayUserIDResponse + 150, // 308: hyapp.user.v1.UserIdentityService.ChangeDisplayUserID:output_type -> hyapp.user.v1.ChangeDisplayUserIDResponse + 152, // 309: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayUserID:output_type -> hyapp.user.v1.ApplyPrettyDisplayUserIDResponse + 159, // 310: hyapp.user.v1.UserIdentityService.ListAvailablePrettyDisplayIDs:output_type -> hyapp.user.v1.ListAvailablePrettyDisplayIDsResponse + 161, // 311: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayIDFromPool:output_type -> hyapp.user.v1.ApplyPrettyDisplayIDFromPoolResponse + 154, // 312: hyapp.user.v1.UserIdentityService.ExpirePrettyDisplayUserID:output_type -> hyapp.user.v1.ExpirePrettyDisplayUserIDResponse + 163, // 313: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDPools:output_type -> hyapp.user.v1.ListPrettyDisplayIDPoolsResponse + 166, // 314: hyapp.user.v1.UserPrettyDisplayIDAdminService.CreatePrettyDisplayIDPool:output_type -> hyapp.user.v1.PrettyDisplayIDPoolResponse + 166, // 315: hyapp.user.v1.UserPrettyDisplayIDAdminService.UpdatePrettyDisplayIDPool:output_type -> hyapp.user.v1.PrettyDisplayIDPoolResponse + 168, // 316: hyapp.user.v1.UserPrettyDisplayIDAdminService.GeneratePrettyDisplayIDs:output_type -> hyapp.user.v1.GeneratePrettyDisplayIDsResponse + 170, // 317: hyapp.user.v1.UserPrettyDisplayIDAdminService.ListPrettyDisplayIDs:output_type -> hyapp.user.v1.ListPrettyDisplayIDsResponse + 173, // 318: hyapp.user.v1.UserPrettyDisplayIDAdminService.SetPrettyDisplayIDStatus:output_type -> hyapp.user.v1.PrettyDisplayIDResponse + 173, // 319: hyapp.user.v1.UserPrettyDisplayIDAdminService.RecyclePrettyDisplayID:output_type -> hyapp.user.v1.PrettyDisplayIDResponse + 175, // 320: hyapp.user.v1.UserPrettyDisplayIDAdminService.AdminGrantPrettyDisplayID:output_type -> hyapp.user.v1.AdminGrantPrettyDisplayIDResponse + 243, // [243:321] is the sub-list for method output_type + 165, // [165:243] is the sub-list for method input_type + 165, // [165:165] is the sub-list for extension type_name + 165, // [165:165] is the sub-list for extension extendee + 0, // [0:165] is the sub-list for field type_name } func init() { file_proto_user_v1_user_proto_init() } @@ -15336,15 +16314,15 @@ func file_proto_user_v1_user_proto_init() { if File_proto_user_v1_user_proto != nil { return } - file_proto_user_v1_user_proto_msgTypes[87].OneofWrappers = []any{} - file_proto_user_v1_user_proto_msgTypes[119].OneofWrappers = []any{} + file_proto_user_v1_user_proto_msgTypes[91].OneofWrappers = []any{} + file_proto_user_v1_user_proto_msgTypes[128].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_user_v1_user_proto_rawDesc, NumEnums: 1, - NumMessages: 168, + NumMessages: 178, NumExtensions: 0, NumServices: 12, }, diff --git a/api/proto/user/v1/user.proto b/api/proto/user/v1/user.proto index 5e75e451..f62e7486 100644 --- a/api/proto/user/v1/user.proto +++ b/api/proto/user/v1/user.proto @@ -160,6 +160,7 @@ message CronBatchRequest { int64 lock_ttl_ms = 5; int64 pending_publish_max_age_ms = 6; int64 publishing_session_max_age_ms = 7; + int64 open_session_max_age_ms = 8; } // CronBatchResponse 返回一个批处理 run 的执行摘要。 @@ -691,6 +692,46 @@ message BatchGetUsersResponse { map users = 1; } +// ActiveUserBanSummary 是后台用户列表读取的有效封禁摘要。 +// expires_at_ms=0 只在 permanent=true 时表示永久;source 区分 admin、manager 和无新事实表记录的 legacy。 +message ActiveUserBanSummary { + bool active = 1; + string source = 2; + string ban_id = 3; + bool permanent = 4; + int64 expires_at_ms = 5; + UserStatus user_status = 6; + string operator_type = 7; + int64 operator_user_id = 8; + string reason = 9; + int64 created_at_ms = 10; + int32 active_ban_count = 11; +} + +// UserAdminProfile 聚合后台用户列表和详情需要的 user-service owner 事实。 +// roles 只返回当前有效身份:host、agency、bd、bd_leader、coin_seller、manager。 +message UserAdminProfile { + User user = 1; + string birth = 2; + string register_device = 3; + int64 last_success_login_at_ms = 4; + repeated string roles = 5; + ActiveUserBanSummary ban = 6; + string last_operator_type = 7; + int64 last_operator_user_id = 8; + string last_operation_reason = 9; + int64 last_operation_at_ms = 10; +} + +message BatchGetUserAdminProfilesRequest { + RequestMeta meta = 1; + repeated int64 user_ids = 2; +} + +message BatchGetUserAdminProfilesResponse { + map profiles = 1; +} + // RoomBasicUser 是房间首屏只需要的用户展示基础资料。 message RoomBasicUser { int64 user_id = 1; @@ -831,6 +872,51 @@ message SetUserStatusResponse { string access_token_revoke_error = 11; } +// AdminUserBan 是后台管理员封禁的独立事实;expires_at_ms=0 表示永久封禁。 +message AdminUserBan { + string ban_id = 1; + string command_id = 2; + int64 target_user_id = 3; + int64 expires_at_ms = 4; + bool permanent = 5; + string status = 6; + string reason = 7; + int64 operator_admin_id = 8; + int64 created_at_ms = 9; + int64 updated_at_ms = 10; + int64 released_by_admin_id = 11; + string released_reason = 12; + int64 released_at_ms = 13; +} + +message AdminBanUserRequest { + RequestMeta meta = 1; + string command_id = 2; + int64 target_user_id = 3; + int64 expires_at_ms = 4; + int64 operator_admin_id = 5; + string reason = 6; +} + +message AdminBanUserResponse { + AdminUserBan ban = 1; + SetUserStatusResponse status = 2; +} + +// AdminUnbanUserRequest 释放一条管理员封禁;ban_id 留空时按目标用户释放最新一条,其他管理员或经理封禁仍会阻止账号恢复。 +message AdminUnbanUserRequest { + RequestMeta meta = 1; + string ban_id = 2; + int64 target_user_id = 3; + int64 operator_admin_id = 4; + string reason = 5; +} + +message AdminUnbanUserResponse { + AdminUserBan ban = 1; + SetUserStatusResponse status = 2; +} + message ManagerUserBlock { string block_id = 1; int64 manager_user_id = 2; @@ -1343,6 +1429,7 @@ service UserService { rpc BusinessUserLookup(BusinessUserLookupRequest) returns (BusinessUserLookupResponse); rpc GetMyProfileStats(GetMyProfileStatsRequest) returns (GetMyProfileStatsResponse); rpc BatchGetUsers(BatchGetUsersRequest) returns (BatchGetUsersResponse); + rpc BatchGetUserAdminProfiles(BatchGetUserAdminProfilesRequest) returns (BatchGetUserAdminProfilesResponse); rpc BatchGetRoomBasicUsers(BatchGetRoomBasicUsersRequest) returns (BatchGetRoomBasicUsersResponse); rpc ListUserIDs(ListUserIDsRequest) returns (ListUserIDsResponse); rpc GetUserMicLifetimeStats(GetUserMicLifetimeStatsRequest) returns (GetUserMicLifetimeStatsResponse); @@ -1353,6 +1440,8 @@ service UserService { rpc ChangeUserCountry(ChangeUserCountryRequest) returns (ChangeUserCountryResponse); rpc AdminChangeUserCountry(AdminChangeUserCountryRequest) returns (ChangeUserCountryResponse); rpc SetUserStatus(SetUserStatusRequest) returns (SetUserStatusResponse); + rpc AdminBanUser(AdminBanUserRequest) returns (AdminBanUserResponse); + rpc AdminUnbanUser(AdminUnbanUserRequest) returns (AdminUnbanUserResponse); rpc CreateManagerUserBlock(CreateManagerUserBlockRequest) returns (CreateManagerUserBlockResponse); rpc ListManagerUserBlocks(ListManagerUserBlocksRequest) returns (ListManagerUserBlocksResponse); rpc UnblockManagerUser(UnblockManagerUserRequest) returns (UnblockManagerUserResponse); @@ -1399,7 +1488,9 @@ service UserCronService { rpc ProcessLoginIPRiskBatch(CronBatchRequest) returns (CronBatchResponse); rpc ProcessRegionRebuildBatch(CronBatchRequest) returns (CronBatchResponse); rpc CompensateMicOpenSessions(CronBatchRequest) returns (CronBatchResponse); + rpc CompensateRoomOpenSessions(CronBatchRequest) returns (CronBatchResponse); rpc ExpireManagerUserBlocks(CronBatchRequest) returns (CronBatchResponse); + rpc ExpireAdminUserBans(CronBatchRequest) returns (CronBatchResponse); rpc RefreshCPIntimacyLeaderboard(CronBatchRequest) returns (CronBatchResponse); } diff --git a/api/proto/user/v1/user_grpc.pb.go b/api/proto/user/v1/user_grpc.pb.go index d65f079e..878f17e8 100644 --- a/api/proto/user/v1/user_grpc.pb.go +++ b/api/proto/user/v1/user_grpc.pb.go @@ -24,6 +24,7 @@ const ( UserService_BusinessUserLookup_FullMethodName = "/hyapp.user.v1.UserService/BusinessUserLookup" UserService_GetMyProfileStats_FullMethodName = "/hyapp.user.v1.UserService/GetMyProfileStats" UserService_BatchGetUsers_FullMethodName = "/hyapp.user.v1.UserService/BatchGetUsers" + UserService_BatchGetUserAdminProfiles_FullMethodName = "/hyapp.user.v1.UserService/BatchGetUserAdminProfiles" UserService_BatchGetRoomBasicUsers_FullMethodName = "/hyapp.user.v1.UserService/BatchGetRoomBasicUsers" UserService_ListUserIDs_FullMethodName = "/hyapp.user.v1.UserService/ListUserIDs" UserService_GetUserMicLifetimeStats_FullMethodName = "/hyapp.user.v1.UserService/GetUserMicLifetimeStats" @@ -34,6 +35,8 @@ const ( UserService_ChangeUserCountry_FullMethodName = "/hyapp.user.v1.UserService/ChangeUserCountry" UserService_AdminChangeUserCountry_FullMethodName = "/hyapp.user.v1.UserService/AdminChangeUserCountry" UserService_SetUserStatus_FullMethodName = "/hyapp.user.v1.UserService/SetUserStatus" + UserService_AdminBanUser_FullMethodName = "/hyapp.user.v1.UserService/AdminBanUser" + UserService_AdminUnbanUser_FullMethodName = "/hyapp.user.v1.UserService/AdminUnbanUser" UserService_CreateManagerUserBlock_FullMethodName = "/hyapp.user.v1.UserService/CreateManagerUserBlock" UserService_ListManagerUserBlocks_FullMethodName = "/hyapp.user.v1.UserService/ListManagerUserBlocks" UserService_UnblockManagerUser_FullMethodName = "/hyapp.user.v1.UserService/UnblockManagerUser" @@ -53,6 +56,7 @@ type UserServiceClient interface { BusinessUserLookup(ctx context.Context, in *BusinessUserLookupRequest, opts ...grpc.CallOption) (*BusinessUserLookupResponse, error) GetMyProfileStats(ctx context.Context, in *GetMyProfileStatsRequest, opts ...grpc.CallOption) (*GetMyProfileStatsResponse, error) BatchGetUsers(ctx context.Context, in *BatchGetUsersRequest, opts ...grpc.CallOption) (*BatchGetUsersResponse, error) + BatchGetUserAdminProfiles(ctx context.Context, in *BatchGetUserAdminProfilesRequest, opts ...grpc.CallOption) (*BatchGetUserAdminProfilesResponse, error) BatchGetRoomBasicUsers(ctx context.Context, in *BatchGetRoomBasicUsersRequest, opts ...grpc.CallOption) (*BatchGetRoomBasicUsersResponse, error) ListUserIDs(ctx context.Context, in *ListUserIDsRequest, opts ...grpc.CallOption) (*ListUserIDsResponse, error) GetUserMicLifetimeStats(ctx context.Context, in *GetUserMicLifetimeStatsRequest, opts ...grpc.CallOption) (*GetUserMicLifetimeStatsResponse, error) @@ -63,6 +67,8 @@ type UserServiceClient interface { ChangeUserCountry(ctx context.Context, in *ChangeUserCountryRequest, opts ...grpc.CallOption) (*ChangeUserCountryResponse, error) AdminChangeUserCountry(ctx context.Context, in *AdminChangeUserCountryRequest, opts ...grpc.CallOption) (*ChangeUserCountryResponse, error) SetUserStatus(ctx context.Context, in *SetUserStatusRequest, opts ...grpc.CallOption) (*SetUserStatusResponse, error) + AdminBanUser(ctx context.Context, in *AdminBanUserRequest, opts ...grpc.CallOption) (*AdminBanUserResponse, error) + AdminUnbanUser(ctx context.Context, in *AdminUnbanUserRequest, opts ...grpc.CallOption) (*AdminUnbanUserResponse, error) CreateManagerUserBlock(ctx context.Context, in *CreateManagerUserBlockRequest, opts ...grpc.CallOption) (*CreateManagerUserBlockResponse, error) ListManagerUserBlocks(ctx context.Context, in *ListManagerUserBlocksRequest, opts ...grpc.CallOption) (*ListManagerUserBlocksResponse, error) UnblockManagerUser(ctx context.Context, in *UnblockManagerUserRequest, opts ...grpc.CallOption) (*UnblockManagerUserResponse, error) @@ -129,6 +135,16 @@ func (c *userServiceClient) BatchGetUsers(ctx context.Context, in *BatchGetUsers return out, nil } +func (c *userServiceClient) BatchGetUserAdminProfiles(ctx context.Context, in *BatchGetUserAdminProfilesRequest, opts ...grpc.CallOption) (*BatchGetUserAdminProfilesResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(BatchGetUserAdminProfilesResponse) + err := c.cc.Invoke(ctx, UserService_BatchGetUserAdminProfiles_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *userServiceClient) BatchGetRoomBasicUsers(ctx context.Context, in *BatchGetRoomBasicUsersRequest, opts ...grpc.CallOption) (*BatchGetRoomBasicUsersResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(BatchGetRoomBasicUsersResponse) @@ -229,6 +245,26 @@ func (c *userServiceClient) SetUserStatus(ctx context.Context, in *SetUserStatus return out, nil } +func (c *userServiceClient) AdminBanUser(ctx context.Context, in *AdminBanUserRequest, opts ...grpc.CallOption) (*AdminBanUserResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(AdminBanUserResponse) + err := c.cc.Invoke(ctx, UserService_AdminBanUser_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *userServiceClient) AdminUnbanUser(ctx context.Context, in *AdminUnbanUserRequest, opts ...grpc.CallOption) (*AdminUnbanUserResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(AdminUnbanUserResponse) + err := c.cc.Invoke(ctx, UserService_AdminUnbanUser_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *userServiceClient) CreateManagerUserBlock(ctx context.Context, in *CreateManagerUserBlockRequest, opts ...grpc.CallOption) (*CreateManagerUserBlockResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(CreateManagerUserBlockResponse) @@ -300,6 +336,7 @@ type UserServiceServer interface { BusinessUserLookup(context.Context, *BusinessUserLookupRequest) (*BusinessUserLookupResponse, error) GetMyProfileStats(context.Context, *GetMyProfileStatsRequest) (*GetMyProfileStatsResponse, error) BatchGetUsers(context.Context, *BatchGetUsersRequest) (*BatchGetUsersResponse, error) + BatchGetUserAdminProfiles(context.Context, *BatchGetUserAdminProfilesRequest) (*BatchGetUserAdminProfilesResponse, error) BatchGetRoomBasicUsers(context.Context, *BatchGetRoomBasicUsersRequest) (*BatchGetRoomBasicUsersResponse, error) ListUserIDs(context.Context, *ListUserIDsRequest) (*ListUserIDsResponse, error) GetUserMicLifetimeStats(context.Context, *GetUserMicLifetimeStatsRequest) (*GetUserMicLifetimeStatsResponse, error) @@ -310,6 +347,8 @@ type UserServiceServer interface { ChangeUserCountry(context.Context, *ChangeUserCountryRequest) (*ChangeUserCountryResponse, error) AdminChangeUserCountry(context.Context, *AdminChangeUserCountryRequest) (*ChangeUserCountryResponse, error) SetUserStatus(context.Context, *SetUserStatusRequest) (*SetUserStatusResponse, error) + AdminBanUser(context.Context, *AdminBanUserRequest) (*AdminBanUserResponse, error) + AdminUnbanUser(context.Context, *AdminUnbanUserRequest) (*AdminUnbanUserResponse, error) CreateManagerUserBlock(context.Context, *CreateManagerUserBlockRequest) (*CreateManagerUserBlockResponse, error) ListManagerUserBlocks(context.Context, *ListManagerUserBlocksRequest) (*ListManagerUserBlocksResponse, error) UnblockManagerUser(context.Context, *UnblockManagerUserRequest) (*UnblockManagerUserResponse, error) @@ -341,6 +380,9 @@ func (UnimplementedUserServiceServer) GetMyProfileStats(context.Context, *GetMyP func (UnimplementedUserServiceServer) BatchGetUsers(context.Context, *BatchGetUsersRequest) (*BatchGetUsersResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method BatchGetUsers not implemented") } +func (UnimplementedUserServiceServer) BatchGetUserAdminProfiles(context.Context, *BatchGetUserAdminProfilesRequest) (*BatchGetUserAdminProfilesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method BatchGetUserAdminProfiles not implemented") +} func (UnimplementedUserServiceServer) BatchGetRoomBasicUsers(context.Context, *BatchGetRoomBasicUsersRequest) (*BatchGetRoomBasicUsersResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method BatchGetRoomBasicUsers not implemented") } @@ -371,6 +413,12 @@ func (UnimplementedUserServiceServer) AdminChangeUserCountry(context.Context, *A func (UnimplementedUserServiceServer) SetUserStatus(context.Context, *SetUserStatusRequest) (*SetUserStatusResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SetUserStatus not implemented") } +func (UnimplementedUserServiceServer) AdminBanUser(context.Context, *AdminBanUserRequest) (*AdminBanUserResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AdminBanUser not implemented") +} +func (UnimplementedUserServiceServer) AdminUnbanUser(context.Context, *AdminUnbanUserRequest) (*AdminUnbanUserResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AdminUnbanUser not implemented") +} func (UnimplementedUserServiceServer) CreateManagerUserBlock(context.Context, *CreateManagerUserBlockRequest) (*CreateManagerUserBlockResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateManagerUserBlock not implemented") } @@ -500,6 +548,24 @@ func _UserService_BatchGetUsers_Handler(srv interface{}, ctx context.Context, de return interceptor(ctx, in, info, handler) } +func _UserService_BatchGetUserAdminProfiles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BatchGetUserAdminProfilesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServiceServer).BatchGetUserAdminProfiles(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UserService_BatchGetUserAdminProfiles_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServiceServer).BatchGetUserAdminProfiles(ctx, req.(*BatchGetUserAdminProfilesRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _UserService_BatchGetRoomBasicUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(BatchGetRoomBasicUsersRequest) if err := dec(in); err != nil { @@ -680,6 +746,42 @@ func _UserService_SetUserStatus_Handler(srv interface{}, ctx context.Context, de return interceptor(ctx, in, info, handler) } +func _UserService_AdminBanUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AdminBanUserRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServiceServer).AdminBanUser(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UserService_AdminBanUser_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServiceServer).AdminBanUser(ctx, req.(*AdminBanUserRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _UserService_AdminUnbanUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AdminUnbanUserRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServiceServer).AdminUnbanUser(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UserService_AdminUnbanUser_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServiceServer).AdminUnbanUser(ctx, req.(*AdminUnbanUserRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _UserService_CreateManagerUserBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreateManagerUserBlockRequest) if err := dec(in); err != nil { @@ -815,6 +917,10 @@ var UserService_ServiceDesc = grpc.ServiceDesc{ MethodName: "BatchGetUsers", Handler: _UserService_BatchGetUsers_Handler, }, + { + MethodName: "BatchGetUserAdminProfiles", + Handler: _UserService_BatchGetUserAdminProfiles_Handler, + }, { MethodName: "BatchGetRoomBasicUsers", Handler: _UserService_BatchGetRoomBasicUsers_Handler, @@ -855,6 +961,14 @@ var UserService_ServiceDesc = grpc.ServiceDesc{ MethodName: "SetUserStatus", Handler: _UserService_SetUserStatus_Handler, }, + { + MethodName: "AdminBanUser", + Handler: _UserService_AdminBanUser_Handler, + }, + { + MethodName: "AdminUnbanUser", + Handler: _UserService_AdminUnbanUser_Handler, + }, { MethodName: "CreateManagerUserBlock", Handler: _UserService_CreateManagerUserBlock_Handler, @@ -1890,7 +2004,9 @@ const ( UserCronService_ProcessLoginIPRiskBatch_FullMethodName = "/hyapp.user.v1.UserCronService/ProcessLoginIPRiskBatch" UserCronService_ProcessRegionRebuildBatch_FullMethodName = "/hyapp.user.v1.UserCronService/ProcessRegionRebuildBatch" UserCronService_CompensateMicOpenSessions_FullMethodName = "/hyapp.user.v1.UserCronService/CompensateMicOpenSessions" + UserCronService_CompensateRoomOpenSessions_FullMethodName = "/hyapp.user.v1.UserCronService/CompensateRoomOpenSessions" UserCronService_ExpireManagerUserBlocks_FullMethodName = "/hyapp.user.v1.UserCronService/ExpireManagerUserBlocks" + UserCronService_ExpireAdminUserBans_FullMethodName = "/hyapp.user.v1.UserCronService/ExpireAdminUserBans" UserCronService_RefreshCPIntimacyLeaderboard_FullMethodName = "/hyapp.user.v1.UserCronService/RefreshCPIntimacyLeaderboard" ) @@ -1903,7 +2019,9 @@ type UserCronServiceClient interface { ProcessLoginIPRiskBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) ProcessRegionRebuildBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) CompensateMicOpenSessions(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) + CompensateRoomOpenSessions(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) ExpireManagerUserBlocks(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) + ExpireAdminUserBans(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) RefreshCPIntimacyLeaderboard(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) } @@ -1945,6 +2063,16 @@ func (c *userCronServiceClient) CompensateMicOpenSessions(ctx context.Context, i return out, nil } +func (c *userCronServiceClient) CompensateRoomOpenSessions(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CronBatchResponse) + err := c.cc.Invoke(ctx, UserCronService_CompensateRoomOpenSessions_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *userCronServiceClient) ExpireManagerUserBlocks(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(CronBatchResponse) @@ -1955,6 +2083,16 @@ func (c *userCronServiceClient) ExpireManagerUserBlocks(ctx context.Context, in return out, nil } +func (c *userCronServiceClient) ExpireAdminUserBans(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CronBatchResponse) + err := c.cc.Invoke(ctx, UserCronService_ExpireAdminUserBans_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *userCronServiceClient) RefreshCPIntimacyLeaderboard(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(CronBatchResponse) @@ -1974,7 +2112,9 @@ type UserCronServiceServer interface { ProcessLoginIPRiskBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) ProcessRegionRebuildBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) CompensateMicOpenSessions(context.Context, *CronBatchRequest) (*CronBatchResponse, error) + CompensateRoomOpenSessions(context.Context, *CronBatchRequest) (*CronBatchResponse, error) ExpireManagerUserBlocks(context.Context, *CronBatchRequest) (*CronBatchResponse, error) + ExpireAdminUserBans(context.Context, *CronBatchRequest) (*CronBatchResponse, error) RefreshCPIntimacyLeaderboard(context.Context, *CronBatchRequest) (*CronBatchResponse, error) mustEmbedUnimplementedUserCronServiceServer() } @@ -1995,9 +2135,15 @@ func (UnimplementedUserCronServiceServer) ProcessRegionRebuildBatch(context.Cont func (UnimplementedUserCronServiceServer) CompensateMicOpenSessions(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CompensateMicOpenSessions not implemented") } +func (UnimplementedUserCronServiceServer) CompensateRoomOpenSessions(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CompensateRoomOpenSessions not implemented") +} func (UnimplementedUserCronServiceServer) ExpireManagerUserBlocks(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ExpireManagerUserBlocks not implemented") } +func (UnimplementedUserCronServiceServer) ExpireAdminUserBans(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ExpireAdminUserBans not implemented") +} func (UnimplementedUserCronServiceServer) RefreshCPIntimacyLeaderboard(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RefreshCPIntimacyLeaderboard not implemented") } @@ -2076,6 +2222,24 @@ func _UserCronService_CompensateMicOpenSessions_Handler(srv interface{}, ctx con return interceptor(ctx, in, info, handler) } +func _UserCronService_CompensateRoomOpenSessions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CronBatchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserCronServiceServer).CompensateRoomOpenSessions(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UserCronService_CompensateRoomOpenSessions_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserCronServiceServer).CompensateRoomOpenSessions(ctx, req.(*CronBatchRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _UserCronService_ExpireManagerUserBlocks_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CronBatchRequest) if err := dec(in); err != nil { @@ -2094,6 +2258,24 @@ func _UserCronService_ExpireManagerUserBlocks_Handler(srv interface{}, ctx conte return interceptor(ctx, in, info, handler) } +func _UserCronService_ExpireAdminUserBans_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CronBatchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserCronServiceServer).ExpireAdminUserBans(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UserCronService_ExpireAdminUserBans_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserCronServiceServer).ExpireAdminUserBans(ctx, req.(*CronBatchRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _UserCronService_RefreshCPIntimacyLeaderboard_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CronBatchRequest) if err := dec(in); err != nil { @@ -2131,10 +2313,18 @@ var UserCronService_ServiceDesc = grpc.ServiceDesc{ MethodName: "CompensateMicOpenSessions", Handler: _UserCronService_CompensateMicOpenSessions_Handler, }, + { + MethodName: "CompensateRoomOpenSessions", + Handler: _UserCronService_CompensateRoomOpenSessions_Handler, + }, { MethodName: "ExpireManagerUserBlocks", Handler: _UserCronService_ExpireManagerUserBlocks_Handler, }, + { + MethodName: "ExpireAdminUserBans", + Handler: _UserCronService_ExpireAdminUserBans_Handler, + }, { MethodName: "RefreshCPIntimacyLeaderboard", Handler: _UserCronService_RefreshCPIntimacyLeaderboard_Handler, diff --git a/api/proto/wallet/v1/wallet.pb.go b/api/proto/wallet/v1/wallet.pb.go index cb5cb70a..c0af0aee 100644 --- a/api/proto/wallet/v1/wallet.pb.go +++ b/api/proto/wallet/v1/wallet.pb.go @@ -11180,6 +11180,198 @@ func (x *GetRechargeBillSummaryResponse) GetCoinSeller() *RechargeBillSummaryBuc return nil } +// 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"` +} + +func (x *UserRechargeStats) Reset() { + *x = UserRechargeStats{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UserRechargeStats) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserRechargeStats) ProtoMessage() {} + +func (x *UserRechargeStats) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] + 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 UserRechargeStats.ProtoReflect.Descriptor instead. +func (*UserRechargeStats) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{120} +} + +func (x *UserRechargeStats) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *UserRechargeStats) GetRechargeCount() int64 { + if x != nil { + return x.RechargeCount + } + return 0 +} + +func (x *UserRechargeStats) GetTotalCoinAmount() int64 { + if x != nil { + return x.TotalCoinAmount + } + return 0 +} + +func (x *UserRechargeStats) GetTotalUsdMinorAmount() int64 { + if x != nil { + return x.TotalUsdMinorAmount + } + return 0 +} + +func (x *UserRechargeStats) GetFirstRechargedAtMs() int64 { + if x != nil { + return x.FirstRechargedAtMs + } + return 0 +} + +func (x *UserRechargeStats) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +type BatchGetUserRechargeStatsRequest 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"` + UserIds []int64 `protobuf:"varint,3,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` +} + +func (x *BatchGetUserRechargeStatsRequest) Reset() { + *x = BatchGetUserRechargeStatsRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BatchGetUserRechargeStatsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BatchGetUserRechargeStatsRequest) ProtoMessage() {} + +func (x *BatchGetUserRechargeStatsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] + 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 BatchGetUserRechargeStatsRequest.ProtoReflect.Descriptor instead. +func (*BatchGetUserRechargeStatsRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{121} +} + +func (x *BatchGetUserRechargeStatsRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *BatchGetUserRechargeStatsRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *BatchGetUserRechargeStatsRequest) GetUserIds() []int64 { + if x != nil { + return x.UserIds + } + return nil +} + +type BatchGetUserRechargeStatsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Items []*UserRechargeStats `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` +} + +func (x *BatchGetUserRechargeStatsResponse) Reset() { + *x = BatchGetUserRechargeStatsResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BatchGetUserRechargeStatsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BatchGetUserRechargeStatsResponse) ProtoMessage() {} + +func (x *BatchGetUserRechargeStatsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] + 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 BatchGetUserRechargeStatsResponse.ProtoReflect.Descriptor instead. +func (*BatchGetUserRechargeStatsResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{122} +} + +func (x *BatchGetUserRechargeStatsResponse) GetItems() []*UserRechargeStats { + if x != nil { + return x.Items + } + return nil +} + type GetRechargeBillOverviewRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -11198,7 +11390,7 @@ type GetRechargeBillOverviewRequest struct { func (x *GetRechargeBillOverviewRequest) Reset() { *x = GetRechargeBillOverviewRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11210,7 +11402,7 @@ func (x *GetRechargeBillOverviewRequest) String() string { func (*GetRechargeBillOverviewRequest) ProtoMessage() {} func (x *GetRechargeBillOverviewRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11223,7 +11415,7 @@ func (x *GetRechargeBillOverviewRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRechargeBillOverviewRequest.ProtoReflect.Descriptor instead. func (*GetRechargeBillOverviewRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{120} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{123} } func (x *GetRechargeBillOverviewRequest) GetRequestId() string { @@ -11299,7 +11491,7 @@ type RechargeBillDailyBucket struct { func (x *RechargeBillDailyBucket) Reset() { *x = RechargeBillDailyBucket{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11311,7 +11503,7 @@ func (x *RechargeBillDailyBucket) String() string { func (*RechargeBillDailyBucket) ProtoMessage() {} func (x *RechargeBillDailyBucket) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11324,7 +11516,7 @@ func (x *RechargeBillDailyBucket) ProtoReflect() protoreflect.Message { // Deprecated: Use RechargeBillDailyBucket.ProtoReflect.Descriptor instead. func (*RechargeBillDailyBucket) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{121} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{124} } func (x *RechargeBillDailyBucket) GetDate() string { @@ -11388,7 +11580,7 @@ type RechargeBillRegionBucket struct { func (x *RechargeBillRegionBucket) Reset() { *x = RechargeBillRegionBucket{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11400,7 +11592,7 @@ func (x *RechargeBillRegionBucket) String() string { func (*RechargeBillRegionBucket) ProtoMessage() {} func (x *RechargeBillRegionBucket) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11413,7 +11605,7 @@ func (x *RechargeBillRegionBucket) ProtoReflect() protoreflect.Message { // Deprecated: Use RechargeBillRegionBucket.ProtoReflect.Descriptor instead. func (*RechargeBillRegionBucket) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{122} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{125} } func (x *RechargeBillRegionBucket) GetRegionId() int64 { @@ -11455,7 +11647,7 @@ type RechargeBillGooglePaidStats struct { func (x *RechargeBillGooglePaidStats) Reset() { *x = RechargeBillGooglePaidStats{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11467,7 +11659,7 @@ func (x *RechargeBillGooglePaidStats) String() string { func (*RechargeBillGooglePaidStats) ProtoMessage() {} func (x *RechargeBillGooglePaidStats) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11480,7 +11672,7 @@ func (x *RechargeBillGooglePaidStats) ProtoReflect() protoreflect.Message { // Deprecated: Use RechargeBillGooglePaidStats.ProtoReflect.Descriptor instead. func (*RechargeBillGooglePaidStats) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{123} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{126} } func (x *RechargeBillGooglePaidStats) GetGoogleBillCount() int64 { @@ -11545,7 +11737,7 @@ type RechargeBillSalaryTransferStats struct { func (x *RechargeBillSalaryTransferStats) Reset() { *x = RechargeBillSalaryTransferStats{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11557,7 +11749,7 @@ func (x *RechargeBillSalaryTransferStats) String() string { func (*RechargeBillSalaryTransferStats) ProtoMessage() {} func (x *RechargeBillSalaryTransferStats) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11570,7 +11762,7 @@ func (x *RechargeBillSalaryTransferStats) ProtoReflect() protoreflect.Message { // Deprecated: Use RechargeBillSalaryTransferStats.ProtoReflect.Descriptor instead. func (*RechargeBillSalaryTransferStats) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{124} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{127} } func (x *RechargeBillSalaryTransferStats) GetTransferCount() int64 { @@ -11600,7 +11792,7 @@ type GetRechargeBillOverviewResponse struct { func (x *GetRechargeBillOverviewResponse) Reset() { *x = GetRechargeBillOverviewResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11612,7 +11804,7 @@ func (x *GetRechargeBillOverviewResponse) String() string { func (*GetRechargeBillOverviewResponse) ProtoMessage() {} func (x *GetRechargeBillOverviewResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11625,7 +11817,7 @@ func (x *GetRechargeBillOverviewResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRechargeBillOverviewResponse.ProtoReflect.Descriptor instead. func (*GetRechargeBillOverviewResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{125} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{128} } func (x *GetRechargeBillOverviewResponse) GetDaily() []*RechargeBillDailyBucket { @@ -11668,7 +11860,7 @@ type RefreshGooglePaymentPricesRequest struct { func (x *RefreshGooglePaymentPricesRequest) Reset() { *x = RefreshGooglePaymentPricesRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11680,7 +11872,7 @@ func (x *RefreshGooglePaymentPricesRequest) String() string { func (*RefreshGooglePaymentPricesRequest) ProtoMessage() {} func (x *RefreshGooglePaymentPricesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11693,7 +11885,7 @@ func (x *RefreshGooglePaymentPricesRequest) ProtoReflect() protoreflect.Message // Deprecated: Use RefreshGooglePaymentPricesRequest.ProtoReflect.Descriptor instead. func (*RefreshGooglePaymentPricesRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{126} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{129} } func (x *RefreshGooglePaymentPricesRequest) GetRequestId() string { @@ -11733,7 +11925,7 @@ type GooglePaymentPrice struct { func (x *GooglePaymentPrice) Reset() { *x = GooglePaymentPrice{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11745,7 +11937,7 @@ func (x *GooglePaymentPrice) String() string { func (*GooglePaymentPrice) ProtoMessage() {} func (x *GooglePaymentPrice) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11758,7 +11950,7 @@ func (x *GooglePaymentPrice) ProtoReflect() protoreflect.Message { // Deprecated: Use GooglePaymentPrice.ProtoReflect.Descriptor instead. func (*GooglePaymentPrice) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{127} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{130} } func (x *GooglePaymentPrice) GetTransactionId() string { @@ -11820,7 +12012,7 @@ type RefreshGooglePaymentPricesResponse struct { func (x *RefreshGooglePaymentPricesResponse) Reset() { *x = RefreshGooglePaymentPricesResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11832,7 +12024,7 @@ func (x *RefreshGooglePaymentPricesResponse) String() string { func (*RefreshGooglePaymentPricesResponse) ProtoMessage() {} func (x *RefreshGooglePaymentPricesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11845,7 +12037,7 @@ func (x *RefreshGooglePaymentPricesResponse) ProtoReflect() protoreflect.Message // Deprecated: Use RefreshGooglePaymentPricesResponse.ProtoReflect.Descriptor instead. func (*RefreshGooglePaymentPricesResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{128} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{131} } func (x *RefreshGooglePaymentPricesResponse) GetPrices() []*GooglePaymentPrice { @@ -11867,7 +12059,7 @@ type WalletFeatureFlags struct { func (x *WalletFeatureFlags) Reset() { *x = WalletFeatureFlags{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11879,7 +12071,7 @@ func (x *WalletFeatureFlags) String() string { func (*WalletFeatureFlags) ProtoMessage() {} func (x *WalletFeatureFlags) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11892,7 +12084,7 @@ func (x *WalletFeatureFlags) ProtoReflect() protoreflect.Message { // Deprecated: Use WalletFeatureFlags.ProtoReflect.Descriptor instead. func (*WalletFeatureFlags) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{129} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{132} } func (x *WalletFeatureFlags) GetRechargeEnabled() bool { @@ -11921,7 +12113,7 @@ type GetWalletOverviewRequest struct { func (x *GetWalletOverviewRequest) Reset() { *x = GetWalletOverviewRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11933,7 +12125,7 @@ func (x *GetWalletOverviewRequest) String() string { func (*GetWalletOverviewRequest) ProtoMessage() {} func (x *GetWalletOverviewRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11946,7 +12138,7 @@ func (x *GetWalletOverviewRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWalletOverviewRequest.ProtoReflect.Descriptor instead. func (*GetWalletOverviewRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{130} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{133} } func (x *GetWalletOverviewRequest) GetRequestId() string { @@ -11981,7 +12173,7 @@ type GetWalletOverviewResponse struct { func (x *GetWalletOverviewResponse) Reset() { *x = GetWalletOverviewResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11993,7 +12185,7 @@ func (x *GetWalletOverviewResponse) String() string { func (*GetWalletOverviewResponse) ProtoMessage() {} func (x *GetWalletOverviewResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12006,7 +12198,7 @@ func (x *GetWalletOverviewResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWalletOverviewResponse.ProtoReflect.Descriptor instead. func (*GetWalletOverviewResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{131} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{134} } func (x *GetWalletOverviewResponse) GetBalances() []*AssetBalance { @@ -12035,7 +12227,7 @@ type WalletValueSummary struct { func (x *WalletValueSummary) Reset() { *x = WalletValueSummary{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12047,7 +12239,7 @@ func (x *WalletValueSummary) String() string { func (*WalletValueSummary) ProtoMessage() {} func (x *WalletValueSummary) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12060,7 +12252,7 @@ func (x *WalletValueSummary) ProtoReflect() protoreflect.Message { // Deprecated: Use WalletValueSummary.ProtoReflect.Descriptor instead. func (*WalletValueSummary) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{132} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{135} } func (x *WalletValueSummary) GetCoinAmount() int64 { @@ -12089,7 +12281,7 @@ type GetWalletValueSummaryRequest struct { func (x *GetWalletValueSummaryRequest) Reset() { *x = GetWalletValueSummaryRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12101,7 +12293,7 @@ func (x *GetWalletValueSummaryRequest) String() string { func (*GetWalletValueSummaryRequest) ProtoMessage() {} func (x *GetWalletValueSummaryRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12114,7 +12306,7 @@ func (x *GetWalletValueSummaryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWalletValueSummaryRequest.ProtoReflect.Descriptor instead. func (*GetWalletValueSummaryRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{133} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{136} } func (x *GetWalletValueSummaryRequest) GetRequestId() string { @@ -12148,7 +12340,7 @@ type GetWalletValueSummaryResponse struct { func (x *GetWalletValueSummaryResponse) Reset() { *x = GetWalletValueSummaryResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12160,7 +12352,7 @@ func (x *GetWalletValueSummaryResponse) String() string { func (*GetWalletValueSummaryResponse) ProtoMessage() {} func (x *GetWalletValueSummaryResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12173,7 +12365,7 @@ func (x *GetWalletValueSummaryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWalletValueSummaryResponse.ProtoReflect.Descriptor instead. func (*GetWalletValueSummaryResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{134} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{137} } func (x *GetWalletValueSummaryResponse) GetSummary() *WalletValueSummary { @@ -12212,7 +12404,7 @@ type GiftWallItem struct { func (x *GiftWallItem) Reset() { *x = GiftWallItem{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12224,7 +12416,7 @@ func (x *GiftWallItem) String() string { func (*GiftWallItem) ProtoMessage() {} func (x *GiftWallItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12237,7 +12429,7 @@ func (x *GiftWallItem) ProtoReflect() protoreflect.Message { // Deprecated: Use GiftWallItem.ProtoReflect.Descriptor instead. func (*GiftWallItem) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{135} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{138} } func (x *GiftWallItem) GetGiftId() string { @@ -12378,7 +12570,7 @@ type GetUserGiftWallRequest struct { func (x *GetUserGiftWallRequest) Reset() { *x = GetUserGiftWallRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12390,7 +12582,7 @@ func (x *GetUserGiftWallRequest) String() string { func (*GetUserGiftWallRequest) ProtoMessage() {} func (x *GetUserGiftWallRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12403,7 +12595,7 @@ func (x *GetUserGiftWallRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserGiftWallRequest.ProtoReflect.Descriptor instead. func (*GetUserGiftWallRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{136} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{139} } func (x *GetUserGiftWallRequest) GetRequestId() string { @@ -12445,7 +12637,7 @@ type GetUserGiftWallResponse struct { func (x *GetUserGiftWallResponse) Reset() { *x = GetUserGiftWallResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12457,7 +12649,7 @@ func (x *GetUserGiftWallResponse) String() string { func (*GetUserGiftWallResponse) ProtoMessage() {} func (x *GetUserGiftWallResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12470,7 +12662,7 @@ func (x *GetUserGiftWallResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserGiftWallResponse.ProtoReflect.Descriptor instead. func (*GetUserGiftWallResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{137} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{140} } func (x *GetUserGiftWallResponse) GetItems() []*GiftWallItem { @@ -12564,7 +12756,7 @@ type RechargeProduct struct { func (x *RechargeProduct) Reset() { *x = RechargeProduct{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12576,7 +12768,7 @@ func (x *RechargeProduct) String() string { func (*RechargeProduct) ProtoMessage() {} func (x *RechargeProduct) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12589,7 +12781,7 @@ func (x *RechargeProduct) ProtoReflect() protoreflect.Message { // Deprecated: Use RechargeProduct.ProtoReflect.Descriptor instead. func (*RechargeProduct) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{138} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{141} } func (x *RechargeProduct) GetProductId() int64 { @@ -12770,7 +12962,7 @@ type ListRechargeProductsRequest struct { func (x *ListRechargeProductsRequest) Reset() { *x = ListRechargeProductsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12782,7 +12974,7 @@ func (x *ListRechargeProductsRequest) String() string { func (*ListRechargeProductsRequest) ProtoMessage() {} func (x *ListRechargeProductsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12795,7 +12987,7 @@ func (x *ListRechargeProductsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRechargeProductsRequest.ProtoReflect.Descriptor instead. func (*ListRechargeProductsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{139} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{142} } func (x *ListRechargeProductsRequest) GetRequestId() string { @@ -12851,7 +13043,7 @@ type ListRechargeProductsResponse struct { func (x *ListRechargeProductsResponse) Reset() { *x = ListRechargeProductsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12863,7 +13055,7 @@ func (x *ListRechargeProductsResponse) String() string { func (*ListRechargeProductsResponse) ProtoMessage() {} func (x *ListRechargeProductsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12876,7 +13068,7 @@ func (x *ListRechargeProductsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRechargeProductsResponse.ProtoReflect.Descriptor instead. func (*ListRechargeProductsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{140} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{143} } func (x *ListRechargeProductsResponse) GetProducts() []*RechargeProduct { @@ -12915,7 +13107,7 @@ type ConfirmGooglePaymentRequest struct { func (x *ConfirmGooglePaymentRequest) Reset() { *x = ConfirmGooglePaymentRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12927,7 +13119,7 @@ func (x *ConfirmGooglePaymentRequest) String() string { func (*ConfirmGooglePaymentRequest) ProtoMessage() {} func (x *ConfirmGooglePaymentRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12940,7 +13132,7 @@ func (x *ConfirmGooglePaymentRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfirmGooglePaymentRequest.ProtoReflect.Descriptor instead. func (*ConfirmGooglePaymentRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{141} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{144} } func (x *ConfirmGooglePaymentRequest) GetRequestId() string { @@ -13045,7 +13237,7 @@ type ConfirmGooglePaymentResponse struct { func (x *ConfirmGooglePaymentResponse) Reset() { *x = ConfirmGooglePaymentResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13057,7 +13249,7 @@ func (x *ConfirmGooglePaymentResponse) String() string { func (*ConfirmGooglePaymentResponse) ProtoMessage() {} func (x *ConfirmGooglePaymentResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13070,7 +13262,7 @@ func (x *ConfirmGooglePaymentResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfirmGooglePaymentResponse.ProtoReflect.Descriptor instead. func (*ConfirmGooglePaymentResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{142} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{145} } func (x *ConfirmGooglePaymentResponse) GetPaymentOrderId() string { @@ -13155,7 +13347,7 @@ type ListAdminRechargeProductsRequest struct { func (x *ListAdminRechargeProductsRequest) Reset() { *x = ListAdminRechargeProductsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13167,7 +13359,7 @@ func (x *ListAdminRechargeProductsRequest) String() string { func (*ListAdminRechargeProductsRequest) ProtoMessage() {} func (x *ListAdminRechargeProductsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13180,7 +13372,7 @@ func (x *ListAdminRechargeProductsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAdminRechargeProductsRequest.ProtoReflect.Descriptor instead. func (*ListAdminRechargeProductsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{143} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{146} } func (x *ListAdminRechargeProductsRequest) GetRequestId() string { @@ -13257,7 +13449,7 @@ type ListAdminRechargeProductsResponse struct { func (x *ListAdminRechargeProductsResponse) Reset() { *x = ListAdminRechargeProductsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[147] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13269,7 +13461,7 @@ func (x *ListAdminRechargeProductsResponse) String() string { func (*ListAdminRechargeProductsResponse) ProtoMessage() {} func (x *ListAdminRechargeProductsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[147] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13282,7 +13474,7 @@ func (x *ListAdminRechargeProductsResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ListAdminRechargeProductsResponse.ProtoReflect.Descriptor instead. func (*ListAdminRechargeProductsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{144} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{147} } func (x *ListAdminRechargeProductsResponse) GetProducts() []*RechargeProduct { @@ -13322,7 +13514,7 @@ type CreateRechargeProductRequest struct { func (x *CreateRechargeProductRequest) Reset() { *x = CreateRechargeProductRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[148] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13334,7 +13526,7 @@ func (x *CreateRechargeProductRequest) String() string { func (*CreateRechargeProductRequest) ProtoMessage() {} func (x *CreateRechargeProductRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[148] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13347,7 +13539,7 @@ func (x *CreateRechargeProductRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRechargeProductRequest.ProtoReflect.Descriptor instead. func (*CreateRechargeProductRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{145} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{148} } func (x *CreateRechargeProductRequest) GetRequestId() string { @@ -13457,7 +13649,7 @@ type UpdateRechargeProductRequest struct { func (x *UpdateRechargeProductRequest) Reset() { *x = UpdateRechargeProductRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[149] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13469,7 +13661,7 @@ func (x *UpdateRechargeProductRequest) String() string { func (*UpdateRechargeProductRequest) ProtoMessage() {} func (x *UpdateRechargeProductRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[149] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13482,7 +13674,7 @@ func (x *UpdateRechargeProductRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRechargeProductRequest.ProtoReflect.Descriptor instead. func (*UpdateRechargeProductRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{146} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{149} } func (x *UpdateRechargeProductRequest) GetRequestId() string { @@ -13589,7 +13781,7 @@ type DeleteRechargeProductRequest struct { func (x *DeleteRechargeProductRequest) Reset() { *x = DeleteRechargeProductRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[147] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[150] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13601,7 +13793,7 @@ func (x *DeleteRechargeProductRequest) String() string { func (*DeleteRechargeProductRequest) ProtoMessage() {} func (x *DeleteRechargeProductRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[147] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[150] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13614,7 +13806,7 @@ func (x *DeleteRechargeProductRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteRechargeProductRequest.ProtoReflect.Descriptor instead. func (*DeleteRechargeProductRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{147} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{150} } func (x *DeleteRechargeProductRequest) GetRequestId() string { @@ -13655,7 +13847,7 @@ type RechargeProductResponse struct { func (x *RechargeProductResponse) Reset() { *x = RechargeProductResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[148] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[151] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13667,7 +13859,7 @@ func (x *RechargeProductResponse) String() string { func (*RechargeProductResponse) ProtoMessage() {} func (x *RechargeProductResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[148] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[151] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13680,7 +13872,7 @@ func (x *RechargeProductResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RechargeProductResponse.ProtoReflect.Descriptor instead. func (*RechargeProductResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{148} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{151} } func (x *RechargeProductResponse) GetProduct() *RechargeProduct { @@ -13700,7 +13892,7 @@ type DeleteRechargeProductResponse struct { func (x *DeleteRechargeProductResponse) Reset() { *x = DeleteRechargeProductResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[149] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[152] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13712,7 +13904,7 @@ func (x *DeleteRechargeProductResponse) String() string { func (*DeleteRechargeProductResponse) ProtoMessage() {} func (x *DeleteRechargeProductResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[149] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[152] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13725,7 +13917,7 @@ func (x *DeleteRechargeProductResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteRechargeProductResponse.ProtoReflect.Descriptor instead. func (*DeleteRechargeProductResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{149} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{152} } func (x *DeleteRechargeProductResponse) GetDeleted() bool { @@ -13761,7 +13953,7 @@ type ThirdPartyPaymentMethod struct { func (x *ThirdPartyPaymentMethod) Reset() { *x = ThirdPartyPaymentMethod{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[150] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[153] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13773,7 +13965,7 @@ func (x *ThirdPartyPaymentMethod) String() string { func (*ThirdPartyPaymentMethod) ProtoMessage() {} func (x *ThirdPartyPaymentMethod) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[150] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[153] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13786,7 +13978,7 @@ func (x *ThirdPartyPaymentMethod) ProtoReflect() protoreflect.Message { // Deprecated: Use ThirdPartyPaymentMethod.ProtoReflect.Descriptor instead. func (*ThirdPartyPaymentMethod) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{150} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{153} } func (x *ThirdPartyPaymentMethod) GetMethodId() int64 { @@ -13916,7 +14108,7 @@ type ThirdPartyPaymentChannel struct { func (x *ThirdPartyPaymentChannel) Reset() { *x = ThirdPartyPaymentChannel{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[151] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[154] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13928,7 +14120,7 @@ func (x *ThirdPartyPaymentChannel) String() string { func (*ThirdPartyPaymentChannel) ProtoMessage() {} func (x *ThirdPartyPaymentChannel) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[151] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[154] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13941,7 +14133,7 @@ func (x *ThirdPartyPaymentChannel) ProtoReflect() protoreflect.Message { // Deprecated: Use ThirdPartyPaymentChannel.ProtoReflect.Descriptor instead. func (*ThirdPartyPaymentChannel) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{151} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{154} } func (x *ThirdPartyPaymentChannel) GetAppCode() string { @@ -14000,7 +14192,7 @@ type ListThirdPartyPaymentChannelsRequest struct { func (x *ListThirdPartyPaymentChannelsRequest) Reset() { *x = ListThirdPartyPaymentChannelsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[152] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[155] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14012,7 +14204,7 @@ func (x *ListThirdPartyPaymentChannelsRequest) String() string { func (*ListThirdPartyPaymentChannelsRequest) ProtoMessage() {} func (x *ListThirdPartyPaymentChannelsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[152] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[155] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14025,7 +14217,7 @@ func (x *ListThirdPartyPaymentChannelsRequest) ProtoReflect() protoreflect.Messa // Deprecated: Use ListThirdPartyPaymentChannelsRequest.ProtoReflect.Descriptor instead. func (*ListThirdPartyPaymentChannelsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{152} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{155} } func (x *ListThirdPartyPaymentChannelsRequest) GetRequestId() string { @@ -14073,7 +14265,7 @@ type ListThirdPartyPaymentChannelsResponse struct { func (x *ListThirdPartyPaymentChannelsResponse) Reset() { *x = ListThirdPartyPaymentChannelsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[153] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[156] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14085,7 +14277,7 @@ func (x *ListThirdPartyPaymentChannelsResponse) String() string { func (*ListThirdPartyPaymentChannelsResponse) ProtoMessage() {} func (x *ListThirdPartyPaymentChannelsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[153] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[156] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14098,7 +14290,7 @@ func (x *ListThirdPartyPaymentChannelsResponse) ProtoReflect() protoreflect.Mess // Deprecated: Use ListThirdPartyPaymentChannelsResponse.ProtoReflect.Descriptor instead. func (*ListThirdPartyPaymentChannelsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{153} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{156} } func (x *ListThirdPartyPaymentChannelsResponse) GetChannels() []*ThirdPartyPaymentChannel { @@ -14122,7 +14314,7 @@ type SetThirdPartyPaymentMethodStatusRequest struct { func (x *SetThirdPartyPaymentMethodStatusRequest) Reset() { *x = SetThirdPartyPaymentMethodStatusRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[154] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[157] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14134,7 +14326,7 @@ func (x *SetThirdPartyPaymentMethodStatusRequest) String() string { func (*SetThirdPartyPaymentMethodStatusRequest) ProtoMessage() {} func (x *SetThirdPartyPaymentMethodStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[154] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[157] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14147,7 +14339,7 @@ func (x *SetThirdPartyPaymentMethodStatusRequest) ProtoReflect() protoreflect.Me // Deprecated: Use SetThirdPartyPaymentMethodStatusRequest.ProtoReflect.Descriptor instead. func (*SetThirdPartyPaymentMethodStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{154} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{157} } func (x *SetThirdPartyPaymentMethodStatusRequest) GetRequestId() string { @@ -14195,7 +14387,7 @@ type ThirdPartyPaymentMethodResponse struct { func (x *ThirdPartyPaymentMethodResponse) Reset() { *x = ThirdPartyPaymentMethodResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[155] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[158] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14207,7 +14399,7 @@ func (x *ThirdPartyPaymentMethodResponse) String() string { func (*ThirdPartyPaymentMethodResponse) ProtoMessage() {} func (x *ThirdPartyPaymentMethodResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[155] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[158] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14220,7 +14412,7 @@ func (x *ThirdPartyPaymentMethodResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ThirdPartyPaymentMethodResponse.ProtoReflect.Descriptor instead. func (*ThirdPartyPaymentMethodResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{155} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{158} } func (x *ThirdPartyPaymentMethodResponse) GetMethod() *ThirdPartyPaymentMethod { @@ -14244,7 +14436,7 @@ type UpdateThirdPartyPaymentRateRequest struct { func (x *UpdateThirdPartyPaymentRateRequest) Reset() { *x = UpdateThirdPartyPaymentRateRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[156] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[159] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14256,7 +14448,7 @@ func (x *UpdateThirdPartyPaymentRateRequest) String() string { func (*UpdateThirdPartyPaymentRateRequest) ProtoMessage() {} func (x *UpdateThirdPartyPaymentRateRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[156] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[159] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14269,7 +14461,7 @@ func (x *UpdateThirdPartyPaymentRateRequest) ProtoReflect() protoreflect.Message // Deprecated: Use UpdateThirdPartyPaymentRateRequest.ProtoReflect.Descriptor instead. func (*UpdateThirdPartyPaymentRateRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{156} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{159} } func (x *UpdateThirdPartyPaymentRateRequest) GetRequestId() string { @@ -14320,7 +14512,7 @@ type ThirdPartyPaymentMethodSyncIssue struct { func (x *ThirdPartyPaymentMethodSyncIssue) Reset() { *x = ThirdPartyPaymentMethodSyncIssue{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[157] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[160] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14332,7 +14524,7 @@ func (x *ThirdPartyPaymentMethodSyncIssue) String() string { func (*ThirdPartyPaymentMethodSyncIssue) ProtoMessage() {} func (x *ThirdPartyPaymentMethodSyncIssue) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[157] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[160] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14345,7 +14537,7 @@ func (x *ThirdPartyPaymentMethodSyncIssue) ProtoReflect() protoreflect.Message { // Deprecated: Use ThirdPartyPaymentMethodSyncIssue.ProtoReflect.Descriptor instead. func (*ThirdPartyPaymentMethodSyncIssue) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{157} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{160} } func (x *ThirdPartyPaymentMethodSyncIssue) GetCountryCode() string { @@ -14389,7 +14581,7 @@ type SyncThirdPartyPaymentMethodsRequest struct { func (x *SyncThirdPartyPaymentMethodsRequest) Reset() { *x = SyncThirdPartyPaymentMethodsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[158] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[161] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14401,7 +14593,7 @@ func (x *SyncThirdPartyPaymentMethodsRequest) String() string { func (*SyncThirdPartyPaymentMethodsRequest) ProtoMessage() {} func (x *SyncThirdPartyPaymentMethodsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[158] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[161] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14414,7 +14606,7 @@ func (x *SyncThirdPartyPaymentMethodsRequest) ProtoReflect() protoreflect.Messag // Deprecated: Use SyncThirdPartyPaymentMethodsRequest.ProtoReflect.Descriptor instead. func (*SyncThirdPartyPaymentMethodsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{158} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{161} } func (x *SyncThirdPartyPaymentMethodsRequest) GetRequestId() string { @@ -14461,7 +14653,7 @@ type SyncThirdPartyPaymentMethodsResponse struct { func (x *SyncThirdPartyPaymentMethodsResponse) Reset() { *x = SyncThirdPartyPaymentMethodsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[159] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[162] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14473,7 +14665,7 @@ func (x *SyncThirdPartyPaymentMethodsResponse) String() string { func (*SyncThirdPartyPaymentMethodsResponse) ProtoMessage() {} func (x *SyncThirdPartyPaymentMethodsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[159] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[162] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14486,7 +14678,7 @@ func (x *SyncThirdPartyPaymentMethodsResponse) ProtoReflect() protoreflect.Messa // Deprecated: Use SyncThirdPartyPaymentMethodsResponse.ProtoReflect.Descriptor instead. func (*SyncThirdPartyPaymentMethodsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{159} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{162} } func (x *SyncThirdPartyPaymentMethodsResponse) GetProviderCode() string { @@ -14553,7 +14745,7 @@ type H5RechargeOptionsRequest struct { func (x *H5RechargeOptionsRequest) Reset() { *x = H5RechargeOptionsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[160] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[163] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14565,7 +14757,7 @@ func (x *H5RechargeOptionsRequest) String() string { func (*H5RechargeOptionsRequest) ProtoMessage() {} func (x *H5RechargeOptionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[160] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[163] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14578,7 +14770,7 @@ func (x *H5RechargeOptionsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use H5RechargeOptionsRequest.ProtoReflect.Descriptor instead. func (*H5RechargeOptionsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{160} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{163} } func (x *H5RechargeOptionsRequest) GetRequestId() string { @@ -14636,7 +14828,7 @@ type H5RechargeOptionsResponse struct { func (x *H5RechargeOptionsResponse) Reset() { *x = H5RechargeOptionsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[161] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[164] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14648,7 +14840,7 @@ func (x *H5RechargeOptionsResponse) String() string { func (*H5RechargeOptionsResponse) ProtoMessage() {} func (x *H5RechargeOptionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[161] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[164] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14661,7 +14853,7 @@ func (x *H5RechargeOptionsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use H5RechargeOptionsResponse.ProtoReflect.Descriptor instead. func (*H5RechargeOptionsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{161} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{164} } func (x *H5RechargeOptionsResponse) GetProducts() []*RechargeProduct { @@ -14730,7 +14922,7 @@ type ExternalRechargeOrder struct { func (x *ExternalRechargeOrder) Reset() { *x = ExternalRechargeOrder{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[162] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[165] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14742,7 +14934,7 @@ func (x *ExternalRechargeOrder) String() string { func (*ExternalRechargeOrder) ProtoMessage() {} func (x *ExternalRechargeOrder) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[162] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[165] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14755,7 +14947,7 @@ func (x *ExternalRechargeOrder) ProtoReflect() protoreflect.Message { // Deprecated: Use ExternalRechargeOrder.ProtoReflect.Descriptor instead. func (*ExternalRechargeOrder) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{162} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{165} } func (x *ExternalRechargeOrder) GetOrderId() string { @@ -14983,7 +15175,7 @@ type CreateH5RechargeOrderRequest struct { func (x *CreateH5RechargeOrderRequest) Reset() { *x = CreateH5RechargeOrderRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[163] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[166] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14995,7 +15187,7 @@ func (x *CreateH5RechargeOrderRequest) String() string { func (*CreateH5RechargeOrderRequest) ProtoMessage() {} func (x *CreateH5RechargeOrderRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[163] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[166] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15008,7 +15200,7 @@ func (x *CreateH5RechargeOrderRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateH5RechargeOrderRequest.ProtoReflect.Descriptor instead. func (*CreateH5RechargeOrderRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{163} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{166} } func (x *CreateH5RechargeOrderRequest) GetRequestId() string { @@ -15160,7 +15352,7 @@ type CreateTemporaryRechargeOrderRequest struct { func (x *CreateTemporaryRechargeOrderRequest) Reset() { *x = CreateTemporaryRechargeOrderRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[164] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[167] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15172,7 +15364,7 @@ func (x *CreateTemporaryRechargeOrderRequest) String() string { func (*CreateTemporaryRechargeOrderRequest) ProtoMessage() {} func (x *CreateTemporaryRechargeOrderRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[164] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[167] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15185,7 +15377,7 @@ func (x *CreateTemporaryRechargeOrderRequest) ProtoReflect() protoreflect.Messag // Deprecated: Use CreateTemporaryRechargeOrderRequest.ProtoReflect.Descriptor instead. func (*CreateTemporaryRechargeOrderRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{164} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{167} } func (x *CreateTemporaryRechargeOrderRequest) GetRequestId() string { @@ -15298,7 +15490,7 @@ type GetTemporaryRechargeOrderRequest struct { func (x *GetTemporaryRechargeOrderRequest) Reset() { *x = GetTemporaryRechargeOrderRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[165] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[168] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15310,7 +15502,7 @@ func (x *GetTemporaryRechargeOrderRequest) String() string { func (*GetTemporaryRechargeOrderRequest) ProtoMessage() {} func (x *GetTemporaryRechargeOrderRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[165] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[168] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15323,7 +15515,7 @@ func (x *GetTemporaryRechargeOrderRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetTemporaryRechargeOrderRequest.ProtoReflect.Descriptor instead. func (*GetTemporaryRechargeOrderRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{165} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{168} } func (x *GetTemporaryRechargeOrderRequest) GetRequestId() string { @@ -15363,7 +15555,7 @@ type ListTemporaryRechargeOrdersRequest struct { func (x *ListTemporaryRechargeOrdersRequest) Reset() { *x = ListTemporaryRechargeOrdersRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[166] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[169] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15375,7 +15567,7 @@ func (x *ListTemporaryRechargeOrdersRequest) String() string { func (*ListTemporaryRechargeOrdersRequest) ProtoMessage() {} func (x *ListTemporaryRechargeOrdersRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[166] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[169] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15388,7 +15580,7 @@ func (x *ListTemporaryRechargeOrdersRequest) ProtoReflect() protoreflect.Message // Deprecated: Use ListTemporaryRechargeOrdersRequest.ProtoReflect.Descriptor instead. func (*ListTemporaryRechargeOrdersRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{166} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{169} } func (x *ListTemporaryRechargeOrdersRequest) GetRequestId() string { @@ -15451,7 +15643,7 @@ type ListTemporaryRechargeOrdersResponse struct { func (x *ListTemporaryRechargeOrdersResponse) Reset() { *x = ListTemporaryRechargeOrdersResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[167] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[170] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15463,7 +15655,7 @@ func (x *ListTemporaryRechargeOrdersResponse) String() string { func (*ListTemporaryRechargeOrdersResponse) ProtoMessage() {} func (x *ListTemporaryRechargeOrdersResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[167] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[170] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15476,7 +15668,7 @@ func (x *ListTemporaryRechargeOrdersResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use ListTemporaryRechargeOrdersResponse.ProtoReflect.Descriptor instead. func (*ListTemporaryRechargeOrdersResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{167} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{170} } func (x *ListTemporaryRechargeOrdersResponse) GetOrders() []*ExternalRechargeOrder { @@ -15507,7 +15699,7 @@ type SubmitH5RechargeTxRequest struct { func (x *SubmitH5RechargeTxRequest) Reset() { *x = SubmitH5RechargeTxRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[168] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[171] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15519,7 +15711,7 @@ func (x *SubmitH5RechargeTxRequest) String() string { func (*SubmitH5RechargeTxRequest) ProtoMessage() {} func (x *SubmitH5RechargeTxRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[168] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[171] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15532,7 +15724,7 @@ func (x *SubmitH5RechargeTxRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitH5RechargeTxRequest.ProtoReflect.Descriptor instead. func (*SubmitH5RechargeTxRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{168} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{171} } func (x *SubmitH5RechargeTxRequest) GetRequestId() string { @@ -15583,7 +15775,7 @@ type GetH5RechargeOrderRequest struct { func (x *GetH5RechargeOrderRequest) Reset() { *x = GetH5RechargeOrderRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[169] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[172] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15595,7 +15787,7 @@ func (x *GetH5RechargeOrderRequest) String() string { func (*GetH5RechargeOrderRequest) ProtoMessage() {} func (x *GetH5RechargeOrderRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[169] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[172] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15608,7 +15800,7 @@ func (x *GetH5RechargeOrderRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetH5RechargeOrderRequest.ProtoReflect.Descriptor instead. func (*GetH5RechargeOrderRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{169} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{172} } func (x *GetH5RechargeOrderRequest) GetRequestId() string { @@ -15649,7 +15841,7 @@ type H5RechargeOrderResponse struct { func (x *H5RechargeOrderResponse) Reset() { *x = H5RechargeOrderResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[170] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[173] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15661,7 +15853,7 @@ func (x *H5RechargeOrderResponse) String() string { func (*H5RechargeOrderResponse) ProtoMessage() {} func (x *H5RechargeOrderResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[170] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[173] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15674,7 +15866,7 @@ func (x *H5RechargeOrderResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use H5RechargeOrderResponse.ProtoReflect.Descriptor instead. func (*H5RechargeOrderResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{170} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{173} } func (x *H5RechargeOrderResponse) GetOrder() *ExternalRechargeOrder { @@ -15704,7 +15896,7 @@ type VerifyCoinSellerRechargeReceiptRequest struct { func (x *VerifyCoinSellerRechargeReceiptRequest) Reset() { *x = VerifyCoinSellerRechargeReceiptRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[171] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[174] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15716,7 +15908,7 @@ func (x *VerifyCoinSellerRechargeReceiptRequest) String() string { func (*VerifyCoinSellerRechargeReceiptRequest) ProtoMessage() {} func (x *VerifyCoinSellerRechargeReceiptRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[171] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[174] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15729,7 +15921,7 @@ func (x *VerifyCoinSellerRechargeReceiptRequest) ProtoReflect() protoreflect.Mes // Deprecated: Use VerifyCoinSellerRechargeReceiptRequest.ProtoReflect.Descriptor instead. func (*VerifyCoinSellerRechargeReceiptRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{171} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{174} } func (x *VerifyCoinSellerRechargeReceiptRequest) GetRequestId() string { @@ -15830,7 +16022,7 @@ type VerifyCoinSellerRechargeReceiptResponse struct { func (x *VerifyCoinSellerRechargeReceiptResponse) Reset() { *x = VerifyCoinSellerRechargeReceiptResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[172] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[175] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15842,7 +16034,7 @@ func (x *VerifyCoinSellerRechargeReceiptResponse) String() string { func (*VerifyCoinSellerRechargeReceiptResponse) ProtoMessage() {} func (x *VerifyCoinSellerRechargeReceiptResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[172] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[175] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15855,7 +16047,7 @@ func (x *VerifyCoinSellerRechargeReceiptResponse) ProtoReflect() protoreflect.Me // Deprecated: Use VerifyCoinSellerRechargeReceiptResponse.ProtoReflect.Descriptor instead. func (*VerifyCoinSellerRechargeReceiptResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{172} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{175} } func (x *VerifyCoinSellerRechargeReceiptResponse) GetVerified() bool { @@ -15956,7 +16148,7 @@ type HandleMifapayNotifyRequest struct { func (x *HandleMifapayNotifyRequest) Reset() { *x = HandleMifapayNotifyRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[173] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[176] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15968,7 +16160,7 @@ func (x *HandleMifapayNotifyRequest) String() string { func (*HandleMifapayNotifyRequest) ProtoMessage() {} func (x *HandleMifapayNotifyRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[173] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[176] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15981,7 +16173,7 @@ func (x *HandleMifapayNotifyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use HandleMifapayNotifyRequest.ProtoReflect.Descriptor instead. func (*HandleMifapayNotifyRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{173} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{176} } func (x *HandleMifapayNotifyRequest) GetRequestId() string { @@ -16031,7 +16223,7 @@ type HandleMifapayNotifyResponse struct { func (x *HandleMifapayNotifyResponse) Reset() { *x = HandleMifapayNotifyResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[174] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[177] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16043,7 +16235,7 @@ func (x *HandleMifapayNotifyResponse) String() string { func (*HandleMifapayNotifyResponse) ProtoMessage() {} func (x *HandleMifapayNotifyResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[174] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[177] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16056,7 +16248,7 @@ func (x *HandleMifapayNotifyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use HandleMifapayNotifyResponse.ProtoReflect.Descriptor instead. func (*HandleMifapayNotifyResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{174} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{177} } func (x *HandleMifapayNotifyResponse) GetAccepted() bool { @@ -16093,7 +16285,7 @@ type HandleV5PayNotifyRequest struct { func (x *HandleV5PayNotifyRequest) Reset() { *x = HandleV5PayNotifyRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[175] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[178] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16105,7 +16297,7 @@ func (x *HandleV5PayNotifyRequest) String() string { func (*HandleV5PayNotifyRequest) ProtoMessage() {} func (x *HandleV5PayNotifyRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[175] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[178] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16118,7 +16310,7 @@ func (x *HandleV5PayNotifyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use HandleV5PayNotifyRequest.ProtoReflect.Descriptor instead. func (*HandleV5PayNotifyRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{175} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{178} } func (x *HandleV5PayNotifyRequest) GetRequestId() string { @@ -16161,7 +16353,7 @@ type HandleV5PayNotifyResponse struct { func (x *HandleV5PayNotifyResponse) Reset() { *x = HandleV5PayNotifyResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[176] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[179] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16173,7 +16365,7 @@ func (x *HandleV5PayNotifyResponse) String() string { func (*HandleV5PayNotifyResponse) ProtoMessage() {} func (x *HandleV5PayNotifyResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[176] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[179] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16186,7 +16378,7 @@ func (x *HandleV5PayNotifyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use HandleV5PayNotifyResponse.ProtoReflect.Descriptor instead. func (*HandleV5PayNotifyResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{176} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{179} } func (x *HandleV5PayNotifyResponse) GetAccepted() bool { @@ -16225,7 +16417,7 @@ type DiamondExchangeRule struct { func (x *DiamondExchangeRule) Reset() { *x = DiamondExchangeRule{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[177] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[180] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16237,7 +16429,7 @@ func (x *DiamondExchangeRule) String() string { func (*DiamondExchangeRule) ProtoMessage() {} func (x *DiamondExchangeRule) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[177] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[180] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16250,7 +16442,7 @@ func (x *DiamondExchangeRule) ProtoReflect() protoreflect.Message { // Deprecated: Use DiamondExchangeRule.ProtoReflect.Descriptor instead. func (*DiamondExchangeRule) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{177} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{180} } func (x *DiamondExchangeRule) GetExchangeType() string { @@ -16307,7 +16499,7 @@ type GetDiamondExchangeConfigRequest struct { func (x *GetDiamondExchangeConfigRequest) Reset() { *x = GetDiamondExchangeConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[178] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[181] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16319,7 +16511,7 @@ func (x *GetDiamondExchangeConfigRequest) String() string { func (*GetDiamondExchangeConfigRequest) ProtoMessage() {} func (x *GetDiamondExchangeConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[178] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[181] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16332,7 +16524,7 @@ func (x *GetDiamondExchangeConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDiamondExchangeConfigRequest.ProtoReflect.Descriptor instead. func (*GetDiamondExchangeConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{178} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{181} } func (x *GetDiamondExchangeConfigRequest) GetRequestId() string { @@ -16366,7 +16558,7 @@ type GetDiamondExchangeConfigResponse struct { func (x *GetDiamondExchangeConfigResponse) Reset() { *x = GetDiamondExchangeConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[179] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[182] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16378,7 +16570,7 @@ func (x *GetDiamondExchangeConfigResponse) String() string { func (*GetDiamondExchangeConfigResponse) ProtoMessage() {} func (x *GetDiamondExchangeConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[179] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[182] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16391,7 +16583,7 @@ func (x *GetDiamondExchangeConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDiamondExchangeConfigResponse.ProtoReflect.Descriptor instead. func (*GetDiamondExchangeConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{179} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{182} } func (x *GetDiamondExchangeConfigResponse) GetRules() []*DiamondExchangeRule { @@ -16424,7 +16616,7 @@ type WalletTransaction struct { func (x *WalletTransaction) Reset() { *x = WalletTransaction{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[180] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[183] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16436,7 +16628,7 @@ func (x *WalletTransaction) String() string { func (*WalletTransaction) ProtoMessage() {} func (x *WalletTransaction) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[180] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[183] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16449,7 +16641,7 @@ func (x *WalletTransaction) ProtoReflect() protoreflect.Message { // Deprecated: Use WalletTransaction.ProtoReflect.Descriptor instead. func (*WalletTransaction) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{180} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{183} } func (x *WalletTransaction) GetEntryId() int64 { @@ -16558,7 +16750,7 @@ type ListWalletTransactionsRequest struct { func (x *ListWalletTransactionsRequest) Reset() { *x = ListWalletTransactionsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[181] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[184] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16570,7 +16762,7 @@ func (x *ListWalletTransactionsRequest) String() string { func (*ListWalletTransactionsRequest) ProtoMessage() {} func (x *ListWalletTransactionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[181] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[184] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16583,7 +16775,7 @@ func (x *ListWalletTransactionsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWalletTransactionsRequest.ProtoReflect.Descriptor instead. func (*ListWalletTransactionsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{181} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{184} } func (x *ListWalletTransactionsRequest) GetRequestId() string { @@ -16639,7 +16831,7 @@ type ListWalletTransactionsResponse struct { func (x *ListWalletTransactionsResponse) Reset() { *x = ListWalletTransactionsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[182] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[185] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16651,7 +16843,7 @@ func (x *ListWalletTransactionsResponse) String() string { func (*ListWalletTransactionsResponse) ProtoMessage() {} func (x *ListWalletTransactionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[182] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[185] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16664,7 +16856,7 @@ func (x *ListWalletTransactionsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWalletTransactionsResponse.ProtoReflect.Descriptor instead. func (*ListWalletTransactionsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{182} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{185} } func (x *ListWalletTransactionsResponse) GetTransactions() []*WalletTransaction { @@ -16699,7 +16891,7 @@ type VipRewardItem struct { func (x *VipRewardItem) Reset() { *x = VipRewardItem{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[183] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[186] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16711,7 +16903,7 @@ func (x *VipRewardItem) String() string { func (*VipRewardItem) ProtoMessage() {} func (x *VipRewardItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[183] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[186] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16724,7 +16916,7 @@ func (x *VipRewardItem) ProtoReflect() protoreflect.Message { // Deprecated: Use VipRewardItem.ProtoReflect.Descriptor instead. func (*VipRewardItem) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{183} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{186} } func (x *VipRewardItem) GetResourceId() int64 { @@ -16790,6 +16982,318 @@ func (x *VipRewardItem) GetAnimationUrl() string { return "" } +// 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"` + // 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"` + // same_level_expiry_policy: extend_remaining;同级购买从当前有效截止时间续期。 + SameLevelExpiryPolicy string `protobuf:"bytes,4,opt,name=same_level_expiry_policy,json=sameLevelExpiryPolicy,proto3" json:"same_level_expiry_policy,omitempty"` + // upgrade_expiry_policy: extend_remaining/replace_from_now。 + UpgradeExpiryPolicy string `protobuf:"bytes,5,opt,name=upgrade_expiry_policy,json=upgradeExpiryPolicy,proto3" json:"upgrade_expiry_policy,omitempty"` + // downgrade_purchase_policy 首版固定 reject,保留字段用于后台完整展示当前规则。 + DowngradePurchasePolicy string `protobuf:"bytes,6,opt,name=downgrade_purchase_policy,json=downgradePurchasePolicy,proto3" json:"downgrade_purchase_policy,omitempty"` + // benefit_inheritance_policy 当前固定 target_only;每级提交最终完整集合,不做自动继承。 + BenefitInheritancePolicy string `protobuf:"bytes,7,opt,name=benefit_inheritance_policy,json=benefitInheritancePolicy,proto3" json:"benefit_inheritance_policy,omitempty"` + // grant_mode: direct_membership/trial_card,决定后台“赠送 VIP”的真实账务对象。 + GrantMode string `protobuf:"bytes,8,opt,name=grant_mode,json=grantMode,proto3" json:"grant_mode,omitempty"` + TrialCardEnabled bool `protobuf:"varint,9,opt,name=trial_card_enabled,json=trialCardEnabled,proto3" json:"trial_card_enabled,omitempty"` + Status string `protobuf:"bytes,10,opt,name=status,proto3" json:"status,omitempty"` + ConfigVersion int64 `protobuf:"varint,11,opt,name=config_version,json=configVersion,proto3" json:"config_version,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"` +} + +func (x *VipProgramConfig) Reset() { + *x = VipProgramConfig{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[187] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VipProgramConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VipProgramConfig) ProtoMessage() {} + +func (x *VipProgramConfig) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[187] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VipProgramConfig.ProtoReflect.Descriptor instead. +func (*VipProgramConfig) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{187} +} + +func (x *VipProgramConfig) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *VipProgramConfig) GetProgramType() string { + if x != nil { + return x.ProgramType + } + return "" +} + +func (x *VipProgramConfig) GetLevelCount() int32 { + if x != nil { + return x.LevelCount + } + return 0 +} + +func (x *VipProgramConfig) GetSameLevelExpiryPolicy() string { + if x != nil { + return x.SameLevelExpiryPolicy + } + return "" +} + +func (x *VipProgramConfig) GetUpgradeExpiryPolicy() string { + if x != nil { + return x.UpgradeExpiryPolicy + } + return "" +} + +func (x *VipProgramConfig) GetDowngradePurchasePolicy() string { + if x != nil { + return x.DowngradePurchasePolicy + } + return "" +} + +func (x *VipProgramConfig) GetBenefitInheritancePolicy() string { + if x != nil { + return x.BenefitInheritancePolicy + } + return "" +} + +func (x *VipProgramConfig) GetGrantMode() string { + if x != nil { + return x.GrantMode + } + return "" +} + +func (x *VipProgramConfig) GetTrialCardEnabled() bool { + if x != nil { + return x.TrialCardEnabled + } + return false +} + +func (x *VipProgramConfig) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *VipProgramConfig) GetConfigVersion() int64 { + if x != nil { + return x.ConfigVersion + } + return 0 +} + +func (x *VipProgramConfig) GetUpdatedByAdminId() int64 { + if x != nil { + return x.UpdatedByAdminId + } + return 0 +} + +func (x *VipProgramConfig) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *VipProgramConfig) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +// 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"` + // benefit_type: decoration/function。 + BenefitType string `protobuf:"bytes,3,opt,name=benefit_type,json=benefitType,proto3" json:"benefit_type,omitempty"` + // unlock_level 只作为 P1 默认矩阵的来源信息;后台仍按每个等级提交完整权益集合, + // 运行时不得据此自动补齐高等级权益。 + UnlockLevel int32 `protobuf:"varint,4,opt,name=unlock_level,json=unlockLevel,proto3" json:"unlock_level,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + TrialEnabled bool `protobuf:"varint,6,opt,name=trial_enabled,json=trialEnabled,proto3" json:"trial_enabled,omitempty"` + 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"` +} + +func (x *VipBenefit) Reset() { + *x = VipBenefit{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[188] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VipBenefit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VipBenefit) ProtoMessage() {} + +func (x *VipBenefit) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[188] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VipBenefit.ProtoReflect.Descriptor instead. +func (*VipBenefit) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{188} +} + +func (x *VipBenefit) GetBenefitCode() string { + if x != nil { + return x.BenefitCode + } + return "" +} + +func (x *VipBenefit) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *VipBenefit) GetBenefitType() string { + if x != nil { + return x.BenefitType + } + return "" +} + +func (x *VipBenefit) GetUnlockLevel() int32 { + if x != nil { + return x.UnlockLevel + } + return 0 +} + +func (x *VipBenefit) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *VipBenefit) GetTrialEnabled() bool { + if x != nil { + return x.TrialEnabled + } + return false +} + +func (x *VipBenefit) GetResourceId() int64 { + if x != nil { + return x.ResourceId + } + return 0 +} + +func (x *VipBenefit) GetResourceType() string { + if x != nil { + return x.ResourceType + } + return "" +} + +func (x *VipBenefit) GetExecutionScope() string { + if x != nil { + return x.ExecutionScope + } + return "" +} + +func (x *VipBenefit) GetAutoEquip() bool { + if x != nil { + return x.AutoEquip + } + return false +} + +func (x *VipBenefit) GetSortOrder() int32 { + if x != nil { + return x.SortOrder + } + return 0 +} + +func (x *VipBenefit) GetMetadataJson() string { + if x != nil { + return x.MetadataJson + } + return "" +} + +func (x *VipBenefit) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *VipBenefit) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + type VipLevel struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -16810,11 +17314,14 @@ type VipLevel struct { 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"` } func (x *VipLevel) Reset() { *x = VipLevel{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[184] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[189] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16826,7 +17333,7 @@ func (x *VipLevel) String() string { func (*VipLevel) ProtoMessage() {} func (x *VipLevel) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[184] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[189] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16839,7 +17346,7 @@ func (x *VipLevel) ProtoReflect() protoreflect.Message { // Deprecated: Use VipLevel.ProtoReflect.Descriptor instead. func (*VipLevel) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{184} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{189} } func (x *VipLevel) GetLevel() int32 { @@ -16947,23 +17454,39 @@ func (x *VipLevel) GetUpdatedAtMs() int64 { return 0 } +func (x *VipLevel) GetBenefits() []*VipBenefit { + if x != nil { + return x.Benefits + } + return nil +} + +func (x *VipLevel) GetConfigVersion() int64 { + if x != nil { + return x.ConfigVersion + } + return 0 +} + type UserVip 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"` - 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"` + 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"` } func (x *UserVip) Reset() { *x = UserVip{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[185] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[190] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16975,7 +17498,7 @@ func (x *UserVip) String() string { func (*UserVip) ProtoMessage() {} func (x *UserVip) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[185] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[190] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16988,7 +17511,7 @@ func (x *UserVip) ProtoReflect() protoreflect.Message { // Deprecated: Use UserVip.ProtoReflect.Descriptor instead. func (*UserVip) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{185} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{190} } func (x *UserVip) GetUserId() int64 { @@ -17040,6 +17563,371 @@ func (x *UserVip) GetUpdatedAtMs() int64 { return 0 } +func (x *UserVip) GetProgramType() string { + if x != nil { + return x.ProgramType + } + return "" +} + +func (x *UserVip) GetConfigVersion() int64 { + if x != nil { + return x.ConfigVersion + } + return 0 +} + +// 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"` +} + +func (x *VipTrialCard) Reset() { + *x = VipTrialCard{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[191] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VipTrialCard) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VipTrialCard) ProtoMessage() {} + +func (x *VipTrialCard) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[191] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VipTrialCard.ProtoReflect.Descriptor instead. +func (*VipTrialCard) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{191} +} + +func (x *VipTrialCard) GetTrialCardId() string { + if x != nil { + return x.TrialCardId + } + return "" +} + +func (x *VipTrialCard) GetEntitlementId() string { + if x != nil { + return x.EntitlementId + } + return "" +} + +func (x *VipTrialCard) GetResourceId() int64 { + if x != nil { + return x.ResourceId + } + return 0 +} + +func (x *VipTrialCard) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *VipTrialCard) GetLevel() int32 { + if x != nil { + return x.Level + } + return 0 +} + +func (x *VipTrialCard) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *VipTrialCard) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *VipTrialCard) GetEquipped() bool { + if x != nil { + return x.Equipped + } + return false +} + +func (x *VipTrialCard) GetDurationMs() int64 { + if x != nil { + return x.DurationMs + } + return 0 +} + +func (x *VipTrialCard) GetEffectiveAtMs() int64 { + if x != nil { + return x.EffectiveAtMs + } + return 0 +} + +func (x *VipTrialCard) GetExpiresAtMs() int64 { + if x != nil { + return x.ExpiresAtMs + } + return 0 +} + +func (x *VipTrialCard) GetRemainingDurationMs() int64 { + if x != nil { + return x.RemainingDurationMs + } + return 0 +} + +func (x *VipTrialCard) GetGrantSource() string { + if x != nil { + return x.GrantSource + } + return "" +} + +func (x *VipTrialCard) GetSourceGrantId() string { + if x != nil { + return x.SourceGrantId + } + return "" +} + +func (x *VipTrialCard) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *VipTrialCard) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +// VipUserSettings 是用户按 App 隔离的可关闭 VIP 功能偏好。没有持久记录时 wallet +// 仍返回两个默认开启值,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"` +} + +func (x *VipUserSettings) Reset() { + *x = VipUserSettings{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[192] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VipUserSettings) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VipUserSettings) ProtoMessage() {} + +func (x *VipUserSettings) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[192] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VipUserSettings.ProtoReflect.Descriptor instead. +func (*VipUserSettings) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{192} +} + +func (x *VipUserSettings) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *VipUserSettings) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *VipUserSettings) GetRoomEntryNoticeEnabled() bool { + if x != nil { + return x.RoomEntryNoticeEnabled + } + return false +} + +func (x *VipUserSettings) GetOnlineGlobalNoticeEnabled() bool { + if x != nil { + return x.OnlineGlobalNoticeEnabled + } + return false +} + +func (x *VipUserSettings) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +// 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"` + // 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"` +} + +func (x *VipState) Reset() { + *x = VipState{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[193] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VipState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VipState) ProtoMessage() {} + +func (x *VipState) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[193] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VipState.ProtoReflect.Descriptor instead. +func (*VipState) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{193} +} + +func (x *VipState) GetPaidVip() *UserVip { + if x != nil { + return x.PaidVip + } + return nil +} + +func (x *VipState) GetEquippedTrialCard() *VipTrialCard { + if x != nil { + return x.EquippedTrialCard + } + return nil +} + +func (x *VipState) GetEffectiveVip() *UserVip { + if x != nil { + return x.EffectiveVip + } + return nil +} + +func (x *VipState) GetEffectiveSource() string { + if x != nil { + return x.EffectiveSource + } + return "" +} + +func (x *VipState) GetEffectiveBenefits() []*VipBenefit { + if x != nil { + return x.EffectiveBenefits + } + return nil +} + +func (x *VipState) GetEvaluatedAtMs() int64 { + if x != nil { + return x.EvaluatedAtMs + } + return 0 +} + +func (x *VipState) GetProgramConfig() *VipProgramConfig { + if x != nil { + return x.ProgramConfig + } + return nil +} + +func (x *VipState) GetUserSettings() *VipUserSettings { + if x != nil { + return x.UserSettings + } + return nil +} + type ListVipPackagesRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -17052,7 +17940,7 @@ type ListVipPackagesRequest struct { func (x *ListVipPackagesRequest) Reset() { *x = ListVipPackagesRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[186] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[194] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17064,7 +17952,7 @@ func (x *ListVipPackagesRequest) String() string { func (*ListVipPackagesRequest) ProtoMessage() {} func (x *ListVipPackagesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[186] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[194] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17077,7 +17965,7 @@ func (x *ListVipPackagesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListVipPackagesRequest.ProtoReflect.Descriptor instead. func (*ListVipPackagesRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{186} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{194} } func (x *ListVipPackagesRequest) GetRequestId() string { @@ -17106,13 +17994,15 @@ type ListVipPackagesResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - CurrentVip *UserVip `protobuf:"bytes,1,opt,name=current_vip,json=currentVip,proto3" json:"current_vip,omitempty"` - Packages []*VipLevel `protobuf:"bytes,2,rep,name=packages,proto3" json:"packages,omitempty"` + 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"` } func (x *ListVipPackagesResponse) Reset() { *x = ListVipPackagesResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[187] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[195] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17124,7 +18014,7 @@ func (x *ListVipPackagesResponse) String() string { func (*ListVipPackagesResponse) ProtoMessage() {} func (x *ListVipPackagesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[187] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[195] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17137,7 +18027,7 @@ func (x *ListVipPackagesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListVipPackagesResponse.ProtoReflect.Descriptor instead. func (*ListVipPackagesResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{187} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{195} } func (x *ListVipPackagesResponse) GetCurrentVip() *UserVip { @@ -17154,6 +18044,20 @@ func (x *ListVipPackagesResponse) GetPackages() []*VipLevel { return nil } +func (x *ListVipPackagesResponse) GetState() *VipState { + if x != nil { + return x.State + } + return nil +} + +func (x *ListVipPackagesResponse) GetProgramConfig() *VipProgramConfig { + if x != nil { + return x.ProgramConfig + } + return nil +} + type GetMyVipRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -17166,7 +18070,7 @@ type GetMyVipRequest struct { func (x *GetMyVipRequest) Reset() { *x = GetMyVipRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[188] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[196] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17178,7 +18082,7 @@ func (x *GetMyVipRequest) String() string { func (*GetMyVipRequest) ProtoMessage() {} func (x *GetMyVipRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[188] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[196] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17191,7 +18095,7 @@ func (x *GetMyVipRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyVipRequest.ProtoReflect.Descriptor instead. func (*GetMyVipRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{188} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{196} } func (x *GetMyVipRequest) GetRequestId() string { @@ -17220,12 +18124,13 @@ type GetMyVipResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Vip *UserVip `protobuf:"bytes,1,opt,name=vip,proto3" json:"vip,omitempty"` + Vip *UserVip `protobuf:"bytes,1,opt,name=vip,proto3" json:"vip,omitempty"` + State *VipState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` } func (x *GetMyVipResponse) Reset() { *x = GetMyVipResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[189] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[197] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17237,7 +18142,7 @@ func (x *GetMyVipResponse) String() string { func (*GetMyVipResponse) ProtoMessage() {} func (x *GetMyVipResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[189] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[197] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17250,7 +18155,7 @@ func (x *GetMyVipResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyVipResponse.ProtoReflect.Descriptor instead. func (*GetMyVipResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{189} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{197} } func (x *GetMyVipResponse) GetVip() *UserVip { @@ -17260,6 +18165,13 @@ func (x *GetMyVipResponse) GetVip() *UserVip { return nil } +func (x *GetMyVipResponse) GetState() *VipState { + if x != nil { + return x.State + } + return nil +} + type PurchaseVipRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -17273,7 +18185,7 @@ type PurchaseVipRequest struct { func (x *PurchaseVipRequest) Reset() { *x = PurchaseVipRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[190] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[198] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17285,7 +18197,7 @@ func (x *PurchaseVipRequest) String() string { func (*PurchaseVipRequest) ProtoMessage() {} func (x *PurchaseVipRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[190] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[198] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17298,7 +18210,7 @@ func (x *PurchaseVipRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PurchaseVipRequest.ProtoReflect.Descriptor instead. func (*PurchaseVipRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{190} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{198} } func (x *PurchaseVipRequest) GetCommandId() string { @@ -17340,11 +18252,12 @@ type PurchaseVipResponse struct { 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"` } func (x *PurchaseVipResponse) Reset() { *x = PurchaseVipResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[191] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[199] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17356,7 +18269,7 @@ func (x *PurchaseVipResponse) String() string { func (*PurchaseVipResponse) ProtoMessage() {} func (x *PurchaseVipResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[191] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[199] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17369,7 +18282,7 @@ func (x *PurchaseVipResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PurchaseVipResponse.ProtoReflect.Descriptor instead. func (*PurchaseVipResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{191} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{199} } func (x *PurchaseVipResponse) GetOrderId() string { @@ -17414,6 +18327,13 @@ func (x *PurchaseVipResponse) GetRewardItems() []*VipRewardItem { return nil } +func (x *PurchaseVipResponse) GetState() *VipState { + if x != nil { + return x.State + } + return nil +} + type DebitCPBreakupFeeRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -17429,7 +18349,7 @@ type DebitCPBreakupFeeRequest struct { func (x *DebitCPBreakupFeeRequest) Reset() { *x = DebitCPBreakupFeeRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[192] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[200] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17441,7 +18361,7 @@ func (x *DebitCPBreakupFeeRequest) String() string { func (*DebitCPBreakupFeeRequest) ProtoMessage() {} func (x *DebitCPBreakupFeeRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[192] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[200] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17454,7 +18374,7 @@ func (x *DebitCPBreakupFeeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DebitCPBreakupFeeRequest.ProtoReflect.Descriptor instead. func (*DebitCPBreakupFeeRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{192} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{200} } func (x *DebitCPBreakupFeeRequest) GetCommandId() string { @@ -17512,7 +18432,7 @@ type DebitCPBreakupFeeResponse struct { func (x *DebitCPBreakupFeeResponse) Reset() { *x = DebitCPBreakupFeeResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[193] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[201] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17524,7 +18444,7 @@ func (x *DebitCPBreakupFeeResponse) String() string { func (*DebitCPBreakupFeeResponse) ProtoMessage() {} func (x *DebitCPBreakupFeeResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[193] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[201] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17537,7 +18457,7 @@ func (x *DebitCPBreakupFeeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DebitCPBreakupFeeResponse.ProtoReflect.Descriptor instead. func (*DebitCPBreakupFeeResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{193} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{201} } func (x *DebitCPBreakupFeeResponse) GetTransactionId() string { @@ -17583,7 +18503,7 @@ type DebitWheelDrawRequest struct { func (x *DebitWheelDrawRequest) Reset() { *x = DebitWheelDrawRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[194] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[202] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17595,7 +18515,7 @@ func (x *DebitWheelDrawRequest) String() string { func (*DebitWheelDrawRequest) ProtoMessage() {} func (x *DebitWheelDrawRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[194] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[202] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17608,7 +18528,7 @@ func (x *DebitWheelDrawRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DebitWheelDrawRequest.ProtoReflect.Descriptor instead. func (*DebitWheelDrawRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{194} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{202} } func (x *DebitWheelDrawRequest) GetCommandId() string { @@ -17666,7 +18586,7 @@ type DebitWheelDrawResponse struct { func (x *DebitWheelDrawResponse) Reset() { *x = DebitWheelDrawResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[195] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[203] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17678,7 +18598,7 @@ func (x *DebitWheelDrawResponse) String() string { func (*DebitWheelDrawResponse) ProtoMessage() {} func (x *DebitWheelDrawResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[195] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[203] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17691,7 +18611,7 @@ func (x *DebitWheelDrawResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DebitWheelDrawResponse.ProtoReflect.Descriptor instead. func (*DebitWheelDrawResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{195} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{203} } func (x *DebitWheelDrawResponse) GetTransactionId() string { @@ -17738,7 +18658,7 @@ type GrantVipRequest struct { func (x *GrantVipRequest) Reset() { *x = GrantVipRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[196] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[204] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17750,7 +18670,7 @@ func (x *GrantVipRequest) String() string { func (*GrantVipRequest) ProtoMessage() {} func (x *GrantVipRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[196] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[204] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17763,7 +18683,7 @@ func (x *GrantVipRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GrantVipRequest.ProtoReflect.Descriptor instead. func (*GrantVipRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{196} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{204} } func (x *GrantVipRequest) GetCommandId() string { @@ -17824,11 +18744,12 @@ type GrantVipResponse struct { 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"` } func (x *GrantVipResponse) Reset() { *x = GrantVipResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[197] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[205] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17840,7 +18761,7 @@ func (x *GrantVipResponse) String() string { func (*GrantVipResponse) ProtoMessage() {} func (x *GrantVipResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[197] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[205] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17853,7 +18774,7 @@ func (x *GrantVipResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GrantVipResponse.ProtoReflect.Descriptor instead. func (*GrantVipResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{197} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{205} } func (x *GrantVipResponse) GetTransactionId() string { @@ -17884,6 +18805,1804 @@ func (x *GrantVipResponse) GetServerTimeMs() int64 { return 0 } +func (x *GrantVipResponse) GetState() *VipState { + if x != nil { + return x.State + } + return nil +} + +type GetVipProgramConfigRequest 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"` +} + +func (x *GetVipProgramConfigRequest) Reset() { + *x = GetVipProgramConfigRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[206] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetVipProgramConfigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetVipProgramConfigRequest) ProtoMessage() {} + +func (x *GetVipProgramConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[206] + 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 GetVipProgramConfigRequest.ProtoReflect.Descriptor instead. +func (*GetVipProgramConfigRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{206} +} + +func (x *GetVipProgramConfigRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *GetVipProgramConfigRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +type GetVipProgramConfigResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *GetVipProgramConfigResponse) Reset() { + *x = GetVipProgramConfigResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[207] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetVipProgramConfigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetVipProgramConfigResponse) ProtoMessage() {} + +func (x *GetVipProgramConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[207] + 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 GetVipProgramConfigResponse.ProtoReflect.Descriptor instead. +func (*GetVipProgramConfigResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{207} +} + +func (x *GetVipProgramConfigResponse) GetConfig() *VipProgramConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *GetVipProgramConfigResponse) GetBenefits() []*VipBenefit { + if x != nil { + return x.Benefits + } + return nil +} + +func (x *GetVipProgramConfigResponse) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +// 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"` +} + +func (x *UpdateAdminVipProgramConfigRequest) Reset() { + *x = UpdateAdminVipProgramConfigRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[208] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateAdminVipProgramConfigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateAdminVipProgramConfigRequest) ProtoMessage() {} + +func (x *UpdateAdminVipProgramConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[208] + 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 UpdateAdminVipProgramConfigRequest.ProtoReflect.Descriptor instead. +func (*UpdateAdminVipProgramConfigRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{208} +} + +func (x *UpdateAdminVipProgramConfigRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *UpdateAdminVipProgramConfigRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *UpdateAdminVipProgramConfigRequest) GetConfig() *VipProgramConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *UpdateAdminVipProgramConfigRequest) GetOperatorUserId() int64 { + if x != nil { + return x.OperatorUserId + } + return 0 +} + +type UpdateAdminVipProgramConfigResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *UpdateAdminVipProgramConfigResponse) Reset() { + *x = UpdateAdminVipProgramConfigResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[209] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateAdminVipProgramConfigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateAdminVipProgramConfigResponse) ProtoMessage() {} + +func (x *UpdateAdminVipProgramConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[209] + 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 UpdateAdminVipProgramConfigResponse.ProtoReflect.Descriptor instead. +func (*UpdateAdminVipProgramConfigResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{209} +} + +func (x *UpdateAdminVipProgramConfigResponse) GetConfig() *VipProgramConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *UpdateAdminVipProgramConfigResponse) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +// 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"` +} + +func (x *UpdateMyVipSettingsRequest) Reset() { + *x = UpdateMyVipSettingsRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[210] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateMyVipSettingsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateMyVipSettingsRequest) ProtoMessage() {} + +func (x *UpdateMyVipSettingsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[210] + 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 UpdateMyVipSettingsRequest.ProtoReflect.Descriptor instead. +func (*UpdateMyVipSettingsRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{210} +} + +func (x *UpdateMyVipSettingsRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *UpdateMyVipSettingsRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *UpdateMyVipSettingsRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *UpdateMyVipSettingsRequest) GetRoomEntryNoticeEnabled() bool { + if x != nil && x.RoomEntryNoticeEnabled != nil { + return *x.RoomEntryNoticeEnabled + } + return false +} + +func (x *UpdateMyVipSettingsRequest) GetOnlineGlobalNoticeEnabled() bool { + if x != nil && x.OnlineGlobalNoticeEnabled != nil { + return *x.OnlineGlobalNoticeEnabled + } + return false +} + +type UpdateMyVipSettingsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + 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 *UpdateMyVipSettingsResponse) Reset() { + *x = UpdateMyVipSettingsResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[211] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateMyVipSettingsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateMyVipSettingsResponse) ProtoMessage() {} + +func (x *UpdateMyVipSettingsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[211] + 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 UpdateMyVipSettingsResponse.ProtoReflect.Descriptor instead. +func (*UpdateMyVipSettingsResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{211} +} + +func (x *UpdateMyVipSettingsResponse) GetSettings() *VipUserSettings { + if x != nil { + return x.Settings + } + return nil +} + +func (x *UpdateMyVipSettingsResponse) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +// 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"` +} + +func (x *VipDailyCoinRebateRun) Reset() { + *x = VipDailyCoinRebateRun{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[212] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VipDailyCoinRebateRun) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VipDailyCoinRebateRun) ProtoMessage() {} + +func (x *VipDailyCoinRebateRun) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[212] + 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 VipDailyCoinRebateRun.ProtoReflect.Descriptor instead. +func (*VipDailyCoinRebateRun) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{212} +} + +func (x *VipDailyCoinRebateRun) GetRunId() string { + if x != nil { + return x.RunId + } + return "" +} + +func (x *VipDailyCoinRebateRun) GetTaskDay() string { + if x != nil { + return x.TaskDay + } + return "" +} + +func (x *VipDailyCoinRebateRun) GetDayStartMs() int64 { + if x != nil { + return x.DayStartMs + } + return 0 +} + +func (x *VipDailyCoinRebateRun) GetDayEndMs() int64 { + if x != nil { + return x.DayEndMs + } + return 0 +} + +func (x *VipDailyCoinRebateRun) GetConfigVersion() int64 { + if x != nil { + return x.ConfigVersion + } + return 0 +} + +func (x *VipDailyCoinRebateRun) GetLevelAmountsJson() string { + if x != nil { + return x.LevelAmountsJson + } + return "" +} + +func (x *VipDailyCoinRebateRun) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *VipDailyCoinRebateRun) GetLastUserId() int64 { + if x != nil { + return x.LastUserId + } + return 0 +} + +func (x *VipDailyCoinRebateRun) GetScannedCount() int64 { + if x != nil { + return x.ScannedCount + } + return 0 +} + +func (x *VipDailyCoinRebateRun) GetCreatedCount() int64 { + if x != nil { + return x.CreatedCount + } + return 0 +} + +func (x *VipDailyCoinRebateRun) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *VipDailyCoinRebateRun) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +func (x *VipDailyCoinRebateRun) GetCompletedAtMs() int64 { + if x != nil { + return x.CompletedAtMs + } + return 0 +} + +// 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"` +} + +func (x *VipDailyCoinRebate) Reset() { + *x = VipDailyCoinRebate{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[213] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VipDailyCoinRebate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VipDailyCoinRebate) ProtoMessage() {} + +func (x *VipDailyCoinRebate) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[213] + 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 VipDailyCoinRebate.ProtoReflect.Descriptor instead. +func (*VipDailyCoinRebate) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{213} +} + +func (x *VipDailyCoinRebate) GetRebateId() string { + if x != nil { + return x.RebateId + } + return "" +} + +func (x *VipDailyCoinRebate) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *VipDailyCoinRebate) GetTaskDay() string { + if x != nil { + return x.TaskDay + } + return "" +} + +func (x *VipDailyCoinRebate) GetVipLevel() int32 { + if x != nil { + return x.VipLevel + } + return 0 +} + +func (x *VipDailyCoinRebate) GetVipName() string { + if x != nil { + return x.VipName + } + return "" +} + +func (x *VipDailyCoinRebate) GetCoinAmount() int64 { + if x != nil { + return x.CoinAmount + } + return 0 +} + +func (x *VipDailyCoinRebate) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *VipDailyCoinRebate) GetAvailableAtMs() int64 { + if x != nil { + return x.AvailableAtMs + } + return 0 +} + +func (x *VipDailyCoinRebate) GetExpiresAtMs() int64 { + if x != nil { + return x.ExpiresAtMs + } + return 0 +} + +func (x *VipDailyCoinRebate) GetConfigVersion() int64 { + if x != nil { + return x.ConfigVersion + } + return 0 +} + +func (x *VipDailyCoinRebate) GetClaimedAtMs() int64 { + if x != nil { + return x.ClaimedAtMs + } + return 0 +} + +func (x *VipDailyCoinRebate) GetWalletTransactionId() string { + if x != nil { + return x.WalletTransactionId + } + return "" +} + +func (x *VipDailyCoinRebate) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *VipDailyCoinRebate) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +// ProcessVipDailyCoinRebateBatchRequest 由 WalletCronService 接收。task_day 为空时按 +// wallet-service 当前 UTC 日期处理;同 App+task_day 始终创建或复用同一个 run。 +type ProcessVipDailyCoinRebateBatchRequest 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"` + 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"` +} + +func (x *ProcessVipDailyCoinRebateBatchRequest) Reset() { + *x = ProcessVipDailyCoinRebateBatchRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[214] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProcessVipDailyCoinRebateBatchRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProcessVipDailyCoinRebateBatchRequest) ProtoMessage() {} + +func (x *ProcessVipDailyCoinRebateBatchRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[214] + 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 ProcessVipDailyCoinRebateBatchRequest.ProtoReflect.Descriptor instead. +func (*ProcessVipDailyCoinRebateBatchRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{214} +} + +func (x *ProcessVipDailyCoinRebateBatchRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *ProcessVipDailyCoinRebateBatchRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *ProcessVipDailyCoinRebateBatchRequest) GetTaskDay() string { + if x != nil { + return x.TaskDay + } + return "" +} + +func (x *ProcessVipDailyCoinRebateBatchRequest) GetBatchSize() int32 { + if x != nil { + return x.BatchSize + } + return 0 +} + +type ProcessVipDailyCoinRebateBatchResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *ProcessVipDailyCoinRebateBatchResponse) Reset() { + *x = ProcessVipDailyCoinRebateBatchResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[215] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProcessVipDailyCoinRebateBatchResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProcessVipDailyCoinRebateBatchResponse) ProtoMessage() {} + +func (x *ProcessVipDailyCoinRebateBatchResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[215] + 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 ProcessVipDailyCoinRebateBatchResponse.ProtoReflect.Descriptor instead. +func (*ProcessVipDailyCoinRebateBatchResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{215} +} + +func (x *ProcessVipDailyCoinRebateBatchResponse) GetRun() *VipDailyCoinRebateRun { + if x != nil { + return x.Run + } + return nil +} + +func (x *ProcessVipDailyCoinRebateBatchResponse) GetScannedCount() int32 { + if x != nil { + return x.ScannedCount + } + return 0 +} + +func (x *ProcessVipDailyCoinRebateBatchResponse) GetCreatedCount() int32 { + if x != nil { + return x.CreatedCount + } + return 0 +} + +func (x *ProcessVipDailyCoinRebateBatchResponse) GetHasMore() bool { + if x != nil { + return x.HasMore + } + return false +} + +func (x *ProcessVipDailyCoinRebateBatchResponse) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +type GetMyCurrentVipDailyCoinRebateRequest 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"` +} + +func (x *GetMyCurrentVipDailyCoinRebateRequest) Reset() { + *x = GetMyCurrentVipDailyCoinRebateRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[216] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetMyCurrentVipDailyCoinRebateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetMyCurrentVipDailyCoinRebateRequest) ProtoMessage() {} + +func (x *GetMyCurrentVipDailyCoinRebateRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[216] + 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 GetMyCurrentVipDailyCoinRebateRequest.ProtoReflect.Descriptor instead. +func (*GetMyCurrentVipDailyCoinRebateRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{216} +} + +func (x *GetMyCurrentVipDailyCoinRebateRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *GetMyCurrentVipDailyCoinRebateRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *GetMyCurrentVipDailyCoinRebateRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +type GetMyCurrentVipDailyCoinRebateResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *GetMyCurrentVipDailyCoinRebateResponse) Reset() { + *x = GetMyCurrentVipDailyCoinRebateResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[217] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetMyCurrentVipDailyCoinRebateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetMyCurrentVipDailyCoinRebateResponse) ProtoMessage() {} + +func (x *GetMyCurrentVipDailyCoinRebateResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[217] + 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 GetMyCurrentVipDailyCoinRebateResponse.ProtoReflect.Descriptor instead. +func (*GetMyCurrentVipDailyCoinRebateResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{217} +} + +func (x *GetMyCurrentVipDailyCoinRebateResponse) GetFound() bool { + if x != nil { + return x.Found + } + return false +} + +func (x *GetMyCurrentVipDailyCoinRebateResponse) GetRebate() *VipDailyCoinRebate { + if x != nil { + return x.Rebate + } + return nil +} + +func (x *GetMyCurrentVipDailyCoinRebateResponse) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +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"` + // rebate_ids 非空时精确恢复指定通知的领取状态,最多 100 个;仍强制按 user_id 隔离。 + RebateIds []string `protobuf:"bytes,6,rep,name=rebate_ids,json=rebateIds,proto3" json:"rebate_ids,omitempty"` +} + +func (x *ListMyVipDailyCoinRebateStatusesRequest) Reset() { + *x = ListMyVipDailyCoinRebateStatusesRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[218] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListMyVipDailyCoinRebateStatusesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListMyVipDailyCoinRebateStatusesRequest) ProtoMessage() {} + +func (x *ListMyVipDailyCoinRebateStatusesRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[218] + 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 ListMyVipDailyCoinRebateStatusesRequest.ProtoReflect.Descriptor instead. +func (*ListMyVipDailyCoinRebateStatusesRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{218} +} + +func (x *ListMyVipDailyCoinRebateStatusesRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *ListMyVipDailyCoinRebateStatusesRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *ListMyVipDailyCoinRebateStatusesRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *ListMyVipDailyCoinRebateStatusesRequest) GetPage() int32 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *ListMyVipDailyCoinRebateStatusesRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +func (x *ListMyVipDailyCoinRebateStatusesRequest) GetRebateIds() []string { + if x != nil { + return x.RebateIds + } + return nil +} + +type ListMyVipDailyCoinRebateStatusesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *ListMyVipDailyCoinRebateStatusesResponse) Reset() { + *x = ListMyVipDailyCoinRebateStatusesResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[219] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListMyVipDailyCoinRebateStatusesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListMyVipDailyCoinRebateStatusesResponse) ProtoMessage() {} + +func (x *ListMyVipDailyCoinRebateStatusesResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[219] + 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 ListMyVipDailyCoinRebateStatusesResponse.ProtoReflect.Descriptor instead. +func (*ListMyVipDailyCoinRebateStatusesResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{219} +} + +func (x *ListMyVipDailyCoinRebateStatusesResponse) GetRebates() []*VipDailyCoinRebate { + if x != nil { + return x.Rebates + } + return nil +} + +func (x *ListMyVipDailyCoinRebateStatusesResponse) GetTotal() int64 { + if x != nil { + return x.Total + } + return 0 +} + +func (x *ListMyVipDailyCoinRebateStatusesResponse) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +type ClaimVipDailyCoinRebateRequest 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"` + 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"` +} + +func (x *ClaimVipDailyCoinRebateRequest) Reset() { + *x = ClaimVipDailyCoinRebateRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[220] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ClaimVipDailyCoinRebateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClaimVipDailyCoinRebateRequest) ProtoMessage() {} + +func (x *ClaimVipDailyCoinRebateRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[220] + 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 ClaimVipDailyCoinRebateRequest.ProtoReflect.Descriptor instead. +func (*ClaimVipDailyCoinRebateRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{220} +} + +func (x *ClaimVipDailyCoinRebateRequest) GetCommandId() string { + if x != nil { + return x.CommandId + } + return "" +} + +func (x *ClaimVipDailyCoinRebateRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *ClaimVipDailyCoinRebateRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *ClaimVipDailyCoinRebateRequest) GetRebateId() string { + if x != nil { + return x.RebateId + } + return "" +} + +type ClaimVipDailyCoinRebateResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *ClaimVipDailyCoinRebateResponse) Reset() { + *x = ClaimVipDailyCoinRebateResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[221] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ClaimVipDailyCoinRebateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClaimVipDailyCoinRebateResponse) ProtoMessage() {} + +func (x *ClaimVipDailyCoinRebateResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[221] + 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 ClaimVipDailyCoinRebateResponse.ProtoReflect.Descriptor instead. +func (*ClaimVipDailyCoinRebateResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{221} +} + +func (x *ClaimVipDailyCoinRebateResponse) GetRebate() *VipDailyCoinRebate { + if x != nil { + return x.Rebate + } + return nil +} + +func (x *ClaimVipDailyCoinRebateResponse) GetTransactionId() string { + if x != nil { + return x.TransactionId + } + return "" +} + +func (x *ClaimVipDailyCoinRebateResponse) GetCoinBalance() *AssetBalance { + if x != nil { + return x.CoinBalance + } + return nil +} + +func (x *ClaimVipDailyCoinRebateResponse) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +// 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"` +} + +func (x *GrantVipTrialCardRequest) Reset() { + *x = GrantVipTrialCardRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[222] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GrantVipTrialCardRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GrantVipTrialCardRequest) ProtoMessage() {} + +func (x *GrantVipTrialCardRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[222] + 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 GrantVipTrialCardRequest.ProtoReflect.Descriptor instead. +func (*GrantVipTrialCardRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{222} +} + +func (x *GrantVipTrialCardRequest) GetCommandId() string { + if x != nil { + return x.CommandId + } + return "" +} + +func (x *GrantVipTrialCardRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *GrantVipTrialCardRequest) GetTargetUserId() int64 { + if x != nil { + return x.TargetUserId + } + return 0 +} + +func (x *GrantVipTrialCardRequest) GetLevel() int32 { + if x != nil { + return x.Level + } + return 0 +} + +func (x *GrantVipTrialCardRequest) GetDurationMs() int64 { + if x != nil { + return x.DurationMs + } + return 0 +} + +func (x *GrantVipTrialCardRequest) GetResourceId() int64 { + if x != nil && x.ResourceId != nil { + return *x.ResourceId + } + return 0 +} + +func (x *GrantVipTrialCardRequest) GetGrantSource() string { + if x != nil { + return x.GrantSource + } + return "" +} + +func (x *GrantVipTrialCardRequest) GetOperatorUserId() int64 { + if x != nil { + return x.OperatorUserId + } + return 0 +} + +func (x *GrantVipTrialCardRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type GrantVipTrialCardResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *GrantVipTrialCardResponse) Reset() { + *x = GrantVipTrialCardResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[223] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GrantVipTrialCardResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GrantVipTrialCardResponse) ProtoMessage() {} + +func (x *GrantVipTrialCardResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[223] + 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 GrantVipTrialCardResponse.ProtoReflect.Descriptor instead. +func (*GrantVipTrialCardResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{223} +} + +func (x *GrantVipTrialCardResponse) GetTrialCard() *VipTrialCard { + if x != nil { + return x.TrialCard + } + return nil +} + +func (x *GrantVipTrialCardResponse) GetState() *VipState { + if x != nil { + return x.State + } + return nil +} + +func (x *GrantVipTrialCardResponse) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +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"` + // entitlement_id 是背包实例标识,保证同资源的多张卡也能被精确佩戴。 + EntitlementId string `protobuf:"bytes,4,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` +} + +func (x *EquipVipTrialCardRequest) Reset() { + *x = EquipVipTrialCardRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[224] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EquipVipTrialCardRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EquipVipTrialCardRequest) ProtoMessage() {} + +func (x *EquipVipTrialCardRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[224] + 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 EquipVipTrialCardRequest.ProtoReflect.Descriptor instead. +func (*EquipVipTrialCardRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{224} +} + +func (x *EquipVipTrialCardRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *EquipVipTrialCardRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *EquipVipTrialCardRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *EquipVipTrialCardRequest) GetEntitlementId() string { + if x != nil { + return x.EntitlementId + } + return "" +} + +type EquipVipTrialCardResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *EquipVipTrialCardResponse) Reset() { + *x = EquipVipTrialCardResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[225] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EquipVipTrialCardResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EquipVipTrialCardResponse) ProtoMessage() {} + +func (x *EquipVipTrialCardResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[225] + 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 EquipVipTrialCardResponse.ProtoReflect.Descriptor instead. +func (*EquipVipTrialCardResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{225} +} + +func (x *EquipVipTrialCardResponse) GetTrialCard() *VipTrialCard { + if x != nil { + return x.TrialCard + } + return nil +} + +func (x *EquipVipTrialCardResponse) GetState() *VipState { + if x != nil { + return x.State + } + return nil +} + +func (x *EquipVipTrialCardResponse) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +type UnequipVipTrialCardRequest 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"` +} + +func (x *UnequipVipTrialCardRequest) Reset() { + *x = UnequipVipTrialCardRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[226] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UnequipVipTrialCardRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnequipVipTrialCardRequest) ProtoMessage() {} + +func (x *UnequipVipTrialCardRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[226] + 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 UnequipVipTrialCardRequest.ProtoReflect.Descriptor instead. +func (*UnequipVipTrialCardRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{226} +} + +func (x *UnequipVipTrialCardRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *UnequipVipTrialCardRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *UnequipVipTrialCardRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +type UnequipVipTrialCardResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *UnequipVipTrialCardResponse) Reset() { + *x = UnequipVipTrialCardResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[227] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UnequipVipTrialCardResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnequipVipTrialCardResponse) ProtoMessage() {} + +func (x *UnequipVipTrialCardResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[227] + 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 UnequipVipTrialCardResponse.ProtoReflect.Descriptor instead. +func (*UnequipVipTrialCardResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{227} +} + +func (x *UnequipVipTrialCardResponse) GetUnequipped() bool { + if x != nil { + return x.Unequipped + } + return false +} + +func (x *UnequipVipTrialCardResponse) GetState() *VipState { + if x != nil { + return x.State + } + return nil +} + +func (x *UnequipVipTrialCardResponse) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +// CheckVipBenefit 供 room/user 等权益执行方校验单个特权。调用方不能只比较 VIP level, +// 因为体验卡排除项和 App 配置会改变最终可执行权益集合。 +type CheckVipBenefitRequest 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"` + BenefitCode string `protobuf:"bytes,4,opt,name=benefit_code,json=benefitCode,proto3" json:"benefit_code,omitempty"` +} + +func (x *CheckVipBenefitRequest) Reset() { + *x = CheckVipBenefitRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[228] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckVipBenefitRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckVipBenefitRequest) ProtoMessage() {} + +func (x *CheckVipBenefitRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[228] + 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 CheckVipBenefitRequest.ProtoReflect.Descriptor instead. +func (*CheckVipBenefitRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{228} +} + +func (x *CheckVipBenefitRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *CheckVipBenefitRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *CheckVipBenefitRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *CheckVipBenefitRequest) GetBenefitCode() string { + if x != nil { + return x.BenefitCode + } + return "" +} + +type CheckVipBenefitResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + 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"` +} + +func (x *CheckVipBenefitResponse) Reset() { + *x = CheckVipBenefitResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[229] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckVipBenefitResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckVipBenefitResponse) ProtoMessage() {} + +func (x *CheckVipBenefitResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[229] + 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 CheckVipBenefitResponse.ProtoReflect.Descriptor instead. +func (*CheckVipBenefitResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{229} +} + +func (x *CheckVipBenefitResponse) GetAllowed() bool { + if x != nil { + return x.Allowed + } + return false +} + +func (x *CheckVipBenefitResponse) GetBenefit() *VipBenefit { + if x != nil { + return x.Benefit + } + return nil +} + +func (x *CheckVipBenefitResponse) GetState() *VipState { + if x != nil { + return x.State + } + return nil +} + +func (x *CheckVipBenefitResponse) GetDenialReason() string { + if x != nil { + return x.DenialReason + } + return "" +} + +func (x *CheckVipBenefitResponse) GetEvaluatedAtMs() int64 { + if x != nil { + return x.EvaluatedAtMs + } + return 0 +} + type AdminVipLevelInput struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -17897,11 +20616,13 @@ type AdminVipLevelInput struct { 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"` } func (x *AdminVipLevelInput) Reset() { *x = AdminVipLevelInput{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[198] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[230] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17913,7 +20634,7 @@ func (x *AdminVipLevelInput) String() string { func (*AdminVipLevelInput) ProtoMessage() {} func (x *AdminVipLevelInput) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[198] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[230] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17926,7 +20647,7 @@ func (x *AdminVipLevelInput) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminVipLevelInput.ProtoReflect.Descriptor instead. func (*AdminVipLevelInput) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{198} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{230} } func (x *AdminVipLevelInput) GetLevel() int32 { @@ -17985,6 +20706,13 @@ func (x *AdminVipLevelInput) GetRequiredRechargeCoinAmount() int64 { return 0 } +func (x *AdminVipLevelInput) GetBenefits() []*VipBenefit { + if x != nil { + return x.Benefits + } + return nil +} + type ListAdminVipLevelsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -17996,7 +20724,7 @@ type ListAdminVipLevelsRequest struct { func (x *ListAdminVipLevelsRequest) Reset() { *x = ListAdminVipLevelsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[199] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[231] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18008,7 +20736,7 @@ func (x *ListAdminVipLevelsRequest) String() string { func (*ListAdminVipLevelsRequest) ProtoMessage() {} func (x *ListAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[199] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[231] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18021,7 +20749,7 @@ func (x *ListAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAdminVipLevelsRequest.ProtoReflect.Descriptor instead. func (*ListAdminVipLevelsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{199} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{231} } func (x *ListAdminVipLevelsRequest) GetRequestId() string { @@ -18043,13 +20771,14 @@ type ListAdminVipLevelsResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Levels []*VipLevel `protobuf:"bytes,1,rep,name=levels,proto3" json:"levels,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + 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"` } func (x *ListAdminVipLevelsResponse) Reset() { *x = ListAdminVipLevelsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[200] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[232] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18061,7 +20790,7 @@ func (x *ListAdminVipLevelsResponse) String() string { func (*ListAdminVipLevelsResponse) ProtoMessage() {} func (x *ListAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[200] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[232] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18074,7 +20803,7 @@ func (x *ListAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAdminVipLevelsResponse.ProtoReflect.Descriptor instead. func (*ListAdminVipLevelsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{200} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{232} } func (x *ListAdminVipLevelsResponse) GetLevels() []*VipLevel { @@ -18091,6 +20820,13 @@ func (x *ListAdminVipLevelsResponse) GetServerTimeMs() int64 { return 0 } +func (x *ListAdminVipLevelsResponse) GetProgramConfig() *VipProgramConfig { + if x != nil { + return x.ProgramConfig + } + return nil +} + type UpdateAdminVipLevelsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -18104,7 +20840,7 @@ type UpdateAdminVipLevelsRequest struct { func (x *UpdateAdminVipLevelsRequest) Reset() { *x = UpdateAdminVipLevelsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[201] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[233] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18116,7 +20852,7 @@ func (x *UpdateAdminVipLevelsRequest) String() string { func (*UpdateAdminVipLevelsRequest) ProtoMessage() {} func (x *UpdateAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[201] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[233] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18129,7 +20865,7 @@ func (x *UpdateAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateAdminVipLevelsRequest.ProtoReflect.Descriptor instead. func (*UpdateAdminVipLevelsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{201} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{233} } func (x *UpdateAdminVipLevelsRequest) GetRequestId() string { @@ -18165,13 +20901,14 @@ type UpdateAdminVipLevelsResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Levels []*VipLevel `protobuf:"bytes,1,rep,name=levels,proto3" json:"levels,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + 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"` } func (x *UpdateAdminVipLevelsResponse) Reset() { *x = UpdateAdminVipLevelsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[202] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[234] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18183,7 +20920,7 @@ func (x *UpdateAdminVipLevelsResponse) String() string { func (*UpdateAdminVipLevelsResponse) ProtoMessage() {} func (x *UpdateAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[202] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[234] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18196,7 +20933,7 @@ func (x *UpdateAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateAdminVipLevelsResponse.ProtoReflect.Descriptor instead. func (*UpdateAdminVipLevelsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{202} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{234} } func (x *UpdateAdminVipLevelsResponse) GetLevels() []*VipLevel { @@ -18213,6 +20950,13 @@ func (x *UpdateAdminVipLevelsResponse) GetServerTimeMs() int64 { return 0 } +func (x *UpdateAdminVipLevelsResponse) GetProgramConfig() *VipProgramConfig { + if x != nil { + return x.ProgramConfig + } + return nil +} + // CreditTaskRewardRequest 是 activity-service 领取任务奖励时调用的钱包入账命令。 type CreditTaskRewardRequest struct { state protoimpl.MessageState @@ -18232,7 +20976,7 @@ type CreditTaskRewardRequest struct { func (x *CreditTaskRewardRequest) Reset() { *x = CreditTaskRewardRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[203] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[235] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18244,7 +20988,7 @@ func (x *CreditTaskRewardRequest) String() string { func (*CreditTaskRewardRequest) ProtoMessage() {} func (x *CreditTaskRewardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[203] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[235] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18257,7 +21001,7 @@ func (x *CreditTaskRewardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditTaskRewardRequest.ProtoReflect.Descriptor instead. func (*CreditTaskRewardRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{203} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{235} } func (x *CreditTaskRewardRequest) GetCommandId() string { @@ -18337,7 +21081,7 @@ type CreditTaskRewardResponse struct { func (x *CreditTaskRewardResponse) Reset() { *x = CreditTaskRewardResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[204] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[236] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18349,7 +21093,7 @@ func (x *CreditTaskRewardResponse) String() string { func (*CreditTaskRewardResponse) ProtoMessage() {} func (x *CreditTaskRewardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[204] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[236] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18362,7 +21106,7 @@ func (x *CreditTaskRewardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditTaskRewardResponse.ProtoReflect.Descriptor instead. func (*CreditTaskRewardResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{204} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{236} } func (x *CreditTaskRewardResponse) GetTransactionId() string { @@ -18415,7 +21159,7 @@ type CreditLuckyGiftRewardRequest struct { func (x *CreditLuckyGiftRewardRequest) Reset() { *x = CreditLuckyGiftRewardRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[205] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[237] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18427,7 +21171,7 @@ func (x *CreditLuckyGiftRewardRequest) String() string { func (*CreditLuckyGiftRewardRequest) ProtoMessage() {} func (x *CreditLuckyGiftRewardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[205] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[237] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18440,7 +21184,7 @@ func (x *CreditLuckyGiftRewardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditLuckyGiftRewardRequest.ProtoReflect.Descriptor instead. func (*CreditLuckyGiftRewardRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{205} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{237} } func (x *CreditLuckyGiftRewardRequest) GetCommandId() string { @@ -18534,7 +21278,7 @@ type CreditLuckyGiftRewardResponse struct { func (x *CreditLuckyGiftRewardResponse) Reset() { *x = CreditLuckyGiftRewardResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[206] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[238] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18546,7 +21290,7 @@ func (x *CreditLuckyGiftRewardResponse) String() string { func (*CreditLuckyGiftRewardResponse) ProtoMessage() {} func (x *CreditLuckyGiftRewardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[206] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[238] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18559,7 +21303,7 @@ func (x *CreditLuckyGiftRewardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditLuckyGiftRewardResponse.ProtoReflect.Descriptor instead. func (*CreditLuckyGiftRewardResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{206} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{238} } func (x *CreditLuckyGiftRewardResponse) GetTransactionId() string { @@ -18609,7 +21353,7 @@ type CreditWheelRewardRequest struct { func (x *CreditWheelRewardRequest) Reset() { *x = CreditWheelRewardRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[207] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[239] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18621,7 +21365,7 @@ func (x *CreditWheelRewardRequest) String() string { func (*CreditWheelRewardRequest) ProtoMessage() {} func (x *CreditWheelRewardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[207] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[239] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18634,7 +21378,7 @@ func (x *CreditWheelRewardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditWheelRewardRequest.ProtoReflect.Descriptor instead. func (*CreditWheelRewardRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{207} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{239} } func (x *CreditWheelRewardRequest) GetCommandId() string { @@ -18714,7 +21458,7 @@ type CreditWheelRewardResponse struct { func (x *CreditWheelRewardResponse) Reset() { *x = CreditWheelRewardResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[208] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[240] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18726,7 +21470,7 @@ func (x *CreditWheelRewardResponse) String() string { func (*CreditWheelRewardResponse) ProtoMessage() {} func (x *CreditWheelRewardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[208] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[240] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18739,7 +21483,7 @@ func (x *CreditWheelRewardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditWheelRewardResponse.ProtoReflect.Descriptor instead. func (*CreditWheelRewardResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{208} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{240} } func (x *CreditWheelRewardResponse) GetTransactionId() string { @@ -18792,7 +21536,7 @@ type CreditRoomTurnoverRewardRequest struct { func (x *CreditRoomTurnoverRewardRequest) Reset() { *x = CreditRoomTurnoverRewardRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[209] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[241] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18804,7 +21548,7 @@ func (x *CreditRoomTurnoverRewardRequest) String() string { func (*CreditRoomTurnoverRewardRequest) ProtoMessage() {} func (x *CreditRoomTurnoverRewardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[209] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[241] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18817,7 +21561,7 @@ func (x *CreditRoomTurnoverRewardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditRoomTurnoverRewardRequest.ProtoReflect.Descriptor instead. func (*CreditRoomTurnoverRewardRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{209} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{241} } func (x *CreditRoomTurnoverRewardRequest) GetCommandId() string { @@ -18918,7 +21662,7 @@ type CreditRoomTurnoverRewardResponse struct { func (x *CreditRoomTurnoverRewardResponse) Reset() { *x = CreditRoomTurnoverRewardResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[210] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[242] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -18930,7 +21674,7 @@ func (x *CreditRoomTurnoverRewardResponse) String() string { func (*CreditRoomTurnoverRewardResponse) ProtoMessage() {} func (x *CreditRoomTurnoverRewardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[210] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[242] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -18943,7 +21687,7 @@ func (x *CreditRoomTurnoverRewardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditRoomTurnoverRewardResponse.ProtoReflect.Descriptor instead. func (*CreditRoomTurnoverRewardResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{210} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{242} } func (x *CreditRoomTurnoverRewardResponse) GetTransactionId() string { @@ -18995,7 +21739,7 @@ type CreditInviteActivityRewardRequest struct { func (x *CreditInviteActivityRewardRequest) Reset() { *x = CreditInviteActivityRewardRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[211] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[243] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19007,7 +21751,7 @@ func (x *CreditInviteActivityRewardRequest) String() string { func (*CreditInviteActivityRewardRequest) ProtoMessage() {} func (x *CreditInviteActivityRewardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[211] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[243] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19020,7 +21764,7 @@ func (x *CreditInviteActivityRewardRequest) ProtoReflect() protoreflect.Message // Deprecated: Use CreditInviteActivityRewardRequest.ProtoReflect.Descriptor instead. func (*CreditInviteActivityRewardRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{211} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{243} } func (x *CreditInviteActivityRewardRequest) GetCommandId() string { @@ -19114,7 +21858,7 @@ type CreditInviteActivityRewardResponse struct { func (x *CreditInviteActivityRewardResponse) Reset() { *x = CreditInviteActivityRewardResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[212] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[244] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19126,7 +21870,7 @@ func (x *CreditInviteActivityRewardResponse) String() string { func (*CreditInviteActivityRewardResponse) ProtoMessage() {} func (x *CreditInviteActivityRewardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[212] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[244] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19139,7 +21883,7 @@ func (x *CreditInviteActivityRewardResponse) ProtoReflect() protoreflect.Message // Deprecated: Use CreditInviteActivityRewardResponse.ProtoReflect.Descriptor instead. func (*CreditInviteActivityRewardResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{212} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{244} } func (x *CreditInviteActivityRewardResponse) GetTransactionId() string { @@ -19190,7 +21934,7 @@ type CreditAgencyOpeningRewardRequest struct { func (x *CreditAgencyOpeningRewardRequest) Reset() { *x = CreditAgencyOpeningRewardRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[213] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[245] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19202,7 +21946,7 @@ func (x *CreditAgencyOpeningRewardRequest) String() string { func (*CreditAgencyOpeningRewardRequest) ProtoMessage() {} func (x *CreditAgencyOpeningRewardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[213] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[245] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19215,7 +21959,7 @@ func (x *CreditAgencyOpeningRewardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditAgencyOpeningRewardRequest.ProtoReflect.Descriptor instead. func (*CreditAgencyOpeningRewardRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{213} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{245} } func (x *CreditAgencyOpeningRewardRequest) GetCommandId() string { @@ -19302,7 +22046,7 @@ type CreditAgencyOpeningRewardResponse struct { func (x *CreditAgencyOpeningRewardResponse) Reset() { *x = CreditAgencyOpeningRewardResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[214] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[246] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19314,7 +22058,7 @@ func (x *CreditAgencyOpeningRewardResponse) String() string { func (*CreditAgencyOpeningRewardResponse) ProtoMessage() {} func (x *CreditAgencyOpeningRewardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[214] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[246] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19327,7 +22071,7 @@ func (x *CreditAgencyOpeningRewardResponse) ProtoReflect() protoreflect.Message // Deprecated: Use CreditAgencyOpeningRewardResponse.ProtoReflect.Descriptor instead. func (*CreditAgencyOpeningRewardResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{214} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{246} } func (x *CreditAgencyOpeningRewardResponse) GetTransactionId() string { @@ -19380,7 +22124,7 @@ type ApplyGameCoinChangeRequest struct { func (x *ApplyGameCoinChangeRequest) Reset() { *x = ApplyGameCoinChangeRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[215] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[247] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19392,7 +22136,7 @@ func (x *ApplyGameCoinChangeRequest) String() string { func (*ApplyGameCoinChangeRequest) ProtoMessage() {} func (x *ApplyGameCoinChangeRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[215] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[247] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19405,7 +22149,7 @@ func (x *ApplyGameCoinChangeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyGameCoinChangeRequest.ProtoReflect.Descriptor instead. func (*ApplyGameCoinChangeRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{215} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{247} } func (x *ApplyGameCoinChangeRequest) GetRequestId() string { @@ -19505,7 +22249,7 @@ type ApplyGameCoinChangeResponse struct { func (x *ApplyGameCoinChangeResponse) Reset() { *x = ApplyGameCoinChangeResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[216] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[248] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19517,7 +22261,7 @@ func (x *ApplyGameCoinChangeResponse) String() string { func (*ApplyGameCoinChangeResponse) ProtoMessage() {} func (x *ApplyGameCoinChangeResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[216] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[248] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19530,7 +22274,7 @@ func (x *ApplyGameCoinChangeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyGameCoinChangeResponse.ProtoReflect.Descriptor instead. func (*ApplyGameCoinChangeResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{216} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{248} } func (x *ApplyGameCoinChangeResponse) GetWalletTransactionId() string { @@ -19574,7 +22318,7 @@ type RedPacketConfig struct { func (x *RedPacketConfig) Reset() { *x = RedPacketConfig{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[217] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[249] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19586,7 +22330,7 @@ func (x *RedPacketConfig) String() string { func (*RedPacketConfig) ProtoMessage() {} func (x *RedPacketConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[217] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[249] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19599,7 +22343,7 @@ func (x *RedPacketConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacketConfig.ProtoReflect.Descriptor instead. func (*RedPacketConfig) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{217} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{249} } func (x *RedPacketConfig) GetAppCode() string { @@ -19699,7 +22443,7 @@ type RedPacketClaim struct { func (x *RedPacketClaim) Reset() { *x = RedPacketClaim{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[218] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[250] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19711,7 +22455,7 @@ func (x *RedPacketClaim) String() string { func (*RedPacketClaim) ProtoMessage() {} func (x *RedPacketClaim) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[218] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[250] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19724,7 +22468,7 @@ func (x *RedPacketClaim) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacketClaim.ProtoReflect.Descriptor instead. func (*RedPacketClaim) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{218} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{250} } func (x *RedPacketClaim) GetAppCode() string { @@ -19835,7 +22579,7 @@ type RedPacket struct { func (x *RedPacket) Reset() { *x = RedPacket{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[219] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[251] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -19847,7 +22591,7 @@ func (x *RedPacket) String() string { func (*RedPacket) ProtoMessage() {} func (x *RedPacket) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[219] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[251] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -19860,7 +22604,7 @@ func (x *RedPacket) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacket.ProtoReflect.Descriptor instead. func (*RedPacket) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{219} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{251} } func (x *RedPacket) GetAppCode() string { @@ -20028,7 +22772,7 @@ type GetRedPacketConfigRequest struct { func (x *GetRedPacketConfigRequest) Reset() { *x = GetRedPacketConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[220] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[252] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20040,7 +22784,7 @@ func (x *GetRedPacketConfigRequest) String() string { func (*GetRedPacketConfigRequest) ProtoMessage() {} func (x *GetRedPacketConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[220] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[252] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20053,7 +22797,7 @@ func (x *GetRedPacketConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketConfigRequest.ProtoReflect.Descriptor instead. func (*GetRedPacketConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{220} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{252} } func (x *GetRedPacketConfigRequest) GetRequestId() string { @@ -20081,7 +22825,7 @@ type GetRedPacketConfigResponse struct { func (x *GetRedPacketConfigResponse) Reset() { *x = GetRedPacketConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[221] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[253] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20093,7 +22837,7 @@ func (x *GetRedPacketConfigResponse) String() string { func (*GetRedPacketConfigResponse) ProtoMessage() {} func (x *GetRedPacketConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[221] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[253] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20106,7 +22850,7 @@ func (x *GetRedPacketConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketConfigResponse.ProtoReflect.Descriptor instead. func (*GetRedPacketConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{221} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{253} } func (x *GetRedPacketConfigResponse) GetConfig() *RedPacketConfig { @@ -20142,7 +22886,7 @@ type UpdateRedPacketConfigRequest struct { func (x *UpdateRedPacketConfigRequest) Reset() { *x = UpdateRedPacketConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[222] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[254] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20154,7 +22898,7 @@ func (x *UpdateRedPacketConfigRequest) String() string { func (*UpdateRedPacketConfigRequest) ProtoMessage() {} func (x *UpdateRedPacketConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[222] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[254] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20167,7 +22911,7 @@ func (x *UpdateRedPacketConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRedPacketConfigRequest.ProtoReflect.Descriptor instead. func (*UpdateRedPacketConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{222} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{254} } func (x *UpdateRedPacketConfigRequest) GetRequestId() string { @@ -20251,7 +22995,7 @@ type UpdateRedPacketConfigResponse struct { func (x *UpdateRedPacketConfigResponse) Reset() { *x = UpdateRedPacketConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[223] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[255] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20263,7 +23007,7 @@ func (x *UpdateRedPacketConfigResponse) String() string { func (*UpdateRedPacketConfigResponse) ProtoMessage() {} func (x *UpdateRedPacketConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[223] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[255] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20276,7 +23020,7 @@ func (x *UpdateRedPacketConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRedPacketConfigResponse.ProtoReflect.Descriptor instead. func (*UpdateRedPacketConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{223} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{255} } func (x *UpdateRedPacketConfigResponse) GetConfig() *RedPacketConfig { @@ -20311,7 +23055,7 @@ type CreateRedPacketRequest struct { func (x *CreateRedPacketRequest) Reset() { *x = CreateRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[224] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[256] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20323,7 +23067,7 @@ func (x *CreateRedPacketRequest) String() string { func (*CreateRedPacketRequest) ProtoMessage() {} func (x *CreateRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[224] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[256] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20336,7 +23080,7 @@ func (x *CreateRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRedPacketRequest.ProtoReflect.Descriptor instead. func (*CreateRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{224} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{256} } func (x *CreateRedPacketRequest) GetRequestId() string { @@ -20414,7 +23158,7 @@ type CreateRedPacketResponse struct { func (x *CreateRedPacketResponse) Reset() { *x = CreateRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[225] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[257] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20426,7 +23170,7 @@ func (x *CreateRedPacketResponse) String() string { func (*CreateRedPacketResponse) ProtoMessage() {} func (x *CreateRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[225] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[257] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20439,7 +23183,7 @@ func (x *CreateRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRedPacketResponse.ProtoReflect.Descriptor instead. func (*CreateRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{225} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{257} } func (x *CreateRedPacketResponse) GetPacket() *RedPacket { @@ -20477,7 +23221,7 @@ type ClaimRedPacketRequest struct { func (x *ClaimRedPacketRequest) Reset() { *x = ClaimRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[226] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[258] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20489,7 +23233,7 @@ func (x *ClaimRedPacketRequest) String() string { func (*ClaimRedPacketRequest) ProtoMessage() {} func (x *ClaimRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[226] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[258] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20502,7 +23246,7 @@ func (x *ClaimRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ClaimRedPacketRequest.ProtoReflect.Descriptor instead. func (*ClaimRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{226} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{258} } func (x *ClaimRedPacketRequest) GetRequestId() string { @@ -20553,7 +23297,7 @@ type ClaimRedPacketResponse struct { func (x *ClaimRedPacketResponse) Reset() { *x = ClaimRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[227] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[259] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20565,7 +23309,7 @@ func (x *ClaimRedPacketResponse) String() string { func (*ClaimRedPacketResponse) ProtoMessage() {} func (x *ClaimRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[227] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[259] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20578,7 +23322,7 @@ func (x *ClaimRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ClaimRedPacketResponse.ProtoReflect.Descriptor instead. func (*ClaimRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{227} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{259} } func (x *ClaimRedPacketResponse) GetClaim() *RedPacketClaim { @@ -20630,7 +23374,7 @@ type ListRedPacketsRequest struct { func (x *ListRedPacketsRequest) Reset() { *x = ListRedPacketsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[228] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[260] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20642,7 +23386,7 @@ func (x *ListRedPacketsRequest) String() string { func (*ListRedPacketsRequest) ProtoMessage() {} func (x *ListRedPacketsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[228] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[260] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20655,7 +23399,7 @@ func (x *ListRedPacketsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRedPacketsRequest.ProtoReflect.Descriptor instead. func (*ListRedPacketsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{228} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{260} } func (x *ListRedPacketsRequest) GetRequestId() string { @@ -20754,7 +23498,7 @@ type ListRedPacketsResponse struct { func (x *ListRedPacketsResponse) Reset() { *x = ListRedPacketsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[229] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[261] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20766,7 +23510,7 @@ func (x *ListRedPacketsResponse) String() string { func (*ListRedPacketsResponse) ProtoMessage() {} func (x *ListRedPacketsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[229] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[261] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20779,7 +23523,7 @@ func (x *ListRedPacketsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRedPacketsResponse.ProtoReflect.Descriptor instead. func (*ListRedPacketsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{229} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{261} } func (x *ListRedPacketsResponse) GetPackets() []*RedPacket { @@ -20817,7 +23561,7 @@ type GetRedPacketRequest struct { func (x *GetRedPacketRequest) Reset() { *x = GetRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[230] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[262] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20829,7 +23573,7 @@ func (x *GetRedPacketRequest) String() string { func (*GetRedPacketRequest) ProtoMessage() {} func (x *GetRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[230] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[262] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20842,7 +23586,7 @@ func (x *GetRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketRequest.ProtoReflect.Descriptor instead. func (*GetRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{230} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{262} } func (x *GetRedPacketRequest) GetRequestId() string { @@ -20891,7 +23635,7 @@ type GetRedPacketResponse struct { func (x *GetRedPacketResponse) Reset() { *x = GetRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[231] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[263] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20903,7 +23647,7 @@ func (x *GetRedPacketResponse) String() string { func (*GetRedPacketResponse) ProtoMessage() {} func (x *GetRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[231] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[263] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20916,7 +23660,7 @@ func (x *GetRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketResponse.ProtoReflect.Descriptor instead. func (*GetRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{231} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{263} } func (x *GetRedPacketResponse) GetPacket() *RedPacket { @@ -20945,7 +23689,7 @@ type ExpireRedPacketsRequest struct { func (x *ExpireRedPacketsRequest) Reset() { *x = ExpireRedPacketsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[232] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[264] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -20957,7 +23701,7 @@ func (x *ExpireRedPacketsRequest) String() string { func (*ExpireRedPacketsRequest) ProtoMessage() {} func (x *ExpireRedPacketsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[232] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[264] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20970,7 +23714,7 @@ func (x *ExpireRedPacketsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExpireRedPacketsRequest.ProtoReflect.Descriptor instead. func (*ExpireRedPacketsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{232} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{264} } func (x *ExpireRedPacketsRequest) GetRequestId() string { @@ -21006,7 +23750,7 @@ type ExpireRedPacketsResponse struct { func (x *ExpireRedPacketsResponse) Reset() { *x = ExpireRedPacketsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[233] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[265] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -21018,7 +23762,7 @@ func (x *ExpireRedPacketsResponse) String() string { func (*ExpireRedPacketsResponse) ProtoMessage() {} func (x *ExpireRedPacketsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[233] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[265] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -21031,7 +23775,7 @@ func (x *ExpireRedPacketsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ExpireRedPacketsResponse.ProtoReflect.Descriptor instead. func (*ExpireRedPacketsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{233} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{265} } func (x *ExpireRedPacketsResponse) GetExpiredCount() int32 { @@ -21068,7 +23812,7 @@ type RetryRedPacketRefundRequest struct { func (x *RetryRedPacketRefundRequest) Reset() { *x = RetryRedPacketRefundRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[234] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[266] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -21080,7 +23824,7 @@ func (x *RetryRedPacketRefundRequest) String() string { func (*RetryRedPacketRefundRequest) ProtoMessage() {} func (x *RetryRedPacketRefundRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[234] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[266] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -21093,7 +23837,7 @@ func (x *RetryRedPacketRefundRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryRedPacketRefundRequest.ProtoReflect.Descriptor instead. func (*RetryRedPacketRefundRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{234} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{266} } func (x *RetryRedPacketRefundRequest) GetRequestId() string { @@ -21136,7 +23880,7 @@ type RetryRedPacketRefundResponse struct { func (x *RetryRedPacketRefundResponse) Reset() { *x = RetryRedPacketRefundResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[235] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[267] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -21148,7 +23892,7 @@ func (x *RetryRedPacketRefundResponse) String() string { func (*RetryRedPacketRefundResponse) ProtoMessage() {} func (x *RetryRedPacketRefundResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[235] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[267] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -21161,7 +23905,7 @@ func (x *RetryRedPacketRefundResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryRedPacketRefundResponse.ProtoReflect.Descriptor instead. func (*RetryRedPacketRefundResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{235} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{267} } func (x *RetryRedPacketRefundResponse) GetPacket() *RedPacket { @@ -21209,7 +23953,7 @@ type CronBatchRequest struct { func (x *CronBatchRequest) Reset() { *x = CronBatchRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[236] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[268] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -21221,7 +23965,7 @@ func (x *CronBatchRequest) String() string { func (*CronBatchRequest) ProtoMessage() {} func (x *CronBatchRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[236] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[268] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -21234,7 +23978,7 @@ func (x *CronBatchRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CronBatchRequest.ProtoReflect.Descriptor instead. func (*CronBatchRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{236} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{268} } func (x *CronBatchRequest) GetRequestId() string { @@ -21322,7 +24066,7 @@ type CronBatchResponse struct { func (x *CronBatchResponse) Reset() { *x = CronBatchResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[237] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[269] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -21334,7 +24078,7 @@ func (x *CronBatchResponse) String() string { func (*CronBatchResponse) ProtoMessage() {} func (x *CronBatchResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[237] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[269] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -21347,7 +24091,7 @@ func (x *CronBatchResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CronBatchResponse.ProtoReflect.Descriptor instead. func (*CronBatchResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{237} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{269} } func (x *CronBatchResponse) GetClaimedCount() int32 { @@ -21409,7 +24153,7 @@ type ResourceShopPurchaseOrder struct { func (x *ResourceShopPurchaseOrder) Reset() { *x = ResourceShopPurchaseOrder{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[238] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[270] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -21421,7 +24165,7 @@ func (x *ResourceShopPurchaseOrder) String() string { func (*ResourceShopPurchaseOrder) ProtoMessage() {} func (x *ResourceShopPurchaseOrder) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[238] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[270] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -21434,7 +24178,7 @@ func (x *ResourceShopPurchaseOrder) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceShopPurchaseOrder.ProtoReflect.Descriptor instead. func (*ResourceShopPurchaseOrder) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{238} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{270} } func (x *ResourceShopPurchaseOrder) GetAppCode() string { @@ -21559,7 +24303,7 @@ type ListResourceShopPurchaseOrdersRequest struct { func (x *ListResourceShopPurchaseOrdersRequest) Reset() { *x = ListResourceShopPurchaseOrdersRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[239] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[271] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -21571,7 +24315,7 @@ func (x *ListResourceShopPurchaseOrdersRequest) String() string { func (*ListResourceShopPurchaseOrdersRequest) ProtoMessage() {} func (x *ListResourceShopPurchaseOrdersRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[239] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[271] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -21584,7 +24328,7 @@ func (x *ListResourceShopPurchaseOrdersRequest) ProtoReflect() protoreflect.Mess // Deprecated: Use ListResourceShopPurchaseOrdersRequest.ProtoReflect.Descriptor instead. func (*ListResourceShopPurchaseOrdersRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{239} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{271} } func (x *ListResourceShopPurchaseOrdersRequest) GetRequestId() string { @@ -21654,7 +24398,7 @@ type ListResourceShopPurchaseOrdersResponse struct { func (x *ListResourceShopPurchaseOrdersResponse) Reset() { *x = ListResourceShopPurchaseOrdersResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[240] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[272] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -21666,7 +24410,7 @@ func (x *ListResourceShopPurchaseOrdersResponse) String() string { func (*ListResourceShopPurchaseOrdersResponse) ProtoMessage() {} func (x *ListResourceShopPurchaseOrdersResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[240] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[272] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -21679,7 +24423,7 @@ func (x *ListResourceShopPurchaseOrdersResponse) ProtoReflect() protoreflect.Mes // Deprecated: Use ListResourceShopPurchaseOrdersResponse.ProtoReflect.Descriptor instead. func (*ListResourceShopPurchaseOrdersResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{240} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{272} } func (x *ListResourceShopPurchaseOrdersResponse) GetOrders() []*ResourceShopPurchaseOrder { @@ -21707,7 +24451,7 @@ type GetGiftCatalogVersionRequest struct { func (x *GetGiftCatalogVersionRequest) Reset() { *x = GetGiftCatalogVersionRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[241] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[273] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -21719,7 +24463,7 @@ func (x *GetGiftCatalogVersionRequest) String() string { func (*GetGiftCatalogVersionRequest) ProtoMessage() {} func (x *GetGiftCatalogVersionRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[241] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[273] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -21732,7 +24476,7 @@ func (x *GetGiftCatalogVersionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetGiftCatalogVersionRequest.ProtoReflect.Descriptor instead. func (*GetGiftCatalogVersionRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{241} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{273} } func (x *GetGiftCatalogVersionRequest) GetRequestId() string { @@ -21759,7 +24503,7 @@ type GetGiftCatalogVersionResponse struct { func (x *GetGiftCatalogVersionResponse) Reset() { *x = GetGiftCatalogVersionResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[242] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[274] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -21771,7 +24515,7 @@ func (x *GetGiftCatalogVersionResponse) String() string { func (*GetGiftCatalogVersionResponse) ProtoMessage() {} func (x *GetGiftCatalogVersionResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[242] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[274] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -21784,7 +24528,7 @@ func (x *GetGiftCatalogVersionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetGiftCatalogVersionResponse.ProtoReflect.Descriptor instead. func (*GetGiftCatalogVersionResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{242} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{274} } func (x *GetGiftCatalogVersionResponse) GetVersion() int64 { @@ -23929,1351 +26673,1816 @@ var file_proto_wallet_v1_wallet_proto_rawDesc = []byte{ 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, 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, + 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, 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, + 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, 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, + 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, - 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, + 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, 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, + 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, - 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, + 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, 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, + 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, 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, + 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, - 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, + 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, 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, + 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, 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, + 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, - 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, + 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, 0xe1, 0x03, 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, 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, + 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, 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, 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, + 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, 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, 0xe1, 0x03, 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, 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, 0xfc, 0x04, 0x0a, 0x08, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, - 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, - 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x70, 0x72, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x69, 0x6e, - 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, - 0x73, 0x12, 0x37, 0x0a, 0x18, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x15, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x41, 0x0a, 0x0c, 0x72, 0x65, - 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, - 0x52, 0x0b, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x21, 0x0a, - 0x0c, 0x63, 0x61, 0x6e, 0x5f, 0x70, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0b, 0x63, 0x61, 0x6e, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, - 0x34, 0x0a, 0x16, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x67, 0x61, 0x74, 0x65, - 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x14, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x47, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x41, 0x0a, 0x1d, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, - 0x64, 0x5f, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, - 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1a, 0x72, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x43, 0x6f, - 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x19, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x75, 0x73, 0x65, - 0x72, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, - 0x75, 0x6e, 0x74, 0x12, 0x34, 0x0a, 0x16, 0x70, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x5f, - 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0d, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x14, 0x70, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x4c, 0x6f, 0x63, - 0x6b, 0x65, 0x64, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, - 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0f, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, - 0x73, 0x22, 0xd0, 0x01, 0x0a, 0x07, 0x55, 0x73, 0x65, 0x72, 0x56, 0x69, 0x70, 0x12, 0x17, 0x0a, - 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, - 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, - 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, - 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, - 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, - 0x41, 0x74, 0x4d, 0x73, 0x22, 0x6b, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x69, 0x70, 0x50, - 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, + 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, 0x8b, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x69, 0x70, 0x50, 0x61, 0x63, - 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, - 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, + 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, 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, + 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, - 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x22, - 0x64, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x56, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, - 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, - 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x3e, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x56, 0x69, - 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x03, 0x76, 0x69, 0x70, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x56, 0x69, 0x70, - 0x52, 0x03, 0x76, 0x69, 0x70, 0x22, 0x7d, 0x0a, 0x12, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, - 0x65, 0x56, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, - 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, - 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, - 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, - 0x65, 0x76, 0x65, 0x6c, 0x22, 0x93, 0x02, 0x0a, 0x13, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, - 0x65, 0x56, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2a, - 0x0a, 0x03, 0x76, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, - 0x65, 0x72, 0x56, 0x69, 0x70, 0x52, 0x03, 0x76, 0x69, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, - 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, - 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6f, 0x69, - 0x6e, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x63, 0x6f, 0x69, 0x6e, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0c, 0x72, 0x65, 0x77, 0x61, 0x72, - 0x64, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x56, 0x69, 0x70, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0b, 0x72, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x22, 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, + 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, 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, + 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, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x21, 0x0a, 0x0c, - 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, - 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x22, 0xce, 0x01, 0x0a, 0x10, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x56, 0x69, 0x70, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2a, 0x0a, - 0x03, 0x76, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, - 0x72, 0x56, 0x69, 0x70, 0x52, 0x03, 0x76, 0x69, 0x70, 0x12, 0x41, 0x0a, 0x0c, 0x72, 0x65, 0x77, - 0x61, 0x72, 0x64, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x56, 0x69, 0x70, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x52, - 0x0b, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x24, 0x0a, 0x0e, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, - 0x4d, 0x73, 0x22, 0xb1, 0x02, 0x0a, 0x12, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x4c, - 0x65, 0x76, 0x65, 0x6c, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, - 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, - 0x72, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x09, 0x70, 0x72, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x37, 0x0a, 0x18, 0x72, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, - 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x72, - 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, - 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x1d, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, - 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1a, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x43, 0x6f, 0x69, 0x6e, - 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x55, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, - 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x75, 0x0a, - 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x6c, - 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, - 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x12, 0x24, - 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, - 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x3b, - 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, - 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x49, 0x6e, - 0x70, 0x75, 0x74, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6f, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, - 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x77, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, - 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, - 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 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, + 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, 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, + 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, @@ -25282,55 +28491,17 @@ var file_proto_wallet_v1_wallet_proto_rawDesc = []byte{ 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, + 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, @@ -25341,1293 +28512,1489 @@ var file_proto_wallet_v1_wallet_proto_rawDesc = []byte{ 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, + 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, 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, + 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, 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, + 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, 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, 0x32, 0xe0, - 0x02, 0x0a, 0x11, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x43, 0x72, 0x6f, 0x6e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x6e, 0x0a, 0x25, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x48, - 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x53, 0x65, - 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x21, 0x2e, + 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, 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, 0x72, 0x0a, 0x29, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x48, - 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x48, 0x61, 0x6c, 0x66, 0x4d, 0x6f, 0x6e, - 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, - 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x1e, 0x50, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x4d, 0x6f, 0x6e, - 0x74, 0x68, 0x45, 0x6e, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, - 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, - 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, - 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x32, 0x91, 0x60, 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, + 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, 0xe1, 0x6a, 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, 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, - 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, + 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, 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, 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, + 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, 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, + 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, 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, 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, + 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, 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, 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, + 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, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, 0x0a, 0x0f, 0x4c, 0x69, - 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x27, 0x2e, + 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x64, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x73, 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, - 0x65, 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, + 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, 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, + 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, 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, + 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, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x12, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x2a, 0x2e, 0x68, - 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, - 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x6a, 0x0a, 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, + 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, - 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, + 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, 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, 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, + 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, 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, + 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, 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, 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, + 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, 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, + 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, - 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, + 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, 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, + 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, 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, + 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, 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, + 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, - 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, 0x4f, 0x0a, 0x08, 0x47, - 0x65, 0x74, 0x4d, 0x79, 0x56, 0x69, 0x70, 0x12, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 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, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, - 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, - 0x79, 0x56, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x0b, - 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x56, 0x69, 0x70, 0x12, 0x23, 0x2e, 0x68, 0x79, - 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, - 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x56, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x56, 0x69, 0x70, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 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, 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, + 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, - 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, + 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, 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, + 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, - 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, + 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, 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, + 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, - 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, + 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, 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, + 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, } var ( @@ -26642,7 +30009,7 @@ func file_proto_wallet_v1_wallet_proto_rawDescGZIP() []byte { return file_proto_wallet_v1_wallet_proto_rawDescData } -var file_proto_wallet_v1_wallet_proto_msgTypes = make([]protoimpl.MessageInfo, 244) +var file_proto_wallet_v1_wallet_proto_msgTypes = make([]protoimpl.MessageInfo, 276) var file_proto_wallet_v1_wallet_proto_goTypes = []any{ (*DebitGiftRequest)(nil), // 0: hyapp.wallet.v1.DebitGiftRequest (*DebitDirectGiftRequest)(nil), // 1: hyapp.wallet.v1.DebitDirectGiftRequest @@ -26764,130 +30131,162 @@ var file_proto_wallet_v1_wallet_proto_goTypes = []any{ (*GetRechargeBillSummaryRequest)(nil), // 117: hyapp.wallet.v1.GetRechargeBillSummaryRequest (*RechargeBillSummaryBucket)(nil), // 118: hyapp.wallet.v1.RechargeBillSummaryBucket (*GetRechargeBillSummaryResponse)(nil), // 119: hyapp.wallet.v1.GetRechargeBillSummaryResponse - (*GetRechargeBillOverviewRequest)(nil), // 120: hyapp.wallet.v1.GetRechargeBillOverviewRequest - (*RechargeBillDailyBucket)(nil), // 121: hyapp.wallet.v1.RechargeBillDailyBucket - (*RechargeBillRegionBucket)(nil), // 122: hyapp.wallet.v1.RechargeBillRegionBucket - (*RechargeBillGooglePaidStats)(nil), // 123: hyapp.wallet.v1.RechargeBillGooglePaidStats - (*RechargeBillSalaryTransferStats)(nil), // 124: hyapp.wallet.v1.RechargeBillSalaryTransferStats - (*GetRechargeBillOverviewResponse)(nil), // 125: hyapp.wallet.v1.GetRechargeBillOverviewResponse - (*RefreshGooglePaymentPricesRequest)(nil), // 126: hyapp.wallet.v1.RefreshGooglePaymentPricesRequest - (*GooglePaymentPrice)(nil), // 127: hyapp.wallet.v1.GooglePaymentPrice - (*RefreshGooglePaymentPricesResponse)(nil), // 128: hyapp.wallet.v1.RefreshGooglePaymentPricesResponse - (*WalletFeatureFlags)(nil), // 129: hyapp.wallet.v1.WalletFeatureFlags - (*GetWalletOverviewRequest)(nil), // 130: hyapp.wallet.v1.GetWalletOverviewRequest - (*GetWalletOverviewResponse)(nil), // 131: hyapp.wallet.v1.GetWalletOverviewResponse - (*WalletValueSummary)(nil), // 132: hyapp.wallet.v1.WalletValueSummary - (*GetWalletValueSummaryRequest)(nil), // 133: hyapp.wallet.v1.GetWalletValueSummaryRequest - (*GetWalletValueSummaryResponse)(nil), // 134: hyapp.wallet.v1.GetWalletValueSummaryResponse - (*GiftWallItem)(nil), // 135: hyapp.wallet.v1.GiftWallItem - (*GetUserGiftWallRequest)(nil), // 136: hyapp.wallet.v1.GetUserGiftWallRequest - (*GetUserGiftWallResponse)(nil), // 137: hyapp.wallet.v1.GetUserGiftWallResponse - (*RechargeProduct)(nil), // 138: hyapp.wallet.v1.RechargeProduct - (*ListRechargeProductsRequest)(nil), // 139: hyapp.wallet.v1.ListRechargeProductsRequest - (*ListRechargeProductsResponse)(nil), // 140: hyapp.wallet.v1.ListRechargeProductsResponse - (*ConfirmGooglePaymentRequest)(nil), // 141: hyapp.wallet.v1.ConfirmGooglePaymentRequest - (*ConfirmGooglePaymentResponse)(nil), // 142: hyapp.wallet.v1.ConfirmGooglePaymentResponse - (*ListAdminRechargeProductsRequest)(nil), // 143: hyapp.wallet.v1.ListAdminRechargeProductsRequest - (*ListAdminRechargeProductsResponse)(nil), // 144: hyapp.wallet.v1.ListAdminRechargeProductsResponse - (*CreateRechargeProductRequest)(nil), // 145: hyapp.wallet.v1.CreateRechargeProductRequest - (*UpdateRechargeProductRequest)(nil), // 146: hyapp.wallet.v1.UpdateRechargeProductRequest - (*DeleteRechargeProductRequest)(nil), // 147: hyapp.wallet.v1.DeleteRechargeProductRequest - (*RechargeProductResponse)(nil), // 148: hyapp.wallet.v1.RechargeProductResponse - (*DeleteRechargeProductResponse)(nil), // 149: hyapp.wallet.v1.DeleteRechargeProductResponse - (*ThirdPartyPaymentMethod)(nil), // 150: hyapp.wallet.v1.ThirdPartyPaymentMethod - (*ThirdPartyPaymentChannel)(nil), // 151: hyapp.wallet.v1.ThirdPartyPaymentChannel - (*ListThirdPartyPaymentChannelsRequest)(nil), // 152: hyapp.wallet.v1.ListThirdPartyPaymentChannelsRequest - (*ListThirdPartyPaymentChannelsResponse)(nil), // 153: hyapp.wallet.v1.ListThirdPartyPaymentChannelsResponse - (*SetThirdPartyPaymentMethodStatusRequest)(nil), // 154: hyapp.wallet.v1.SetThirdPartyPaymentMethodStatusRequest - (*ThirdPartyPaymentMethodResponse)(nil), // 155: hyapp.wallet.v1.ThirdPartyPaymentMethodResponse - (*UpdateThirdPartyPaymentRateRequest)(nil), // 156: hyapp.wallet.v1.UpdateThirdPartyPaymentRateRequest - (*ThirdPartyPaymentMethodSyncIssue)(nil), // 157: hyapp.wallet.v1.ThirdPartyPaymentMethodSyncIssue - (*SyncThirdPartyPaymentMethodsRequest)(nil), // 158: hyapp.wallet.v1.SyncThirdPartyPaymentMethodsRequest - (*SyncThirdPartyPaymentMethodsResponse)(nil), // 159: hyapp.wallet.v1.SyncThirdPartyPaymentMethodsResponse - (*H5RechargeOptionsRequest)(nil), // 160: hyapp.wallet.v1.H5RechargeOptionsRequest - (*H5RechargeOptionsResponse)(nil), // 161: hyapp.wallet.v1.H5RechargeOptionsResponse - (*ExternalRechargeOrder)(nil), // 162: hyapp.wallet.v1.ExternalRechargeOrder - (*CreateH5RechargeOrderRequest)(nil), // 163: hyapp.wallet.v1.CreateH5RechargeOrderRequest - (*CreateTemporaryRechargeOrderRequest)(nil), // 164: hyapp.wallet.v1.CreateTemporaryRechargeOrderRequest - (*GetTemporaryRechargeOrderRequest)(nil), // 165: hyapp.wallet.v1.GetTemporaryRechargeOrderRequest - (*ListTemporaryRechargeOrdersRequest)(nil), // 166: hyapp.wallet.v1.ListTemporaryRechargeOrdersRequest - (*ListTemporaryRechargeOrdersResponse)(nil), // 167: hyapp.wallet.v1.ListTemporaryRechargeOrdersResponse - (*SubmitH5RechargeTxRequest)(nil), // 168: hyapp.wallet.v1.SubmitH5RechargeTxRequest - (*GetH5RechargeOrderRequest)(nil), // 169: hyapp.wallet.v1.GetH5RechargeOrderRequest - (*H5RechargeOrderResponse)(nil), // 170: hyapp.wallet.v1.H5RechargeOrderResponse - (*VerifyCoinSellerRechargeReceiptRequest)(nil), // 171: hyapp.wallet.v1.VerifyCoinSellerRechargeReceiptRequest - (*VerifyCoinSellerRechargeReceiptResponse)(nil), // 172: hyapp.wallet.v1.VerifyCoinSellerRechargeReceiptResponse - (*HandleMifapayNotifyRequest)(nil), // 173: hyapp.wallet.v1.HandleMifapayNotifyRequest - (*HandleMifapayNotifyResponse)(nil), // 174: hyapp.wallet.v1.HandleMifapayNotifyResponse - (*HandleV5PayNotifyRequest)(nil), // 175: hyapp.wallet.v1.HandleV5PayNotifyRequest - (*HandleV5PayNotifyResponse)(nil), // 176: hyapp.wallet.v1.HandleV5PayNotifyResponse - (*DiamondExchangeRule)(nil), // 177: hyapp.wallet.v1.DiamondExchangeRule - (*GetDiamondExchangeConfigRequest)(nil), // 178: hyapp.wallet.v1.GetDiamondExchangeConfigRequest - (*GetDiamondExchangeConfigResponse)(nil), // 179: hyapp.wallet.v1.GetDiamondExchangeConfigResponse - (*WalletTransaction)(nil), // 180: hyapp.wallet.v1.WalletTransaction - (*ListWalletTransactionsRequest)(nil), // 181: hyapp.wallet.v1.ListWalletTransactionsRequest - (*ListWalletTransactionsResponse)(nil), // 182: hyapp.wallet.v1.ListWalletTransactionsResponse - (*VipRewardItem)(nil), // 183: hyapp.wallet.v1.VipRewardItem - (*VipLevel)(nil), // 184: hyapp.wallet.v1.VipLevel - (*UserVip)(nil), // 185: hyapp.wallet.v1.UserVip - (*ListVipPackagesRequest)(nil), // 186: hyapp.wallet.v1.ListVipPackagesRequest - (*ListVipPackagesResponse)(nil), // 187: hyapp.wallet.v1.ListVipPackagesResponse - (*GetMyVipRequest)(nil), // 188: hyapp.wallet.v1.GetMyVipRequest - (*GetMyVipResponse)(nil), // 189: hyapp.wallet.v1.GetMyVipResponse - (*PurchaseVipRequest)(nil), // 190: hyapp.wallet.v1.PurchaseVipRequest - (*PurchaseVipResponse)(nil), // 191: hyapp.wallet.v1.PurchaseVipResponse - (*DebitCPBreakupFeeRequest)(nil), // 192: hyapp.wallet.v1.DebitCPBreakupFeeRequest - (*DebitCPBreakupFeeResponse)(nil), // 193: hyapp.wallet.v1.DebitCPBreakupFeeResponse - (*DebitWheelDrawRequest)(nil), // 194: hyapp.wallet.v1.DebitWheelDrawRequest - (*DebitWheelDrawResponse)(nil), // 195: hyapp.wallet.v1.DebitWheelDrawResponse - (*GrantVipRequest)(nil), // 196: hyapp.wallet.v1.GrantVipRequest - (*GrantVipResponse)(nil), // 197: hyapp.wallet.v1.GrantVipResponse - (*AdminVipLevelInput)(nil), // 198: hyapp.wallet.v1.AdminVipLevelInput - (*ListAdminVipLevelsRequest)(nil), // 199: hyapp.wallet.v1.ListAdminVipLevelsRequest - (*ListAdminVipLevelsResponse)(nil), // 200: hyapp.wallet.v1.ListAdminVipLevelsResponse - (*UpdateAdminVipLevelsRequest)(nil), // 201: hyapp.wallet.v1.UpdateAdminVipLevelsRequest - (*UpdateAdminVipLevelsResponse)(nil), // 202: hyapp.wallet.v1.UpdateAdminVipLevelsResponse - (*CreditTaskRewardRequest)(nil), // 203: hyapp.wallet.v1.CreditTaskRewardRequest - (*CreditTaskRewardResponse)(nil), // 204: hyapp.wallet.v1.CreditTaskRewardResponse - (*CreditLuckyGiftRewardRequest)(nil), // 205: hyapp.wallet.v1.CreditLuckyGiftRewardRequest - (*CreditLuckyGiftRewardResponse)(nil), // 206: hyapp.wallet.v1.CreditLuckyGiftRewardResponse - (*CreditWheelRewardRequest)(nil), // 207: hyapp.wallet.v1.CreditWheelRewardRequest - (*CreditWheelRewardResponse)(nil), // 208: hyapp.wallet.v1.CreditWheelRewardResponse - (*CreditRoomTurnoverRewardRequest)(nil), // 209: hyapp.wallet.v1.CreditRoomTurnoverRewardRequest - (*CreditRoomTurnoverRewardResponse)(nil), // 210: hyapp.wallet.v1.CreditRoomTurnoverRewardResponse - (*CreditInviteActivityRewardRequest)(nil), // 211: hyapp.wallet.v1.CreditInviteActivityRewardRequest - (*CreditInviteActivityRewardResponse)(nil), // 212: hyapp.wallet.v1.CreditInviteActivityRewardResponse - (*CreditAgencyOpeningRewardRequest)(nil), // 213: hyapp.wallet.v1.CreditAgencyOpeningRewardRequest - (*CreditAgencyOpeningRewardResponse)(nil), // 214: hyapp.wallet.v1.CreditAgencyOpeningRewardResponse - (*ApplyGameCoinChangeRequest)(nil), // 215: hyapp.wallet.v1.ApplyGameCoinChangeRequest - (*ApplyGameCoinChangeResponse)(nil), // 216: hyapp.wallet.v1.ApplyGameCoinChangeResponse - (*RedPacketConfig)(nil), // 217: hyapp.wallet.v1.RedPacketConfig - (*RedPacketClaim)(nil), // 218: hyapp.wallet.v1.RedPacketClaim - (*RedPacket)(nil), // 219: hyapp.wallet.v1.RedPacket - (*GetRedPacketConfigRequest)(nil), // 220: hyapp.wallet.v1.GetRedPacketConfigRequest - (*GetRedPacketConfigResponse)(nil), // 221: hyapp.wallet.v1.GetRedPacketConfigResponse - (*UpdateRedPacketConfigRequest)(nil), // 222: hyapp.wallet.v1.UpdateRedPacketConfigRequest - (*UpdateRedPacketConfigResponse)(nil), // 223: hyapp.wallet.v1.UpdateRedPacketConfigResponse - (*CreateRedPacketRequest)(nil), // 224: hyapp.wallet.v1.CreateRedPacketRequest - (*CreateRedPacketResponse)(nil), // 225: hyapp.wallet.v1.CreateRedPacketResponse - (*ClaimRedPacketRequest)(nil), // 226: hyapp.wallet.v1.ClaimRedPacketRequest - (*ClaimRedPacketResponse)(nil), // 227: hyapp.wallet.v1.ClaimRedPacketResponse - (*ListRedPacketsRequest)(nil), // 228: hyapp.wallet.v1.ListRedPacketsRequest - (*ListRedPacketsResponse)(nil), // 229: hyapp.wallet.v1.ListRedPacketsResponse - (*GetRedPacketRequest)(nil), // 230: hyapp.wallet.v1.GetRedPacketRequest - (*GetRedPacketResponse)(nil), // 231: hyapp.wallet.v1.GetRedPacketResponse - (*ExpireRedPacketsRequest)(nil), // 232: hyapp.wallet.v1.ExpireRedPacketsRequest - (*ExpireRedPacketsResponse)(nil), // 233: hyapp.wallet.v1.ExpireRedPacketsResponse - (*RetryRedPacketRefundRequest)(nil), // 234: hyapp.wallet.v1.RetryRedPacketRefundRequest - (*RetryRedPacketRefundResponse)(nil), // 235: hyapp.wallet.v1.RetryRedPacketRefundResponse - (*CronBatchRequest)(nil), // 236: hyapp.wallet.v1.CronBatchRequest - (*CronBatchResponse)(nil), // 237: hyapp.wallet.v1.CronBatchResponse - (*ResourceShopPurchaseOrder)(nil), // 238: hyapp.wallet.v1.ResourceShopPurchaseOrder - (*ListResourceShopPurchaseOrdersRequest)(nil), // 239: hyapp.wallet.v1.ListResourceShopPurchaseOrdersRequest - (*ListResourceShopPurchaseOrdersResponse)(nil), // 240: hyapp.wallet.v1.ListResourceShopPurchaseOrdersResponse - (*GetGiftCatalogVersionRequest)(nil), // 241: hyapp.wallet.v1.GetGiftCatalogVersionRequest - (*GetGiftCatalogVersionResponse)(nil), // 242: hyapp.wallet.v1.GetGiftCatalogVersionResponse - nil, // 243: hyapp.wallet.v1.HandleV5PayNotifyRequest.FieldsEntry + (*UserRechargeStats)(nil), // 120: hyapp.wallet.v1.UserRechargeStats + (*BatchGetUserRechargeStatsRequest)(nil), // 121: hyapp.wallet.v1.BatchGetUserRechargeStatsRequest + (*BatchGetUserRechargeStatsResponse)(nil), // 122: hyapp.wallet.v1.BatchGetUserRechargeStatsResponse + (*GetRechargeBillOverviewRequest)(nil), // 123: hyapp.wallet.v1.GetRechargeBillOverviewRequest + (*RechargeBillDailyBucket)(nil), // 124: hyapp.wallet.v1.RechargeBillDailyBucket + (*RechargeBillRegionBucket)(nil), // 125: hyapp.wallet.v1.RechargeBillRegionBucket + (*RechargeBillGooglePaidStats)(nil), // 126: hyapp.wallet.v1.RechargeBillGooglePaidStats + (*RechargeBillSalaryTransferStats)(nil), // 127: hyapp.wallet.v1.RechargeBillSalaryTransferStats + (*GetRechargeBillOverviewResponse)(nil), // 128: hyapp.wallet.v1.GetRechargeBillOverviewResponse + (*RefreshGooglePaymentPricesRequest)(nil), // 129: hyapp.wallet.v1.RefreshGooglePaymentPricesRequest + (*GooglePaymentPrice)(nil), // 130: hyapp.wallet.v1.GooglePaymentPrice + (*RefreshGooglePaymentPricesResponse)(nil), // 131: hyapp.wallet.v1.RefreshGooglePaymentPricesResponse + (*WalletFeatureFlags)(nil), // 132: hyapp.wallet.v1.WalletFeatureFlags + (*GetWalletOverviewRequest)(nil), // 133: hyapp.wallet.v1.GetWalletOverviewRequest + (*GetWalletOverviewResponse)(nil), // 134: hyapp.wallet.v1.GetWalletOverviewResponse + (*WalletValueSummary)(nil), // 135: hyapp.wallet.v1.WalletValueSummary + (*GetWalletValueSummaryRequest)(nil), // 136: hyapp.wallet.v1.GetWalletValueSummaryRequest + (*GetWalletValueSummaryResponse)(nil), // 137: hyapp.wallet.v1.GetWalletValueSummaryResponse + (*GiftWallItem)(nil), // 138: hyapp.wallet.v1.GiftWallItem + (*GetUserGiftWallRequest)(nil), // 139: hyapp.wallet.v1.GetUserGiftWallRequest + (*GetUserGiftWallResponse)(nil), // 140: hyapp.wallet.v1.GetUserGiftWallResponse + (*RechargeProduct)(nil), // 141: hyapp.wallet.v1.RechargeProduct + (*ListRechargeProductsRequest)(nil), // 142: hyapp.wallet.v1.ListRechargeProductsRequest + (*ListRechargeProductsResponse)(nil), // 143: hyapp.wallet.v1.ListRechargeProductsResponse + (*ConfirmGooglePaymentRequest)(nil), // 144: hyapp.wallet.v1.ConfirmGooglePaymentRequest + (*ConfirmGooglePaymentResponse)(nil), // 145: hyapp.wallet.v1.ConfirmGooglePaymentResponse + (*ListAdminRechargeProductsRequest)(nil), // 146: hyapp.wallet.v1.ListAdminRechargeProductsRequest + (*ListAdminRechargeProductsResponse)(nil), // 147: hyapp.wallet.v1.ListAdminRechargeProductsResponse + (*CreateRechargeProductRequest)(nil), // 148: hyapp.wallet.v1.CreateRechargeProductRequest + (*UpdateRechargeProductRequest)(nil), // 149: hyapp.wallet.v1.UpdateRechargeProductRequest + (*DeleteRechargeProductRequest)(nil), // 150: hyapp.wallet.v1.DeleteRechargeProductRequest + (*RechargeProductResponse)(nil), // 151: hyapp.wallet.v1.RechargeProductResponse + (*DeleteRechargeProductResponse)(nil), // 152: hyapp.wallet.v1.DeleteRechargeProductResponse + (*ThirdPartyPaymentMethod)(nil), // 153: hyapp.wallet.v1.ThirdPartyPaymentMethod + (*ThirdPartyPaymentChannel)(nil), // 154: hyapp.wallet.v1.ThirdPartyPaymentChannel + (*ListThirdPartyPaymentChannelsRequest)(nil), // 155: hyapp.wallet.v1.ListThirdPartyPaymentChannelsRequest + (*ListThirdPartyPaymentChannelsResponse)(nil), // 156: hyapp.wallet.v1.ListThirdPartyPaymentChannelsResponse + (*SetThirdPartyPaymentMethodStatusRequest)(nil), // 157: hyapp.wallet.v1.SetThirdPartyPaymentMethodStatusRequest + (*ThirdPartyPaymentMethodResponse)(nil), // 158: hyapp.wallet.v1.ThirdPartyPaymentMethodResponse + (*UpdateThirdPartyPaymentRateRequest)(nil), // 159: hyapp.wallet.v1.UpdateThirdPartyPaymentRateRequest + (*ThirdPartyPaymentMethodSyncIssue)(nil), // 160: hyapp.wallet.v1.ThirdPartyPaymentMethodSyncIssue + (*SyncThirdPartyPaymentMethodsRequest)(nil), // 161: hyapp.wallet.v1.SyncThirdPartyPaymentMethodsRequest + (*SyncThirdPartyPaymentMethodsResponse)(nil), // 162: hyapp.wallet.v1.SyncThirdPartyPaymentMethodsResponse + (*H5RechargeOptionsRequest)(nil), // 163: hyapp.wallet.v1.H5RechargeOptionsRequest + (*H5RechargeOptionsResponse)(nil), // 164: hyapp.wallet.v1.H5RechargeOptionsResponse + (*ExternalRechargeOrder)(nil), // 165: hyapp.wallet.v1.ExternalRechargeOrder + (*CreateH5RechargeOrderRequest)(nil), // 166: hyapp.wallet.v1.CreateH5RechargeOrderRequest + (*CreateTemporaryRechargeOrderRequest)(nil), // 167: hyapp.wallet.v1.CreateTemporaryRechargeOrderRequest + (*GetTemporaryRechargeOrderRequest)(nil), // 168: hyapp.wallet.v1.GetTemporaryRechargeOrderRequest + (*ListTemporaryRechargeOrdersRequest)(nil), // 169: hyapp.wallet.v1.ListTemporaryRechargeOrdersRequest + (*ListTemporaryRechargeOrdersResponse)(nil), // 170: hyapp.wallet.v1.ListTemporaryRechargeOrdersResponse + (*SubmitH5RechargeTxRequest)(nil), // 171: hyapp.wallet.v1.SubmitH5RechargeTxRequest + (*GetH5RechargeOrderRequest)(nil), // 172: hyapp.wallet.v1.GetH5RechargeOrderRequest + (*H5RechargeOrderResponse)(nil), // 173: hyapp.wallet.v1.H5RechargeOrderResponse + (*VerifyCoinSellerRechargeReceiptRequest)(nil), // 174: hyapp.wallet.v1.VerifyCoinSellerRechargeReceiptRequest + (*VerifyCoinSellerRechargeReceiptResponse)(nil), // 175: hyapp.wallet.v1.VerifyCoinSellerRechargeReceiptResponse + (*HandleMifapayNotifyRequest)(nil), // 176: hyapp.wallet.v1.HandleMifapayNotifyRequest + (*HandleMifapayNotifyResponse)(nil), // 177: hyapp.wallet.v1.HandleMifapayNotifyResponse + (*HandleV5PayNotifyRequest)(nil), // 178: hyapp.wallet.v1.HandleV5PayNotifyRequest + (*HandleV5PayNotifyResponse)(nil), // 179: hyapp.wallet.v1.HandleV5PayNotifyResponse + (*DiamondExchangeRule)(nil), // 180: hyapp.wallet.v1.DiamondExchangeRule + (*GetDiamondExchangeConfigRequest)(nil), // 181: hyapp.wallet.v1.GetDiamondExchangeConfigRequest + (*GetDiamondExchangeConfigResponse)(nil), // 182: hyapp.wallet.v1.GetDiamondExchangeConfigResponse + (*WalletTransaction)(nil), // 183: hyapp.wallet.v1.WalletTransaction + (*ListWalletTransactionsRequest)(nil), // 184: hyapp.wallet.v1.ListWalletTransactionsRequest + (*ListWalletTransactionsResponse)(nil), // 185: hyapp.wallet.v1.ListWalletTransactionsResponse + (*VipRewardItem)(nil), // 186: hyapp.wallet.v1.VipRewardItem + (*VipProgramConfig)(nil), // 187: hyapp.wallet.v1.VipProgramConfig + (*VipBenefit)(nil), // 188: hyapp.wallet.v1.VipBenefit + (*VipLevel)(nil), // 189: hyapp.wallet.v1.VipLevel + (*UserVip)(nil), // 190: hyapp.wallet.v1.UserVip + (*VipTrialCard)(nil), // 191: hyapp.wallet.v1.VipTrialCard + (*VipUserSettings)(nil), // 192: hyapp.wallet.v1.VipUserSettings + (*VipState)(nil), // 193: hyapp.wallet.v1.VipState + (*ListVipPackagesRequest)(nil), // 194: hyapp.wallet.v1.ListVipPackagesRequest + (*ListVipPackagesResponse)(nil), // 195: hyapp.wallet.v1.ListVipPackagesResponse + (*GetMyVipRequest)(nil), // 196: hyapp.wallet.v1.GetMyVipRequest + (*GetMyVipResponse)(nil), // 197: hyapp.wallet.v1.GetMyVipResponse + (*PurchaseVipRequest)(nil), // 198: hyapp.wallet.v1.PurchaseVipRequest + (*PurchaseVipResponse)(nil), // 199: hyapp.wallet.v1.PurchaseVipResponse + (*DebitCPBreakupFeeRequest)(nil), // 200: hyapp.wallet.v1.DebitCPBreakupFeeRequest + (*DebitCPBreakupFeeResponse)(nil), // 201: hyapp.wallet.v1.DebitCPBreakupFeeResponse + (*DebitWheelDrawRequest)(nil), // 202: hyapp.wallet.v1.DebitWheelDrawRequest + (*DebitWheelDrawResponse)(nil), // 203: hyapp.wallet.v1.DebitWheelDrawResponse + (*GrantVipRequest)(nil), // 204: hyapp.wallet.v1.GrantVipRequest + (*GrantVipResponse)(nil), // 205: hyapp.wallet.v1.GrantVipResponse + (*GetVipProgramConfigRequest)(nil), // 206: hyapp.wallet.v1.GetVipProgramConfigRequest + (*GetVipProgramConfigResponse)(nil), // 207: hyapp.wallet.v1.GetVipProgramConfigResponse + (*UpdateAdminVipProgramConfigRequest)(nil), // 208: hyapp.wallet.v1.UpdateAdminVipProgramConfigRequest + (*UpdateAdminVipProgramConfigResponse)(nil), // 209: hyapp.wallet.v1.UpdateAdminVipProgramConfigResponse + (*UpdateMyVipSettingsRequest)(nil), // 210: hyapp.wallet.v1.UpdateMyVipSettingsRequest + (*UpdateMyVipSettingsResponse)(nil), // 211: hyapp.wallet.v1.UpdateMyVipSettingsResponse + (*VipDailyCoinRebateRun)(nil), // 212: hyapp.wallet.v1.VipDailyCoinRebateRun + (*VipDailyCoinRebate)(nil), // 213: hyapp.wallet.v1.VipDailyCoinRebate + (*ProcessVipDailyCoinRebateBatchRequest)(nil), // 214: hyapp.wallet.v1.ProcessVipDailyCoinRebateBatchRequest + (*ProcessVipDailyCoinRebateBatchResponse)(nil), // 215: hyapp.wallet.v1.ProcessVipDailyCoinRebateBatchResponse + (*GetMyCurrentVipDailyCoinRebateRequest)(nil), // 216: hyapp.wallet.v1.GetMyCurrentVipDailyCoinRebateRequest + (*GetMyCurrentVipDailyCoinRebateResponse)(nil), // 217: hyapp.wallet.v1.GetMyCurrentVipDailyCoinRebateResponse + (*ListMyVipDailyCoinRebateStatusesRequest)(nil), // 218: hyapp.wallet.v1.ListMyVipDailyCoinRebateStatusesRequest + (*ListMyVipDailyCoinRebateStatusesResponse)(nil), // 219: hyapp.wallet.v1.ListMyVipDailyCoinRebateStatusesResponse + (*ClaimVipDailyCoinRebateRequest)(nil), // 220: hyapp.wallet.v1.ClaimVipDailyCoinRebateRequest + (*ClaimVipDailyCoinRebateResponse)(nil), // 221: hyapp.wallet.v1.ClaimVipDailyCoinRebateResponse + (*GrantVipTrialCardRequest)(nil), // 222: hyapp.wallet.v1.GrantVipTrialCardRequest + (*GrantVipTrialCardResponse)(nil), // 223: hyapp.wallet.v1.GrantVipTrialCardResponse + (*EquipVipTrialCardRequest)(nil), // 224: hyapp.wallet.v1.EquipVipTrialCardRequest + (*EquipVipTrialCardResponse)(nil), // 225: hyapp.wallet.v1.EquipVipTrialCardResponse + (*UnequipVipTrialCardRequest)(nil), // 226: hyapp.wallet.v1.UnequipVipTrialCardRequest + (*UnequipVipTrialCardResponse)(nil), // 227: hyapp.wallet.v1.UnequipVipTrialCardResponse + (*CheckVipBenefitRequest)(nil), // 228: hyapp.wallet.v1.CheckVipBenefitRequest + (*CheckVipBenefitResponse)(nil), // 229: hyapp.wallet.v1.CheckVipBenefitResponse + (*AdminVipLevelInput)(nil), // 230: hyapp.wallet.v1.AdminVipLevelInput + (*ListAdminVipLevelsRequest)(nil), // 231: hyapp.wallet.v1.ListAdminVipLevelsRequest + (*ListAdminVipLevelsResponse)(nil), // 232: hyapp.wallet.v1.ListAdminVipLevelsResponse + (*UpdateAdminVipLevelsRequest)(nil), // 233: hyapp.wallet.v1.UpdateAdminVipLevelsRequest + (*UpdateAdminVipLevelsResponse)(nil), // 234: hyapp.wallet.v1.UpdateAdminVipLevelsResponse + (*CreditTaskRewardRequest)(nil), // 235: hyapp.wallet.v1.CreditTaskRewardRequest + (*CreditTaskRewardResponse)(nil), // 236: hyapp.wallet.v1.CreditTaskRewardResponse + (*CreditLuckyGiftRewardRequest)(nil), // 237: hyapp.wallet.v1.CreditLuckyGiftRewardRequest + (*CreditLuckyGiftRewardResponse)(nil), // 238: hyapp.wallet.v1.CreditLuckyGiftRewardResponse + (*CreditWheelRewardRequest)(nil), // 239: hyapp.wallet.v1.CreditWheelRewardRequest + (*CreditWheelRewardResponse)(nil), // 240: hyapp.wallet.v1.CreditWheelRewardResponse + (*CreditRoomTurnoverRewardRequest)(nil), // 241: hyapp.wallet.v1.CreditRoomTurnoverRewardRequest + (*CreditRoomTurnoverRewardResponse)(nil), // 242: hyapp.wallet.v1.CreditRoomTurnoverRewardResponse + (*CreditInviteActivityRewardRequest)(nil), // 243: hyapp.wallet.v1.CreditInviteActivityRewardRequest + (*CreditInviteActivityRewardResponse)(nil), // 244: hyapp.wallet.v1.CreditInviteActivityRewardResponse + (*CreditAgencyOpeningRewardRequest)(nil), // 245: hyapp.wallet.v1.CreditAgencyOpeningRewardRequest + (*CreditAgencyOpeningRewardResponse)(nil), // 246: hyapp.wallet.v1.CreditAgencyOpeningRewardResponse + (*ApplyGameCoinChangeRequest)(nil), // 247: hyapp.wallet.v1.ApplyGameCoinChangeRequest + (*ApplyGameCoinChangeResponse)(nil), // 248: hyapp.wallet.v1.ApplyGameCoinChangeResponse + (*RedPacketConfig)(nil), // 249: hyapp.wallet.v1.RedPacketConfig + (*RedPacketClaim)(nil), // 250: hyapp.wallet.v1.RedPacketClaim + (*RedPacket)(nil), // 251: hyapp.wallet.v1.RedPacket + (*GetRedPacketConfigRequest)(nil), // 252: hyapp.wallet.v1.GetRedPacketConfigRequest + (*GetRedPacketConfigResponse)(nil), // 253: hyapp.wallet.v1.GetRedPacketConfigResponse + (*UpdateRedPacketConfigRequest)(nil), // 254: hyapp.wallet.v1.UpdateRedPacketConfigRequest + (*UpdateRedPacketConfigResponse)(nil), // 255: hyapp.wallet.v1.UpdateRedPacketConfigResponse + (*CreateRedPacketRequest)(nil), // 256: hyapp.wallet.v1.CreateRedPacketRequest + (*CreateRedPacketResponse)(nil), // 257: hyapp.wallet.v1.CreateRedPacketResponse + (*ClaimRedPacketRequest)(nil), // 258: hyapp.wallet.v1.ClaimRedPacketRequest + (*ClaimRedPacketResponse)(nil), // 259: hyapp.wallet.v1.ClaimRedPacketResponse + (*ListRedPacketsRequest)(nil), // 260: hyapp.wallet.v1.ListRedPacketsRequest + (*ListRedPacketsResponse)(nil), // 261: hyapp.wallet.v1.ListRedPacketsResponse + (*GetRedPacketRequest)(nil), // 262: hyapp.wallet.v1.GetRedPacketRequest + (*GetRedPacketResponse)(nil), // 263: hyapp.wallet.v1.GetRedPacketResponse + (*ExpireRedPacketsRequest)(nil), // 264: hyapp.wallet.v1.ExpireRedPacketsRequest + (*ExpireRedPacketsResponse)(nil), // 265: hyapp.wallet.v1.ExpireRedPacketsResponse + (*RetryRedPacketRefundRequest)(nil), // 266: hyapp.wallet.v1.RetryRedPacketRefundRequest + (*RetryRedPacketRefundResponse)(nil), // 267: hyapp.wallet.v1.RetryRedPacketRefundResponse + (*CronBatchRequest)(nil), // 268: hyapp.wallet.v1.CronBatchRequest + (*CronBatchResponse)(nil), // 269: hyapp.wallet.v1.CronBatchResponse + (*ResourceShopPurchaseOrder)(nil), // 270: hyapp.wallet.v1.ResourceShopPurchaseOrder + (*ListResourceShopPurchaseOrdersRequest)(nil), // 271: hyapp.wallet.v1.ListResourceShopPurchaseOrdersRequest + (*ListResourceShopPurchaseOrdersResponse)(nil), // 272: hyapp.wallet.v1.ListResourceShopPurchaseOrdersResponse + (*GetGiftCatalogVersionRequest)(nil), // 273: hyapp.wallet.v1.GetGiftCatalogVersionRequest + (*GetGiftCatalogVersionResponse)(nil), // 274: hyapp.wallet.v1.GetGiftCatalogVersionResponse + nil, // 275: 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 @@ -26946,286 +30345,343 @@ var file_proto_wallet_v1_wallet_proto_depIdxs = []int32{ 118, // 53: hyapp.wallet.v1.GetRechargeBillSummaryResponse.google_play:type_name -> hyapp.wallet.v1.RechargeBillSummaryBucket 118, // 54: hyapp.wallet.v1.GetRechargeBillSummaryResponse.third_party:type_name -> hyapp.wallet.v1.RechargeBillSummaryBucket 118, // 55: hyapp.wallet.v1.GetRechargeBillSummaryResponse.coin_seller:type_name -> hyapp.wallet.v1.RechargeBillSummaryBucket - 121, // 56: hyapp.wallet.v1.GetRechargeBillOverviewResponse.daily:type_name -> hyapp.wallet.v1.RechargeBillDailyBucket - 122, // 57: hyapp.wallet.v1.GetRechargeBillOverviewResponse.regions:type_name -> hyapp.wallet.v1.RechargeBillRegionBucket - 123, // 58: hyapp.wallet.v1.GetRechargeBillOverviewResponse.google_paid:type_name -> hyapp.wallet.v1.RechargeBillGooglePaidStats - 124, // 59: hyapp.wallet.v1.GetRechargeBillOverviewResponse.salary_transfer:type_name -> hyapp.wallet.v1.RechargeBillSalaryTransferStats - 127, // 60: hyapp.wallet.v1.RefreshGooglePaymentPricesResponse.prices:type_name -> hyapp.wallet.v1.GooglePaymentPrice - 8, // 61: hyapp.wallet.v1.GetWalletOverviewResponse.balances:type_name -> hyapp.wallet.v1.AssetBalance - 129, // 62: hyapp.wallet.v1.GetWalletOverviewResponse.feature_flags:type_name -> hyapp.wallet.v1.WalletFeatureFlags - 132, // 63: hyapp.wallet.v1.GetWalletValueSummaryResponse.summary:type_name -> hyapp.wallet.v1.WalletValueSummary - 48, // 64: hyapp.wallet.v1.GiftWallItem.resource:type_name -> hyapp.wallet.v1.Resource - 135, // 65: hyapp.wallet.v1.GetUserGiftWallResponse.items:type_name -> hyapp.wallet.v1.GiftWallItem - 138, // 66: hyapp.wallet.v1.ListRechargeProductsResponse.products:type_name -> hyapp.wallet.v1.RechargeProduct - 8, // 67: hyapp.wallet.v1.ConfirmGooglePaymentResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 138, // 68: hyapp.wallet.v1.ListAdminRechargeProductsResponse.products:type_name -> hyapp.wallet.v1.RechargeProduct - 138, // 69: hyapp.wallet.v1.RechargeProductResponse.product:type_name -> hyapp.wallet.v1.RechargeProduct - 150, // 70: hyapp.wallet.v1.ThirdPartyPaymentChannel.methods:type_name -> hyapp.wallet.v1.ThirdPartyPaymentMethod - 151, // 71: hyapp.wallet.v1.ListThirdPartyPaymentChannelsResponse.channels:type_name -> hyapp.wallet.v1.ThirdPartyPaymentChannel - 150, // 72: hyapp.wallet.v1.ThirdPartyPaymentMethodResponse.method:type_name -> hyapp.wallet.v1.ThirdPartyPaymentMethod - 157, // 73: hyapp.wallet.v1.SyncThirdPartyPaymentMethodsResponse.issues:type_name -> hyapp.wallet.v1.ThirdPartyPaymentMethodSyncIssue - 138, // 74: hyapp.wallet.v1.H5RechargeOptionsResponse.products:type_name -> hyapp.wallet.v1.RechargeProduct - 150, // 75: hyapp.wallet.v1.H5RechargeOptionsResponse.payment_methods:type_name -> hyapp.wallet.v1.ThirdPartyPaymentMethod - 162, // 76: hyapp.wallet.v1.ListTemporaryRechargeOrdersResponse.orders:type_name -> hyapp.wallet.v1.ExternalRechargeOrder - 162, // 77: hyapp.wallet.v1.H5RechargeOrderResponse.order:type_name -> hyapp.wallet.v1.ExternalRechargeOrder - 243, // 78: hyapp.wallet.v1.HandleV5PayNotifyRequest.fields:type_name -> hyapp.wallet.v1.HandleV5PayNotifyRequest.FieldsEntry - 177, // 79: hyapp.wallet.v1.GetDiamondExchangeConfigResponse.rules:type_name -> hyapp.wallet.v1.DiamondExchangeRule - 180, // 80: hyapp.wallet.v1.ListWalletTransactionsResponse.transactions:type_name -> hyapp.wallet.v1.WalletTransaction - 183, // 81: hyapp.wallet.v1.VipLevel.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 185, // 82: hyapp.wallet.v1.ListVipPackagesResponse.current_vip:type_name -> hyapp.wallet.v1.UserVip - 184, // 83: hyapp.wallet.v1.ListVipPackagesResponse.packages:type_name -> hyapp.wallet.v1.VipLevel - 185, // 84: hyapp.wallet.v1.GetMyVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 185, // 85: hyapp.wallet.v1.PurchaseVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 183, // 86: hyapp.wallet.v1.PurchaseVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 8, // 87: hyapp.wallet.v1.DebitCPBreakupFeeResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 8, // 88: hyapp.wallet.v1.DebitWheelDrawResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 185, // 89: hyapp.wallet.v1.GrantVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 183, // 90: hyapp.wallet.v1.GrantVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 184, // 91: hyapp.wallet.v1.ListAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel - 198, // 92: hyapp.wallet.v1.UpdateAdminVipLevelsRequest.levels:type_name -> hyapp.wallet.v1.AdminVipLevelInput - 184, // 93: hyapp.wallet.v1.UpdateAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel - 8, // 94: hyapp.wallet.v1.CreditTaskRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 8, // 95: hyapp.wallet.v1.CreditLuckyGiftRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 8, // 96: hyapp.wallet.v1.CreditWheelRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 8, // 97: hyapp.wallet.v1.CreditRoomTurnoverRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 8, // 98: hyapp.wallet.v1.CreditInviteActivityRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 8, // 99: hyapp.wallet.v1.CreditAgencyOpeningRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 218, // 100: hyapp.wallet.v1.RedPacket.claims:type_name -> hyapp.wallet.v1.RedPacketClaim - 217, // 101: hyapp.wallet.v1.GetRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig - 217, // 102: hyapp.wallet.v1.UpdateRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig - 219, // 103: hyapp.wallet.v1.CreateRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 218, // 104: hyapp.wallet.v1.ClaimRedPacketResponse.claim:type_name -> hyapp.wallet.v1.RedPacketClaim - 219, // 105: hyapp.wallet.v1.ClaimRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 219, // 106: hyapp.wallet.v1.ListRedPacketsResponse.packets:type_name -> hyapp.wallet.v1.RedPacket - 219, // 107: hyapp.wallet.v1.GetRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 219, // 108: hyapp.wallet.v1.RetryRedPacketRefundResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 48, // 109: hyapp.wallet.v1.ResourceShopPurchaseOrder.resource:type_name -> hyapp.wallet.v1.Resource - 238, // 110: hyapp.wallet.v1.ListResourceShopPurchaseOrdersResponse.orders:type_name -> hyapp.wallet.v1.ResourceShopPurchaseOrder - 236, // 111: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 236, // 112: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 236, // 113: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 0, // 114: hyapp.wallet.v1.WalletService.DebitGift:input_type -> hyapp.wallet.v1.DebitGiftRequest - 1, // 115: hyapp.wallet.v1.WalletService.DebitDirectGift:input_type -> hyapp.wallet.v1.DebitDirectGiftRequest - 4, // 116: hyapp.wallet.v1.WalletService.BatchDebitGift:input_type -> hyapp.wallet.v1.BatchDebitGiftRequest - 7, // 117: hyapp.wallet.v1.WalletService.DebitRobotGift:input_type -> hyapp.wallet.v1.DebitRobotGiftRequest - 9, // 118: hyapp.wallet.v1.WalletService.GetBalances:input_type -> hyapp.wallet.v1.GetBalancesRequest - 13, // 119: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:input_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyRequest - 16, // 120: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:input_type -> hyapp.wallet.v1.GetHostSalaryProgressRequest - 19, // 121: hyapp.wallet.v1.WalletService.GetTeamHostSalaryStats:input_type -> hyapp.wallet.v1.GetTeamHostSalaryStatsRequest - 21, // 122: hyapp.wallet.v1.WalletService.AdminCreditAsset:input_type -> hyapp.wallet.v1.AdminCreditAssetRequest - 23, // 123: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:input_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockRequest - 25, // 124: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:input_type -> hyapp.wallet.v1.TransferCoinFromSellerRequest - 27, // 125: hyapp.wallet.v1.WalletService.TransferCoinSellerStockToChild:input_type -> hyapp.wallet.v1.TransferCoinSellerStockToChildRequest - 30, // 126: hyapp.wallet.v1.WalletService.ListCoinSellerSalaryExchangeRateTiers:input_type -> hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersRequest - 32, // 127: hyapp.wallet.v1.WalletService.ExchangeSalaryToCoin:input_type -> hyapp.wallet.v1.ExchangeSalaryToCoinRequest - 34, // 128: hyapp.wallet.v1.WalletService.TransferSalaryToCoinSeller:input_type -> hyapp.wallet.v1.TransferSalaryToCoinSellerRequest - 36, // 129: hyapp.wallet.v1.WalletService.FreezeSalaryWithdrawal:input_type -> hyapp.wallet.v1.FreezeSalaryWithdrawalRequest - 38, // 130: hyapp.wallet.v1.WalletService.SettleSalaryWithdrawal:input_type -> hyapp.wallet.v1.SettleSalaryWithdrawalRequest - 40, // 131: hyapp.wallet.v1.WalletService.ReleaseSalaryWithdrawal:input_type -> hyapp.wallet.v1.ReleaseSalaryWithdrawalRequest - 42, // 132: hyapp.wallet.v1.WalletService.FreezePointWithdrawal:input_type -> hyapp.wallet.v1.FreezePointWithdrawalRequest - 44, // 133: hyapp.wallet.v1.WalletService.SettlePointWithdrawal:input_type -> hyapp.wallet.v1.SettlePointWithdrawalRequest - 46, // 134: hyapp.wallet.v1.WalletService.ReleasePointWithdrawal:input_type -> hyapp.wallet.v1.ReleasePointWithdrawalRequest - 58, // 135: hyapp.wallet.v1.WalletService.ListResources:input_type -> hyapp.wallet.v1.ListResourcesRequest - 60, // 136: hyapp.wallet.v1.WalletService.GetResource:input_type -> hyapp.wallet.v1.GetResourceRequest - 62, // 137: hyapp.wallet.v1.WalletService.CreateResource:input_type -> hyapp.wallet.v1.CreateResourceRequest - 63, // 138: hyapp.wallet.v1.WalletService.UpdateResource:input_type -> hyapp.wallet.v1.UpdateResourceRequest - 64, // 139: hyapp.wallet.v1.WalletService.SetResourceStatus:input_type -> hyapp.wallet.v1.SetResourceStatusRequest - 65, // 140: hyapp.wallet.v1.WalletService.DeleteResource:input_type -> hyapp.wallet.v1.DeleteResourceRequest - 66, // 141: hyapp.wallet.v1.WalletService.BatchDeleteResources:input_type -> hyapp.wallet.v1.BatchDeleteResourcesRequest - 69, // 142: hyapp.wallet.v1.WalletService.ListResourceGroups:input_type -> hyapp.wallet.v1.ListResourceGroupsRequest - 71, // 143: hyapp.wallet.v1.WalletService.GetResourceGroup:input_type -> hyapp.wallet.v1.GetResourceGroupRequest - 73, // 144: hyapp.wallet.v1.WalletService.CreateResourceGroup:input_type -> hyapp.wallet.v1.CreateResourceGroupRequest - 74, // 145: hyapp.wallet.v1.WalletService.UpdateResourceGroup:input_type -> hyapp.wallet.v1.UpdateResourceGroupRequest - 75, // 146: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:input_type -> hyapp.wallet.v1.SetResourceGroupStatusRequest - 77, // 147: hyapp.wallet.v1.WalletService.ListGiftConfigs:input_type -> hyapp.wallet.v1.ListGiftConfigsRequest - 79, // 148: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:input_type -> hyapp.wallet.v1.ListGiftTypeConfigsRequest - 241, // 149: hyapp.wallet.v1.WalletService.GetGiftCatalogVersion:input_type -> hyapp.wallet.v1.GetGiftCatalogVersionRequest - 83, // 150: hyapp.wallet.v1.WalletService.CreateGiftConfig:input_type -> hyapp.wallet.v1.CreateGiftConfigRequest - 84, // 151: hyapp.wallet.v1.WalletService.BatchCreateGiftConfigs:input_type -> hyapp.wallet.v1.BatchCreateGiftConfigsRequest - 86, // 152: hyapp.wallet.v1.WalletService.UpdateGiftConfig:input_type -> hyapp.wallet.v1.UpdateGiftConfigRequest - 87, // 153: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:input_type -> hyapp.wallet.v1.SetGiftConfigStatusRequest - 88, // 154: hyapp.wallet.v1.WalletService.DeleteGiftConfig:input_type -> hyapp.wallet.v1.DeleteGiftConfigRequest - 81, // 155: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:input_type -> hyapp.wallet.v1.UpsertGiftTypeConfigRequest - 90, // 156: hyapp.wallet.v1.WalletService.GrantResource:input_type -> hyapp.wallet.v1.GrantResourceRequest - 91, // 157: hyapp.wallet.v1.WalletService.GrantResourceGroup:input_type -> hyapp.wallet.v1.GrantResourceGroupRequest - 92, // 158: hyapp.wallet.v1.WalletService.RevokeResourceGrant:input_type -> hyapp.wallet.v1.RevokeResourceGrantRequest - 94, // 159: hyapp.wallet.v1.WalletService.ListUserResources:input_type -> hyapp.wallet.v1.ListUserResourcesRequest - 96, // 160: hyapp.wallet.v1.WalletService.EquipUserResource:input_type -> hyapp.wallet.v1.EquipUserResourceRequest - 98, // 161: hyapp.wallet.v1.WalletService.UnequipUserResource:input_type -> hyapp.wallet.v1.UnequipUserResourceRequest - 100, // 162: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:input_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest - 103, // 163: hyapp.wallet.v1.WalletService.ListResourceGrants:input_type -> hyapp.wallet.v1.ListResourceGrantsRequest - 106, // 164: hyapp.wallet.v1.WalletService.ListResourceShopItems:input_type -> hyapp.wallet.v1.ListResourceShopItemsRequest - 108, // 165: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:input_type -> hyapp.wallet.v1.UpsertResourceShopItemsRequest - 110, // 166: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:input_type -> hyapp.wallet.v1.SetResourceShopItemStatusRequest - 239, // 167: hyapp.wallet.v1.WalletService.ListResourceShopPurchaseOrders:input_type -> hyapp.wallet.v1.ListResourceShopPurchaseOrdersRequest - 112, // 168: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:input_type -> hyapp.wallet.v1.PurchaseResourceShopItemRequest - 115, // 169: hyapp.wallet.v1.WalletService.ListRechargeBills:input_type -> hyapp.wallet.v1.ListRechargeBillsRequest - 117, // 170: hyapp.wallet.v1.WalletService.GetRechargeBillSummary:input_type -> hyapp.wallet.v1.GetRechargeBillSummaryRequest - 120, // 171: hyapp.wallet.v1.WalletService.GetRechargeBillOverview:input_type -> hyapp.wallet.v1.GetRechargeBillOverviewRequest - 126, // 172: hyapp.wallet.v1.WalletService.RefreshGooglePaymentPrices:input_type -> hyapp.wallet.v1.RefreshGooglePaymentPricesRequest - 130, // 173: hyapp.wallet.v1.WalletService.GetWalletOverview:input_type -> hyapp.wallet.v1.GetWalletOverviewRequest - 133, // 174: hyapp.wallet.v1.WalletService.GetWalletValueSummary:input_type -> hyapp.wallet.v1.GetWalletValueSummaryRequest - 136, // 175: hyapp.wallet.v1.WalletService.GetUserGiftWall:input_type -> hyapp.wallet.v1.GetUserGiftWallRequest - 139, // 176: hyapp.wallet.v1.WalletService.ListRechargeProducts:input_type -> hyapp.wallet.v1.ListRechargeProductsRequest - 141, // 177: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:input_type -> hyapp.wallet.v1.ConfirmGooglePaymentRequest - 143, // 178: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:input_type -> hyapp.wallet.v1.ListAdminRechargeProductsRequest - 145, // 179: hyapp.wallet.v1.WalletService.CreateRechargeProduct:input_type -> hyapp.wallet.v1.CreateRechargeProductRequest - 146, // 180: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:input_type -> hyapp.wallet.v1.UpdateRechargeProductRequest - 147, // 181: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:input_type -> hyapp.wallet.v1.DeleteRechargeProductRequest - 152, // 182: hyapp.wallet.v1.WalletService.ListThirdPartyPaymentChannels:input_type -> hyapp.wallet.v1.ListThirdPartyPaymentChannelsRequest - 154, // 183: hyapp.wallet.v1.WalletService.SetThirdPartyPaymentMethodStatus:input_type -> hyapp.wallet.v1.SetThirdPartyPaymentMethodStatusRequest - 156, // 184: hyapp.wallet.v1.WalletService.UpdateThirdPartyPaymentRate:input_type -> hyapp.wallet.v1.UpdateThirdPartyPaymentRateRequest - 158, // 185: hyapp.wallet.v1.WalletService.SyncThirdPartyPaymentMethods:input_type -> hyapp.wallet.v1.SyncThirdPartyPaymentMethodsRequest - 160, // 186: hyapp.wallet.v1.WalletService.ListH5RechargeOptions:input_type -> hyapp.wallet.v1.H5RechargeOptionsRequest - 163, // 187: hyapp.wallet.v1.WalletService.CreateH5RechargeOrder:input_type -> hyapp.wallet.v1.CreateH5RechargeOrderRequest - 164, // 188: hyapp.wallet.v1.WalletService.CreateTemporaryRechargeOrder:input_type -> hyapp.wallet.v1.CreateTemporaryRechargeOrderRequest - 165, // 189: hyapp.wallet.v1.WalletService.GetTemporaryRechargeOrder:input_type -> hyapp.wallet.v1.GetTemporaryRechargeOrderRequest - 166, // 190: hyapp.wallet.v1.WalletService.ListTemporaryRechargeOrders:input_type -> hyapp.wallet.v1.ListTemporaryRechargeOrdersRequest - 168, // 191: hyapp.wallet.v1.WalletService.SubmitH5RechargeTx:input_type -> hyapp.wallet.v1.SubmitH5RechargeTxRequest - 169, // 192: hyapp.wallet.v1.WalletService.GetH5RechargeOrder:input_type -> hyapp.wallet.v1.GetH5RechargeOrderRequest - 171, // 193: hyapp.wallet.v1.WalletService.VerifyCoinSellerRechargeReceipt:input_type -> hyapp.wallet.v1.VerifyCoinSellerRechargeReceiptRequest - 173, // 194: hyapp.wallet.v1.WalletService.HandleMifapayNotify:input_type -> hyapp.wallet.v1.HandleMifapayNotifyRequest - 175, // 195: hyapp.wallet.v1.WalletService.HandleV5PayNotify:input_type -> hyapp.wallet.v1.HandleV5PayNotifyRequest - 178, // 196: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:input_type -> hyapp.wallet.v1.GetDiamondExchangeConfigRequest - 181, // 197: hyapp.wallet.v1.WalletService.ListWalletTransactions:input_type -> hyapp.wallet.v1.ListWalletTransactionsRequest - 186, // 198: hyapp.wallet.v1.WalletService.ListVipPackages:input_type -> hyapp.wallet.v1.ListVipPackagesRequest - 188, // 199: hyapp.wallet.v1.WalletService.GetMyVip:input_type -> hyapp.wallet.v1.GetMyVipRequest - 190, // 200: hyapp.wallet.v1.WalletService.PurchaseVip:input_type -> hyapp.wallet.v1.PurchaseVipRequest - 192, // 201: hyapp.wallet.v1.WalletService.DebitCPBreakupFee:input_type -> hyapp.wallet.v1.DebitCPBreakupFeeRequest - 194, // 202: hyapp.wallet.v1.WalletService.DebitWheelDraw:input_type -> hyapp.wallet.v1.DebitWheelDrawRequest - 196, // 203: hyapp.wallet.v1.WalletService.GrantVip:input_type -> hyapp.wallet.v1.GrantVipRequest - 199, // 204: hyapp.wallet.v1.WalletService.ListAdminVipLevels:input_type -> hyapp.wallet.v1.ListAdminVipLevelsRequest - 201, // 205: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:input_type -> hyapp.wallet.v1.UpdateAdminVipLevelsRequest - 203, // 206: hyapp.wallet.v1.WalletService.CreditTaskReward:input_type -> hyapp.wallet.v1.CreditTaskRewardRequest - 205, // 207: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:input_type -> hyapp.wallet.v1.CreditLuckyGiftRewardRequest - 207, // 208: hyapp.wallet.v1.WalletService.CreditWheelReward:input_type -> hyapp.wallet.v1.CreditWheelRewardRequest - 209, // 209: hyapp.wallet.v1.WalletService.CreditRoomTurnoverReward:input_type -> hyapp.wallet.v1.CreditRoomTurnoverRewardRequest - 211, // 210: hyapp.wallet.v1.WalletService.CreditInviteActivityReward:input_type -> hyapp.wallet.v1.CreditInviteActivityRewardRequest - 213, // 211: hyapp.wallet.v1.WalletService.CreditAgencyOpeningReward:input_type -> hyapp.wallet.v1.CreditAgencyOpeningRewardRequest - 215, // 212: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:input_type -> hyapp.wallet.v1.ApplyGameCoinChangeRequest - 220, // 213: hyapp.wallet.v1.WalletService.GetRedPacketConfig:input_type -> hyapp.wallet.v1.GetRedPacketConfigRequest - 222, // 214: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:input_type -> hyapp.wallet.v1.UpdateRedPacketConfigRequest - 224, // 215: hyapp.wallet.v1.WalletService.CreateRedPacket:input_type -> hyapp.wallet.v1.CreateRedPacketRequest - 226, // 216: hyapp.wallet.v1.WalletService.ClaimRedPacket:input_type -> hyapp.wallet.v1.ClaimRedPacketRequest - 228, // 217: hyapp.wallet.v1.WalletService.ListRedPackets:input_type -> hyapp.wallet.v1.ListRedPacketsRequest - 230, // 218: hyapp.wallet.v1.WalletService.GetRedPacket:input_type -> hyapp.wallet.v1.GetRedPacketRequest - 232, // 219: hyapp.wallet.v1.WalletService.ExpireRedPackets:input_type -> hyapp.wallet.v1.ExpireRedPacketsRequest - 234, // 220: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:input_type -> hyapp.wallet.v1.RetryRedPacketRefundRequest - 237, // 221: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 237, // 222: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 237, // 223: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 2, // 224: hyapp.wallet.v1.WalletService.DebitGift:output_type -> hyapp.wallet.v1.DebitGiftResponse - 2, // 225: hyapp.wallet.v1.WalletService.DebitDirectGift:output_type -> hyapp.wallet.v1.DebitGiftResponse - 6, // 226: hyapp.wallet.v1.WalletService.BatchDebitGift:output_type -> hyapp.wallet.v1.BatchDebitGiftResponse - 2, // 227: hyapp.wallet.v1.WalletService.DebitRobotGift:output_type -> hyapp.wallet.v1.DebitGiftResponse - 10, // 228: hyapp.wallet.v1.WalletService.GetBalances:output_type -> hyapp.wallet.v1.GetBalancesResponse - 14, // 229: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:output_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse - 17, // 230: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:output_type -> hyapp.wallet.v1.GetHostSalaryProgressResponse - 20, // 231: hyapp.wallet.v1.WalletService.GetTeamHostSalaryStats:output_type -> hyapp.wallet.v1.GetTeamHostSalaryStatsResponse - 22, // 232: hyapp.wallet.v1.WalletService.AdminCreditAsset:output_type -> hyapp.wallet.v1.AdminCreditAssetResponse - 24, // 233: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:output_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockResponse - 26, // 234: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:output_type -> hyapp.wallet.v1.TransferCoinFromSellerResponse - 28, // 235: hyapp.wallet.v1.WalletService.TransferCoinSellerStockToChild:output_type -> hyapp.wallet.v1.TransferCoinSellerStockToChildResponse - 31, // 236: hyapp.wallet.v1.WalletService.ListCoinSellerSalaryExchangeRateTiers:output_type -> hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersResponse - 33, // 237: hyapp.wallet.v1.WalletService.ExchangeSalaryToCoin:output_type -> hyapp.wallet.v1.ExchangeSalaryToCoinResponse - 35, // 238: hyapp.wallet.v1.WalletService.TransferSalaryToCoinSeller:output_type -> hyapp.wallet.v1.TransferSalaryToCoinSellerResponse - 37, // 239: hyapp.wallet.v1.WalletService.FreezeSalaryWithdrawal:output_type -> hyapp.wallet.v1.FreezeSalaryWithdrawalResponse - 39, // 240: hyapp.wallet.v1.WalletService.SettleSalaryWithdrawal:output_type -> hyapp.wallet.v1.SettleSalaryWithdrawalResponse - 41, // 241: hyapp.wallet.v1.WalletService.ReleaseSalaryWithdrawal:output_type -> hyapp.wallet.v1.ReleaseSalaryWithdrawalResponse - 43, // 242: hyapp.wallet.v1.WalletService.FreezePointWithdrawal:output_type -> hyapp.wallet.v1.FreezePointWithdrawalResponse - 45, // 243: hyapp.wallet.v1.WalletService.SettlePointWithdrawal:output_type -> hyapp.wallet.v1.SettlePointWithdrawalResponse - 47, // 244: hyapp.wallet.v1.WalletService.ReleasePointWithdrawal:output_type -> hyapp.wallet.v1.ReleasePointWithdrawalResponse - 59, // 245: hyapp.wallet.v1.WalletService.ListResources:output_type -> hyapp.wallet.v1.ListResourcesResponse - 61, // 246: hyapp.wallet.v1.WalletService.GetResource:output_type -> hyapp.wallet.v1.GetResourceResponse - 68, // 247: hyapp.wallet.v1.WalletService.CreateResource:output_type -> hyapp.wallet.v1.ResourceResponse - 68, // 248: hyapp.wallet.v1.WalletService.UpdateResource:output_type -> hyapp.wallet.v1.ResourceResponse - 68, // 249: hyapp.wallet.v1.WalletService.SetResourceStatus:output_type -> hyapp.wallet.v1.ResourceResponse - 68, // 250: hyapp.wallet.v1.WalletService.DeleteResource:output_type -> hyapp.wallet.v1.ResourceResponse - 67, // 251: hyapp.wallet.v1.WalletService.BatchDeleteResources:output_type -> hyapp.wallet.v1.BatchDeleteResourcesResponse - 70, // 252: hyapp.wallet.v1.WalletService.ListResourceGroups:output_type -> hyapp.wallet.v1.ListResourceGroupsResponse - 72, // 253: hyapp.wallet.v1.WalletService.GetResourceGroup:output_type -> hyapp.wallet.v1.GetResourceGroupResponse - 76, // 254: hyapp.wallet.v1.WalletService.CreateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 76, // 255: hyapp.wallet.v1.WalletService.UpdateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 76, // 256: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 78, // 257: hyapp.wallet.v1.WalletService.ListGiftConfigs:output_type -> hyapp.wallet.v1.ListGiftConfigsResponse - 80, // 258: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:output_type -> hyapp.wallet.v1.ListGiftTypeConfigsResponse - 242, // 259: hyapp.wallet.v1.WalletService.GetGiftCatalogVersion:output_type -> hyapp.wallet.v1.GetGiftCatalogVersionResponse - 89, // 260: hyapp.wallet.v1.WalletService.CreateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse - 85, // 261: hyapp.wallet.v1.WalletService.BatchCreateGiftConfigs:output_type -> hyapp.wallet.v1.BatchCreateGiftConfigsResponse - 89, // 262: hyapp.wallet.v1.WalletService.UpdateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse - 89, // 263: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:output_type -> hyapp.wallet.v1.GiftConfigResponse - 89, // 264: hyapp.wallet.v1.WalletService.DeleteGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse - 82, // 265: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:output_type -> hyapp.wallet.v1.GiftTypeConfigResponse - 93, // 266: hyapp.wallet.v1.WalletService.GrantResource:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 93, // 267: hyapp.wallet.v1.WalletService.GrantResourceGroup:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 93, // 268: hyapp.wallet.v1.WalletService.RevokeResourceGrant:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 95, // 269: hyapp.wallet.v1.WalletService.ListUserResources:output_type -> hyapp.wallet.v1.ListUserResourcesResponse - 97, // 270: hyapp.wallet.v1.WalletService.EquipUserResource:output_type -> hyapp.wallet.v1.EquipUserResourceResponse - 99, // 271: hyapp.wallet.v1.WalletService.UnequipUserResource:output_type -> hyapp.wallet.v1.UnequipUserResourceResponse - 102, // 272: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:output_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse - 104, // 273: hyapp.wallet.v1.WalletService.ListResourceGrants:output_type -> hyapp.wallet.v1.ListResourceGrantsResponse - 107, // 274: hyapp.wallet.v1.WalletService.ListResourceShopItems:output_type -> hyapp.wallet.v1.ListResourceShopItemsResponse - 109, // 275: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:output_type -> hyapp.wallet.v1.UpsertResourceShopItemsResponse - 111, // 276: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:output_type -> hyapp.wallet.v1.ResourceShopItemResponse - 240, // 277: hyapp.wallet.v1.WalletService.ListResourceShopPurchaseOrders:output_type -> hyapp.wallet.v1.ListResourceShopPurchaseOrdersResponse - 113, // 278: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:output_type -> hyapp.wallet.v1.PurchaseResourceShopItemResponse - 116, // 279: hyapp.wallet.v1.WalletService.ListRechargeBills:output_type -> hyapp.wallet.v1.ListRechargeBillsResponse - 119, // 280: hyapp.wallet.v1.WalletService.GetRechargeBillSummary:output_type -> hyapp.wallet.v1.GetRechargeBillSummaryResponse - 125, // 281: hyapp.wallet.v1.WalletService.GetRechargeBillOverview:output_type -> hyapp.wallet.v1.GetRechargeBillOverviewResponse - 128, // 282: hyapp.wallet.v1.WalletService.RefreshGooglePaymentPrices:output_type -> hyapp.wallet.v1.RefreshGooglePaymentPricesResponse - 131, // 283: hyapp.wallet.v1.WalletService.GetWalletOverview:output_type -> hyapp.wallet.v1.GetWalletOverviewResponse - 134, // 284: hyapp.wallet.v1.WalletService.GetWalletValueSummary:output_type -> hyapp.wallet.v1.GetWalletValueSummaryResponse - 137, // 285: hyapp.wallet.v1.WalletService.GetUserGiftWall:output_type -> hyapp.wallet.v1.GetUserGiftWallResponse - 140, // 286: hyapp.wallet.v1.WalletService.ListRechargeProducts:output_type -> hyapp.wallet.v1.ListRechargeProductsResponse - 142, // 287: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:output_type -> hyapp.wallet.v1.ConfirmGooglePaymentResponse - 144, // 288: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:output_type -> hyapp.wallet.v1.ListAdminRechargeProductsResponse - 148, // 289: hyapp.wallet.v1.WalletService.CreateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse - 148, // 290: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse - 149, // 291: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:output_type -> hyapp.wallet.v1.DeleteRechargeProductResponse - 153, // 292: hyapp.wallet.v1.WalletService.ListThirdPartyPaymentChannels:output_type -> hyapp.wallet.v1.ListThirdPartyPaymentChannelsResponse - 155, // 293: hyapp.wallet.v1.WalletService.SetThirdPartyPaymentMethodStatus:output_type -> hyapp.wallet.v1.ThirdPartyPaymentMethodResponse - 155, // 294: hyapp.wallet.v1.WalletService.UpdateThirdPartyPaymentRate:output_type -> hyapp.wallet.v1.ThirdPartyPaymentMethodResponse - 159, // 295: hyapp.wallet.v1.WalletService.SyncThirdPartyPaymentMethods:output_type -> hyapp.wallet.v1.SyncThirdPartyPaymentMethodsResponse - 161, // 296: hyapp.wallet.v1.WalletService.ListH5RechargeOptions:output_type -> hyapp.wallet.v1.H5RechargeOptionsResponse - 170, // 297: hyapp.wallet.v1.WalletService.CreateH5RechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse - 170, // 298: hyapp.wallet.v1.WalletService.CreateTemporaryRechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse - 170, // 299: hyapp.wallet.v1.WalletService.GetTemporaryRechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse - 167, // 300: hyapp.wallet.v1.WalletService.ListTemporaryRechargeOrders:output_type -> hyapp.wallet.v1.ListTemporaryRechargeOrdersResponse - 170, // 301: hyapp.wallet.v1.WalletService.SubmitH5RechargeTx:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse - 170, // 302: hyapp.wallet.v1.WalletService.GetH5RechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse - 172, // 303: hyapp.wallet.v1.WalletService.VerifyCoinSellerRechargeReceipt:output_type -> hyapp.wallet.v1.VerifyCoinSellerRechargeReceiptResponse - 174, // 304: hyapp.wallet.v1.WalletService.HandleMifapayNotify:output_type -> hyapp.wallet.v1.HandleMifapayNotifyResponse - 176, // 305: hyapp.wallet.v1.WalletService.HandleV5PayNotify:output_type -> hyapp.wallet.v1.HandleV5PayNotifyResponse - 179, // 306: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:output_type -> hyapp.wallet.v1.GetDiamondExchangeConfigResponse - 182, // 307: hyapp.wallet.v1.WalletService.ListWalletTransactions:output_type -> hyapp.wallet.v1.ListWalletTransactionsResponse - 187, // 308: hyapp.wallet.v1.WalletService.ListVipPackages:output_type -> hyapp.wallet.v1.ListVipPackagesResponse - 189, // 309: hyapp.wallet.v1.WalletService.GetMyVip:output_type -> hyapp.wallet.v1.GetMyVipResponse - 191, // 310: hyapp.wallet.v1.WalletService.PurchaseVip:output_type -> hyapp.wallet.v1.PurchaseVipResponse - 193, // 311: hyapp.wallet.v1.WalletService.DebitCPBreakupFee:output_type -> hyapp.wallet.v1.DebitCPBreakupFeeResponse - 195, // 312: hyapp.wallet.v1.WalletService.DebitWheelDraw:output_type -> hyapp.wallet.v1.DebitWheelDrawResponse - 197, // 313: hyapp.wallet.v1.WalletService.GrantVip:output_type -> hyapp.wallet.v1.GrantVipResponse - 200, // 314: hyapp.wallet.v1.WalletService.ListAdminVipLevels:output_type -> hyapp.wallet.v1.ListAdminVipLevelsResponse - 202, // 315: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:output_type -> hyapp.wallet.v1.UpdateAdminVipLevelsResponse - 204, // 316: hyapp.wallet.v1.WalletService.CreditTaskReward:output_type -> hyapp.wallet.v1.CreditTaskRewardResponse - 206, // 317: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:output_type -> hyapp.wallet.v1.CreditLuckyGiftRewardResponse - 208, // 318: hyapp.wallet.v1.WalletService.CreditWheelReward:output_type -> hyapp.wallet.v1.CreditWheelRewardResponse - 210, // 319: hyapp.wallet.v1.WalletService.CreditRoomTurnoverReward:output_type -> hyapp.wallet.v1.CreditRoomTurnoverRewardResponse - 212, // 320: hyapp.wallet.v1.WalletService.CreditInviteActivityReward:output_type -> hyapp.wallet.v1.CreditInviteActivityRewardResponse - 214, // 321: hyapp.wallet.v1.WalletService.CreditAgencyOpeningReward:output_type -> hyapp.wallet.v1.CreditAgencyOpeningRewardResponse - 216, // 322: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:output_type -> hyapp.wallet.v1.ApplyGameCoinChangeResponse - 221, // 323: hyapp.wallet.v1.WalletService.GetRedPacketConfig:output_type -> hyapp.wallet.v1.GetRedPacketConfigResponse - 223, // 324: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:output_type -> hyapp.wallet.v1.UpdateRedPacketConfigResponse - 225, // 325: hyapp.wallet.v1.WalletService.CreateRedPacket:output_type -> hyapp.wallet.v1.CreateRedPacketResponse - 227, // 326: hyapp.wallet.v1.WalletService.ClaimRedPacket:output_type -> hyapp.wallet.v1.ClaimRedPacketResponse - 229, // 327: hyapp.wallet.v1.WalletService.ListRedPackets:output_type -> hyapp.wallet.v1.ListRedPacketsResponse - 231, // 328: hyapp.wallet.v1.WalletService.GetRedPacket:output_type -> hyapp.wallet.v1.GetRedPacketResponse - 233, // 329: hyapp.wallet.v1.WalletService.ExpireRedPackets:output_type -> hyapp.wallet.v1.ExpireRedPacketsResponse - 235, // 330: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:output_type -> hyapp.wallet.v1.RetryRedPacketRefundResponse - 221, // [221:331] is the sub-list for method output_type - 111, // [111:221] is the sub-list for method input_type - 111, // [111:111] is the sub-list for extension type_name - 111, // [111:111] is the sub-list for extension extendee - 0, // [0:111] is the sub-list for field type_name + 120, // 56: hyapp.wallet.v1.BatchGetUserRechargeStatsResponse.items:type_name -> hyapp.wallet.v1.UserRechargeStats + 124, // 57: hyapp.wallet.v1.GetRechargeBillOverviewResponse.daily:type_name -> hyapp.wallet.v1.RechargeBillDailyBucket + 125, // 58: hyapp.wallet.v1.GetRechargeBillOverviewResponse.regions:type_name -> hyapp.wallet.v1.RechargeBillRegionBucket + 126, // 59: hyapp.wallet.v1.GetRechargeBillOverviewResponse.google_paid:type_name -> hyapp.wallet.v1.RechargeBillGooglePaidStats + 127, // 60: hyapp.wallet.v1.GetRechargeBillOverviewResponse.salary_transfer:type_name -> hyapp.wallet.v1.RechargeBillSalaryTransferStats + 130, // 61: hyapp.wallet.v1.RefreshGooglePaymentPricesResponse.prices:type_name -> hyapp.wallet.v1.GooglePaymentPrice + 8, // 62: hyapp.wallet.v1.GetWalletOverviewResponse.balances:type_name -> hyapp.wallet.v1.AssetBalance + 132, // 63: hyapp.wallet.v1.GetWalletOverviewResponse.feature_flags:type_name -> hyapp.wallet.v1.WalletFeatureFlags + 135, // 64: hyapp.wallet.v1.GetWalletValueSummaryResponse.summary:type_name -> hyapp.wallet.v1.WalletValueSummary + 48, // 65: hyapp.wallet.v1.GiftWallItem.resource:type_name -> hyapp.wallet.v1.Resource + 138, // 66: hyapp.wallet.v1.GetUserGiftWallResponse.items:type_name -> hyapp.wallet.v1.GiftWallItem + 141, // 67: hyapp.wallet.v1.ListRechargeProductsResponse.products:type_name -> hyapp.wallet.v1.RechargeProduct + 8, // 68: hyapp.wallet.v1.ConfirmGooglePaymentResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 141, // 69: hyapp.wallet.v1.ListAdminRechargeProductsResponse.products:type_name -> hyapp.wallet.v1.RechargeProduct + 141, // 70: hyapp.wallet.v1.RechargeProductResponse.product:type_name -> hyapp.wallet.v1.RechargeProduct + 153, // 71: hyapp.wallet.v1.ThirdPartyPaymentChannel.methods:type_name -> hyapp.wallet.v1.ThirdPartyPaymentMethod + 154, // 72: hyapp.wallet.v1.ListThirdPartyPaymentChannelsResponse.channels:type_name -> hyapp.wallet.v1.ThirdPartyPaymentChannel + 153, // 73: hyapp.wallet.v1.ThirdPartyPaymentMethodResponse.method:type_name -> hyapp.wallet.v1.ThirdPartyPaymentMethod + 160, // 74: hyapp.wallet.v1.SyncThirdPartyPaymentMethodsResponse.issues:type_name -> hyapp.wallet.v1.ThirdPartyPaymentMethodSyncIssue + 141, // 75: hyapp.wallet.v1.H5RechargeOptionsResponse.products:type_name -> hyapp.wallet.v1.RechargeProduct + 153, // 76: hyapp.wallet.v1.H5RechargeOptionsResponse.payment_methods:type_name -> hyapp.wallet.v1.ThirdPartyPaymentMethod + 165, // 77: hyapp.wallet.v1.ListTemporaryRechargeOrdersResponse.orders:type_name -> hyapp.wallet.v1.ExternalRechargeOrder + 165, // 78: hyapp.wallet.v1.H5RechargeOrderResponse.order:type_name -> hyapp.wallet.v1.ExternalRechargeOrder + 275, // 79: hyapp.wallet.v1.HandleV5PayNotifyRequest.fields:type_name -> hyapp.wallet.v1.HandleV5PayNotifyRequest.FieldsEntry + 180, // 80: hyapp.wallet.v1.GetDiamondExchangeConfigResponse.rules:type_name -> hyapp.wallet.v1.DiamondExchangeRule + 183, // 81: hyapp.wallet.v1.ListWalletTransactionsResponse.transactions:type_name -> hyapp.wallet.v1.WalletTransaction + 186, // 82: hyapp.wallet.v1.VipLevel.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 188, // 83: hyapp.wallet.v1.VipLevel.benefits:type_name -> hyapp.wallet.v1.VipBenefit + 190, // 84: hyapp.wallet.v1.VipState.paid_vip:type_name -> hyapp.wallet.v1.UserVip + 191, // 85: hyapp.wallet.v1.VipState.equipped_trial_card:type_name -> hyapp.wallet.v1.VipTrialCard + 190, // 86: hyapp.wallet.v1.VipState.effective_vip:type_name -> hyapp.wallet.v1.UserVip + 188, // 87: hyapp.wallet.v1.VipState.effective_benefits:type_name -> hyapp.wallet.v1.VipBenefit + 187, // 88: hyapp.wallet.v1.VipState.program_config:type_name -> hyapp.wallet.v1.VipProgramConfig + 192, // 89: hyapp.wallet.v1.VipState.user_settings:type_name -> hyapp.wallet.v1.VipUserSettings + 190, // 90: hyapp.wallet.v1.ListVipPackagesResponse.current_vip:type_name -> hyapp.wallet.v1.UserVip + 189, // 91: hyapp.wallet.v1.ListVipPackagesResponse.packages:type_name -> hyapp.wallet.v1.VipLevel + 193, // 92: hyapp.wallet.v1.ListVipPackagesResponse.state:type_name -> hyapp.wallet.v1.VipState + 187, // 93: hyapp.wallet.v1.ListVipPackagesResponse.program_config:type_name -> hyapp.wallet.v1.VipProgramConfig + 190, // 94: hyapp.wallet.v1.GetMyVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 193, // 95: hyapp.wallet.v1.GetMyVipResponse.state:type_name -> hyapp.wallet.v1.VipState + 190, // 96: hyapp.wallet.v1.PurchaseVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 186, // 97: hyapp.wallet.v1.PurchaseVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 193, // 98: hyapp.wallet.v1.PurchaseVipResponse.state:type_name -> hyapp.wallet.v1.VipState + 8, // 99: hyapp.wallet.v1.DebitCPBreakupFeeResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 8, // 100: hyapp.wallet.v1.DebitWheelDrawResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 190, // 101: hyapp.wallet.v1.GrantVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 186, // 102: hyapp.wallet.v1.GrantVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 193, // 103: hyapp.wallet.v1.GrantVipResponse.state:type_name -> hyapp.wallet.v1.VipState + 187, // 104: hyapp.wallet.v1.GetVipProgramConfigResponse.config:type_name -> hyapp.wallet.v1.VipProgramConfig + 188, // 105: hyapp.wallet.v1.GetVipProgramConfigResponse.benefits:type_name -> hyapp.wallet.v1.VipBenefit + 187, // 106: hyapp.wallet.v1.UpdateAdminVipProgramConfigRequest.config:type_name -> hyapp.wallet.v1.VipProgramConfig + 187, // 107: hyapp.wallet.v1.UpdateAdminVipProgramConfigResponse.config:type_name -> hyapp.wallet.v1.VipProgramConfig + 192, // 108: hyapp.wallet.v1.UpdateMyVipSettingsResponse.settings:type_name -> hyapp.wallet.v1.VipUserSettings + 212, // 109: hyapp.wallet.v1.ProcessVipDailyCoinRebateBatchResponse.run:type_name -> hyapp.wallet.v1.VipDailyCoinRebateRun + 213, // 110: hyapp.wallet.v1.GetMyCurrentVipDailyCoinRebateResponse.rebate:type_name -> hyapp.wallet.v1.VipDailyCoinRebate + 213, // 111: hyapp.wallet.v1.ListMyVipDailyCoinRebateStatusesResponse.rebates:type_name -> hyapp.wallet.v1.VipDailyCoinRebate + 213, // 112: hyapp.wallet.v1.ClaimVipDailyCoinRebateResponse.rebate:type_name -> hyapp.wallet.v1.VipDailyCoinRebate + 8, // 113: hyapp.wallet.v1.ClaimVipDailyCoinRebateResponse.coin_balance:type_name -> hyapp.wallet.v1.AssetBalance + 191, // 114: hyapp.wallet.v1.GrantVipTrialCardResponse.trial_card:type_name -> hyapp.wallet.v1.VipTrialCard + 193, // 115: hyapp.wallet.v1.GrantVipTrialCardResponse.state:type_name -> hyapp.wallet.v1.VipState + 191, // 116: hyapp.wallet.v1.EquipVipTrialCardResponse.trial_card:type_name -> hyapp.wallet.v1.VipTrialCard + 193, // 117: hyapp.wallet.v1.EquipVipTrialCardResponse.state:type_name -> hyapp.wallet.v1.VipState + 193, // 118: hyapp.wallet.v1.UnequipVipTrialCardResponse.state:type_name -> hyapp.wallet.v1.VipState + 188, // 119: hyapp.wallet.v1.CheckVipBenefitResponse.benefit:type_name -> hyapp.wallet.v1.VipBenefit + 193, // 120: hyapp.wallet.v1.CheckVipBenefitResponse.state:type_name -> hyapp.wallet.v1.VipState + 188, // 121: hyapp.wallet.v1.AdminVipLevelInput.benefits:type_name -> hyapp.wallet.v1.VipBenefit + 189, // 122: hyapp.wallet.v1.ListAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel + 187, // 123: hyapp.wallet.v1.ListAdminVipLevelsResponse.program_config:type_name -> hyapp.wallet.v1.VipProgramConfig + 230, // 124: hyapp.wallet.v1.UpdateAdminVipLevelsRequest.levels:type_name -> hyapp.wallet.v1.AdminVipLevelInput + 189, // 125: hyapp.wallet.v1.UpdateAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel + 187, // 126: hyapp.wallet.v1.UpdateAdminVipLevelsResponse.program_config:type_name -> hyapp.wallet.v1.VipProgramConfig + 8, // 127: hyapp.wallet.v1.CreditTaskRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 8, // 128: hyapp.wallet.v1.CreditLuckyGiftRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 8, // 129: hyapp.wallet.v1.CreditWheelRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 8, // 130: hyapp.wallet.v1.CreditRoomTurnoverRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 8, // 131: hyapp.wallet.v1.CreditInviteActivityRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 8, // 132: hyapp.wallet.v1.CreditAgencyOpeningRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 250, // 133: hyapp.wallet.v1.RedPacket.claims:type_name -> hyapp.wallet.v1.RedPacketClaim + 249, // 134: hyapp.wallet.v1.GetRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig + 249, // 135: hyapp.wallet.v1.UpdateRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig + 251, // 136: hyapp.wallet.v1.CreateRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 250, // 137: hyapp.wallet.v1.ClaimRedPacketResponse.claim:type_name -> hyapp.wallet.v1.RedPacketClaim + 251, // 138: hyapp.wallet.v1.ClaimRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 251, // 139: hyapp.wallet.v1.ListRedPacketsResponse.packets:type_name -> hyapp.wallet.v1.RedPacket + 251, // 140: hyapp.wallet.v1.GetRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 251, // 141: hyapp.wallet.v1.RetryRedPacketRefundResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 48, // 142: hyapp.wallet.v1.ResourceShopPurchaseOrder.resource:type_name -> hyapp.wallet.v1.Resource + 270, // 143: hyapp.wallet.v1.ListResourceShopPurchaseOrdersResponse.orders:type_name -> hyapp.wallet.v1.ResourceShopPurchaseOrder + 268, // 144: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 268, // 145: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 268, // 146: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 214, // 147: hyapp.wallet.v1.WalletCronService.ProcessVipDailyCoinRebateBatch:input_type -> hyapp.wallet.v1.ProcessVipDailyCoinRebateBatchRequest + 0, // 148: hyapp.wallet.v1.WalletService.DebitGift:input_type -> hyapp.wallet.v1.DebitGiftRequest + 1, // 149: hyapp.wallet.v1.WalletService.DebitDirectGift:input_type -> hyapp.wallet.v1.DebitDirectGiftRequest + 4, // 150: hyapp.wallet.v1.WalletService.BatchDebitGift:input_type -> hyapp.wallet.v1.BatchDebitGiftRequest + 7, // 151: hyapp.wallet.v1.WalletService.DebitRobotGift:input_type -> hyapp.wallet.v1.DebitRobotGiftRequest + 9, // 152: hyapp.wallet.v1.WalletService.GetBalances:input_type -> hyapp.wallet.v1.GetBalancesRequest + 13, // 153: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:input_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyRequest + 16, // 154: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:input_type -> hyapp.wallet.v1.GetHostSalaryProgressRequest + 19, // 155: hyapp.wallet.v1.WalletService.GetTeamHostSalaryStats:input_type -> hyapp.wallet.v1.GetTeamHostSalaryStatsRequest + 21, // 156: hyapp.wallet.v1.WalletService.AdminCreditAsset:input_type -> hyapp.wallet.v1.AdminCreditAssetRequest + 23, // 157: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:input_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockRequest + 25, // 158: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:input_type -> hyapp.wallet.v1.TransferCoinFromSellerRequest + 27, // 159: hyapp.wallet.v1.WalletService.TransferCoinSellerStockToChild:input_type -> hyapp.wallet.v1.TransferCoinSellerStockToChildRequest + 30, // 160: hyapp.wallet.v1.WalletService.ListCoinSellerSalaryExchangeRateTiers:input_type -> hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersRequest + 32, // 161: hyapp.wallet.v1.WalletService.ExchangeSalaryToCoin:input_type -> hyapp.wallet.v1.ExchangeSalaryToCoinRequest + 34, // 162: hyapp.wallet.v1.WalletService.TransferSalaryToCoinSeller:input_type -> hyapp.wallet.v1.TransferSalaryToCoinSellerRequest + 36, // 163: hyapp.wallet.v1.WalletService.FreezeSalaryWithdrawal:input_type -> hyapp.wallet.v1.FreezeSalaryWithdrawalRequest + 38, // 164: hyapp.wallet.v1.WalletService.SettleSalaryWithdrawal:input_type -> hyapp.wallet.v1.SettleSalaryWithdrawalRequest + 40, // 165: hyapp.wallet.v1.WalletService.ReleaseSalaryWithdrawal:input_type -> hyapp.wallet.v1.ReleaseSalaryWithdrawalRequest + 42, // 166: hyapp.wallet.v1.WalletService.FreezePointWithdrawal:input_type -> hyapp.wallet.v1.FreezePointWithdrawalRequest + 44, // 167: hyapp.wallet.v1.WalletService.SettlePointWithdrawal:input_type -> hyapp.wallet.v1.SettlePointWithdrawalRequest + 46, // 168: hyapp.wallet.v1.WalletService.ReleasePointWithdrawal:input_type -> hyapp.wallet.v1.ReleasePointWithdrawalRequest + 58, // 169: hyapp.wallet.v1.WalletService.ListResources:input_type -> hyapp.wallet.v1.ListResourcesRequest + 60, // 170: hyapp.wallet.v1.WalletService.GetResource:input_type -> hyapp.wallet.v1.GetResourceRequest + 62, // 171: hyapp.wallet.v1.WalletService.CreateResource:input_type -> hyapp.wallet.v1.CreateResourceRequest + 63, // 172: hyapp.wallet.v1.WalletService.UpdateResource:input_type -> hyapp.wallet.v1.UpdateResourceRequest + 64, // 173: hyapp.wallet.v1.WalletService.SetResourceStatus:input_type -> hyapp.wallet.v1.SetResourceStatusRequest + 65, // 174: hyapp.wallet.v1.WalletService.DeleteResource:input_type -> hyapp.wallet.v1.DeleteResourceRequest + 66, // 175: hyapp.wallet.v1.WalletService.BatchDeleteResources:input_type -> hyapp.wallet.v1.BatchDeleteResourcesRequest + 69, // 176: hyapp.wallet.v1.WalletService.ListResourceGroups:input_type -> hyapp.wallet.v1.ListResourceGroupsRequest + 71, // 177: hyapp.wallet.v1.WalletService.GetResourceGroup:input_type -> hyapp.wallet.v1.GetResourceGroupRequest + 73, // 178: hyapp.wallet.v1.WalletService.CreateResourceGroup:input_type -> hyapp.wallet.v1.CreateResourceGroupRequest + 74, // 179: hyapp.wallet.v1.WalletService.UpdateResourceGroup:input_type -> hyapp.wallet.v1.UpdateResourceGroupRequest + 75, // 180: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:input_type -> hyapp.wallet.v1.SetResourceGroupStatusRequest + 77, // 181: hyapp.wallet.v1.WalletService.ListGiftConfigs:input_type -> hyapp.wallet.v1.ListGiftConfigsRequest + 79, // 182: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:input_type -> hyapp.wallet.v1.ListGiftTypeConfigsRequest + 273, // 183: hyapp.wallet.v1.WalletService.GetGiftCatalogVersion:input_type -> hyapp.wallet.v1.GetGiftCatalogVersionRequest + 83, // 184: hyapp.wallet.v1.WalletService.CreateGiftConfig:input_type -> hyapp.wallet.v1.CreateGiftConfigRequest + 84, // 185: hyapp.wallet.v1.WalletService.BatchCreateGiftConfigs:input_type -> hyapp.wallet.v1.BatchCreateGiftConfigsRequest + 86, // 186: hyapp.wallet.v1.WalletService.UpdateGiftConfig:input_type -> hyapp.wallet.v1.UpdateGiftConfigRequest + 87, // 187: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:input_type -> hyapp.wallet.v1.SetGiftConfigStatusRequest + 88, // 188: hyapp.wallet.v1.WalletService.DeleteGiftConfig:input_type -> hyapp.wallet.v1.DeleteGiftConfigRequest + 81, // 189: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:input_type -> hyapp.wallet.v1.UpsertGiftTypeConfigRequest + 90, // 190: hyapp.wallet.v1.WalletService.GrantResource:input_type -> hyapp.wallet.v1.GrantResourceRequest + 91, // 191: hyapp.wallet.v1.WalletService.GrantResourceGroup:input_type -> hyapp.wallet.v1.GrantResourceGroupRequest + 92, // 192: hyapp.wallet.v1.WalletService.RevokeResourceGrant:input_type -> hyapp.wallet.v1.RevokeResourceGrantRequest + 94, // 193: hyapp.wallet.v1.WalletService.ListUserResources:input_type -> hyapp.wallet.v1.ListUserResourcesRequest + 96, // 194: hyapp.wallet.v1.WalletService.EquipUserResource:input_type -> hyapp.wallet.v1.EquipUserResourceRequest + 98, // 195: hyapp.wallet.v1.WalletService.UnequipUserResource:input_type -> hyapp.wallet.v1.UnequipUserResourceRequest + 100, // 196: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:input_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest + 103, // 197: hyapp.wallet.v1.WalletService.ListResourceGrants:input_type -> hyapp.wallet.v1.ListResourceGrantsRequest + 106, // 198: hyapp.wallet.v1.WalletService.ListResourceShopItems:input_type -> hyapp.wallet.v1.ListResourceShopItemsRequest + 108, // 199: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:input_type -> hyapp.wallet.v1.UpsertResourceShopItemsRequest + 110, // 200: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:input_type -> hyapp.wallet.v1.SetResourceShopItemStatusRequest + 271, // 201: hyapp.wallet.v1.WalletService.ListResourceShopPurchaseOrders:input_type -> hyapp.wallet.v1.ListResourceShopPurchaseOrdersRequest + 112, // 202: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:input_type -> hyapp.wallet.v1.PurchaseResourceShopItemRequest + 115, // 203: hyapp.wallet.v1.WalletService.ListRechargeBills:input_type -> hyapp.wallet.v1.ListRechargeBillsRequest + 117, // 204: hyapp.wallet.v1.WalletService.GetRechargeBillSummary:input_type -> hyapp.wallet.v1.GetRechargeBillSummaryRequest + 121, // 205: hyapp.wallet.v1.WalletService.BatchGetUserRechargeStats:input_type -> hyapp.wallet.v1.BatchGetUserRechargeStatsRequest + 123, // 206: hyapp.wallet.v1.WalletService.GetRechargeBillOverview:input_type -> hyapp.wallet.v1.GetRechargeBillOverviewRequest + 129, // 207: hyapp.wallet.v1.WalletService.RefreshGooglePaymentPrices:input_type -> hyapp.wallet.v1.RefreshGooglePaymentPricesRequest + 133, // 208: hyapp.wallet.v1.WalletService.GetWalletOverview:input_type -> hyapp.wallet.v1.GetWalletOverviewRequest + 136, // 209: hyapp.wallet.v1.WalletService.GetWalletValueSummary:input_type -> hyapp.wallet.v1.GetWalletValueSummaryRequest + 139, // 210: hyapp.wallet.v1.WalletService.GetUserGiftWall:input_type -> hyapp.wallet.v1.GetUserGiftWallRequest + 142, // 211: hyapp.wallet.v1.WalletService.ListRechargeProducts:input_type -> hyapp.wallet.v1.ListRechargeProductsRequest + 144, // 212: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:input_type -> hyapp.wallet.v1.ConfirmGooglePaymentRequest + 146, // 213: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:input_type -> hyapp.wallet.v1.ListAdminRechargeProductsRequest + 148, // 214: hyapp.wallet.v1.WalletService.CreateRechargeProduct:input_type -> hyapp.wallet.v1.CreateRechargeProductRequest + 149, // 215: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:input_type -> hyapp.wallet.v1.UpdateRechargeProductRequest + 150, // 216: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:input_type -> hyapp.wallet.v1.DeleteRechargeProductRequest + 155, // 217: hyapp.wallet.v1.WalletService.ListThirdPartyPaymentChannels:input_type -> hyapp.wallet.v1.ListThirdPartyPaymentChannelsRequest + 157, // 218: hyapp.wallet.v1.WalletService.SetThirdPartyPaymentMethodStatus:input_type -> hyapp.wallet.v1.SetThirdPartyPaymentMethodStatusRequest + 159, // 219: hyapp.wallet.v1.WalletService.UpdateThirdPartyPaymentRate:input_type -> hyapp.wallet.v1.UpdateThirdPartyPaymentRateRequest + 161, // 220: hyapp.wallet.v1.WalletService.SyncThirdPartyPaymentMethods:input_type -> hyapp.wallet.v1.SyncThirdPartyPaymentMethodsRequest + 163, // 221: hyapp.wallet.v1.WalletService.ListH5RechargeOptions:input_type -> hyapp.wallet.v1.H5RechargeOptionsRequest + 166, // 222: hyapp.wallet.v1.WalletService.CreateH5RechargeOrder:input_type -> hyapp.wallet.v1.CreateH5RechargeOrderRequest + 167, // 223: hyapp.wallet.v1.WalletService.CreateTemporaryRechargeOrder:input_type -> hyapp.wallet.v1.CreateTemporaryRechargeOrderRequest + 168, // 224: hyapp.wallet.v1.WalletService.GetTemporaryRechargeOrder:input_type -> hyapp.wallet.v1.GetTemporaryRechargeOrderRequest + 169, // 225: hyapp.wallet.v1.WalletService.ListTemporaryRechargeOrders:input_type -> hyapp.wallet.v1.ListTemporaryRechargeOrdersRequest + 171, // 226: hyapp.wallet.v1.WalletService.SubmitH5RechargeTx:input_type -> hyapp.wallet.v1.SubmitH5RechargeTxRequest + 172, // 227: hyapp.wallet.v1.WalletService.GetH5RechargeOrder:input_type -> hyapp.wallet.v1.GetH5RechargeOrderRequest + 174, // 228: hyapp.wallet.v1.WalletService.VerifyCoinSellerRechargeReceipt:input_type -> hyapp.wallet.v1.VerifyCoinSellerRechargeReceiptRequest + 176, // 229: hyapp.wallet.v1.WalletService.HandleMifapayNotify:input_type -> hyapp.wallet.v1.HandleMifapayNotifyRequest + 178, // 230: hyapp.wallet.v1.WalletService.HandleV5PayNotify:input_type -> hyapp.wallet.v1.HandleV5PayNotifyRequest + 181, // 231: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:input_type -> hyapp.wallet.v1.GetDiamondExchangeConfigRequest + 184, // 232: hyapp.wallet.v1.WalletService.ListWalletTransactions:input_type -> hyapp.wallet.v1.ListWalletTransactionsRequest + 194, // 233: hyapp.wallet.v1.WalletService.ListVipPackages:input_type -> hyapp.wallet.v1.ListVipPackagesRequest + 206, // 234: hyapp.wallet.v1.WalletService.GetVipProgramConfig:input_type -> hyapp.wallet.v1.GetVipProgramConfigRequest + 196, // 235: hyapp.wallet.v1.WalletService.GetMyVip:input_type -> hyapp.wallet.v1.GetMyVipRequest + 228, // 236: hyapp.wallet.v1.WalletService.CheckVipBenefit:input_type -> hyapp.wallet.v1.CheckVipBenefitRequest + 198, // 237: hyapp.wallet.v1.WalletService.PurchaseVip:input_type -> hyapp.wallet.v1.PurchaseVipRequest + 200, // 238: hyapp.wallet.v1.WalletService.DebitCPBreakupFee:input_type -> hyapp.wallet.v1.DebitCPBreakupFeeRequest + 202, // 239: hyapp.wallet.v1.WalletService.DebitWheelDraw:input_type -> hyapp.wallet.v1.DebitWheelDrawRequest + 204, // 240: hyapp.wallet.v1.WalletService.GrantVip:input_type -> hyapp.wallet.v1.GrantVipRequest + 222, // 241: hyapp.wallet.v1.WalletService.GrantVipTrialCard:input_type -> hyapp.wallet.v1.GrantVipTrialCardRequest + 224, // 242: hyapp.wallet.v1.WalletService.EquipVipTrialCard:input_type -> hyapp.wallet.v1.EquipVipTrialCardRequest + 226, // 243: hyapp.wallet.v1.WalletService.UnequipVipTrialCard:input_type -> hyapp.wallet.v1.UnequipVipTrialCardRequest + 231, // 244: hyapp.wallet.v1.WalletService.ListAdminVipLevels:input_type -> hyapp.wallet.v1.ListAdminVipLevelsRequest + 233, // 245: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:input_type -> hyapp.wallet.v1.UpdateAdminVipLevelsRequest + 208, // 246: hyapp.wallet.v1.WalletService.UpdateAdminVipProgramConfig:input_type -> hyapp.wallet.v1.UpdateAdminVipProgramConfigRequest + 210, // 247: hyapp.wallet.v1.WalletService.UpdateMyVipSettings:input_type -> hyapp.wallet.v1.UpdateMyVipSettingsRequest + 216, // 248: hyapp.wallet.v1.WalletService.GetMyCurrentVipDailyCoinRebate:input_type -> hyapp.wallet.v1.GetMyCurrentVipDailyCoinRebateRequest + 218, // 249: hyapp.wallet.v1.WalletService.ListMyVipDailyCoinRebateStatuses:input_type -> hyapp.wallet.v1.ListMyVipDailyCoinRebateStatusesRequest + 220, // 250: hyapp.wallet.v1.WalletService.ClaimVipDailyCoinRebate:input_type -> hyapp.wallet.v1.ClaimVipDailyCoinRebateRequest + 235, // 251: hyapp.wallet.v1.WalletService.CreditTaskReward:input_type -> hyapp.wallet.v1.CreditTaskRewardRequest + 237, // 252: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:input_type -> hyapp.wallet.v1.CreditLuckyGiftRewardRequest + 239, // 253: hyapp.wallet.v1.WalletService.CreditWheelReward:input_type -> hyapp.wallet.v1.CreditWheelRewardRequest + 241, // 254: hyapp.wallet.v1.WalletService.CreditRoomTurnoverReward:input_type -> hyapp.wallet.v1.CreditRoomTurnoverRewardRequest + 243, // 255: hyapp.wallet.v1.WalletService.CreditInviteActivityReward:input_type -> hyapp.wallet.v1.CreditInviteActivityRewardRequest + 245, // 256: hyapp.wallet.v1.WalletService.CreditAgencyOpeningReward:input_type -> hyapp.wallet.v1.CreditAgencyOpeningRewardRequest + 247, // 257: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:input_type -> hyapp.wallet.v1.ApplyGameCoinChangeRequest + 252, // 258: hyapp.wallet.v1.WalletService.GetRedPacketConfig:input_type -> hyapp.wallet.v1.GetRedPacketConfigRequest + 254, // 259: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:input_type -> hyapp.wallet.v1.UpdateRedPacketConfigRequest + 256, // 260: hyapp.wallet.v1.WalletService.CreateRedPacket:input_type -> hyapp.wallet.v1.CreateRedPacketRequest + 258, // 261: hyapp.wallet.v1.WalletService.ClaimRedPacket:input_type -> hyapp.wallet.v1.ClaimRedPacketRequest + 260, // 262: hyapp.wallet.v1.WalletService.ListRedPackets:input_type -> hyapp.wallet.v1.ListRedPacketsRequest + 262, // 263: hyapp.wallet.v1.WalletService.GetRedPacket:input_type -> hyapp.wallet.v1.GetRedPacketRequest + 264, // 264: hyapp.wallet.v1.WalletService.ExpireRedPackets:input_type -> hyapp.wallet.v1.ExpireRedPacketsRequest + 266, // 265: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:input_type -> hyapp.wallet.v1.RetryRedPacketRefundRequest + 269, // 266: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 269, // 267: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 269, // 268: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 215, // 269: hyapp.wallet.v1.WalletCronService.ProcessVipDailyCoinRebateBatch:output_type -> hyapp.wallet.v1.ProcessVipDailyCoinRebateBatchResponse + 2, // 270: hyapp.wallet.v1.WalletService.DebitGift:output_type -> hyapp.wallet.v1.DebitGiftResponse + 2, // 271: hyapp.wallet.v1.WalletService.DebitDirectGift:output_type -> hyapp.wallet.v1.DebitGiftResponse + 6, // 272: hyapp.wallet.v1.WalletService.BatchDebitGift:output_type -> hyapp.wallet.v1.BatchDebitGiftResponse + 2, // 273: hyapp.wallet.v1.WalletService.DebitRobotGift:output_type -> hyapp.wallet.v1.DebitGiftResponse + 10, // 274: hyapp.wallet.v1.WalletService.GetBalances:output_type -> hyapp.wallet.v1.GetBalancesResponse + 14, // 275: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:output_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse + 17, // 276: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:output_type -> hyapp.wallet.v1.GetHostSalaryProgressResponse + 20, // 277: hyapp.wallet.v1.WalletService.GetTeamHostSalaryStats:output_type -> hyapp.wallet.v1.GetTeamHostSalaryStatsResponse + 22, // 278: hyapp.wallet.v1.WalletService.AdminCreditAsset:output_type -> hyapp.wallet.v1.AdminCreditAssetResponse + 24, // 279: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:output_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockResponse + 26, // 280: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:output_type -> hyapp.wallet.v1.TransferCoinFromSellerResponse + 28, // 281: hyapp.wallet.v1.WalletService.TransferCoinSellerStockToChild:output_type -> hyapp.wallet.v1.TransferCoinSellerStockToChildResponse + 31, // 282: hyapp.wallet.v1.WalletService.ListCoinSellerSalaryExchangeRateTiers:output_type -> hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersResponse + 33, // 283: hyapp.wallet.v1.WalletService.ExchangeSalaryToCoin:output_type -> hyapp.wallet.v1.ExchangeSalaryToCoinResponse + 35, // 284: hyapp.wallet.v1.WalletService.TransferSalaryToCoinSeller:output_type -> hyapp.wallet.v1.TransferSalaryToCoinSellerResponse + 37, // 285: hyapp.wallet.v1.WalletService.FreezeSalaryWithdrawal:output_type -> hyapp.wallet.v1.FreezeSalaryWithdrawalResponse + 39, // 286: hyapp.wallet.v1.WalletService.SettleSalaryWithdrawal:output_type -> hyapp.wallet.v1.SettleSalaryWithdrawalResponse + 41, // 287: hyapp.wallet.v1.WalletService.ReleaseSalaryWithdrawal:output_type -> hyapp.wallet.v1.ReleaseSalaryWithdrawalResponse + 43, // 288: hyapp.wallet.v1.WalletService.FreezePointWithdrawal:output_type -> hyapp.wallet.v1.FreezePointWithdrawalResponse + 45, // 289: hyapp.wallet.v1.WalletService.SettlePointWithdrawal:output_type -> hyapp.wallet.v1.SettlePointWithdrawalResponse + 47, // 290: hyapp.wallet.v1.WalletService.ReleasePointWithdrawal:output_type -> hyapp.wallet.v1.ReleasePointWithdrawalResponse + 59, // 291: hyapp.wallet.v1.WalletService.ListResources:output_type -> hyapp.wallet.v1.ListResourcesResponse + 61, // 292: hyapp.wallet.v1.WalletService.GetResource:output_type -> hyapp.wallet.v1.GetResourceResponse + 68, // 293: hyapp.wallet.v1.WalletService.CreateResource:output_type -> hyapp.wallet.v1.ResourceResponse + 68, // 294: hyapp.wallet.v1.WalletService.UpdateResource:output_type -> hyapp.wallet.v1.ResourceResponse + 68, // 295: hyapp.wallet.v1.WalletService.SetResourceStatus:output_type -> hyapp.wallet.v1.ResourceResponse + 68, // 296: hyapp.wallet.v1.WalletService.DeleteResource:output_type -> hyapp.wallet.v1.ResourceResponse + 67, // 297: hyapp.wallet.v1.WalletService.BatchDeleteResources:output_type -> hyapp.wallet.v1.BatchDeleteResourcesResponse + 70, // 298: hyapp.wallet.v1.WalletService.ListResourceGroups:output_type -> hyapp.wallet.v1.ListResourceGroupsResponse + 72, // 299: hyapp.wallet.v1.WalletService.GetResourceGroup:output_type -> hyapp.wallet.v1.GetResourceGroupResponse + 76, // 300: hyapp.wallet.v1.WalletService.CreateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 76, // 301: hyapp.wallet.v1.WalletService.UpdateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 76, // 302: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 78, // 303: hyapp.wallet.v1.WalletService.ListGiftConfigs:output_type -> hyapp.wallet.v1.ListGiftConfigsResponse + 80, // 304: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:output_type -> hyapp.wallet.v1.ListGiftTypeConfigsResponse + 274, // 305: hyapp.wallet.v1.WalletService.GetGiftCatalogVersion:output_type -> hyapp.wallet.v1.GetGiftCatalogVersionResponse + 89, // 306: hyapp.wallet.v1.WalletService.CreateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse + 85, // 307: hyapp.wallet.v1.WalletService.BatchCreateGiftConfigs:output_type -> hyapp.wallet.v1.BatchCreateGiftConfigsResponse + 89, // 308: hyapp.wallet.v1.WalletService.UpdateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse + 89, // 309: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:output_type -> hyapp.wallet.v1.GiftConfigResponse + 89, // 310: hyapp.wallet.v1.WalletService.DeleteGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse + 82, // 311: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:output_type -> hyapp.wallet.v1.GiftTypeConfigResponse + 93, // 312: hyapp.wallet.v1.WalletService.GrantResource:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 93, // 313: hyapp.wallet.v1.WalletService.GrantResourceGroup:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 93, // 314: hyapp.wallet.v1.WalletService.RevokeResourceGrant:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 95, // 315: hyapp.wallet.v1.WalletService.ListUserResources:output_type -> hyapp.wallet.v1.ListUserResourcesResponse + 97, // 316: hyapp.wallet.v1.WalletService.EquipUserResource:output_type -> hyapp.wallet.v1.EquipUserResourceResponse + 99, // 317: hyapp.wallet.v1.WalletService.UnequipUserResource:output_type -> hyapp.wallet.v1.UnequipUserResourceResponse + 102, // 318: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:output_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse + 104, // 319: hyapp.wallet.v1.WalletService.ListResourceGrants:output_type -> hyapp.wallet.v1.ListResourceGrantsResponse + 107, // 320: hyapp.wallet.v1.WalletService.ListResourceShopItems:output_type -> hyapp.wallet.v1.ListResourceShopItemsResponse + 109, // 321: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:output_type -> hyapp.wallet.v1.UpsertResourceShopItemsResponse + 111, // 322: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:output_type -> hyapp.wallet.v1.ResourceShopItemResponse + 272, // 323: hyapp.wallet.v1.WalletService.ListResourceShopPurchaseOrders:output_type -> hyapp.wallet.v1.ListResourceShopPurchaseOrdersResponse + 113, // 324: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:output_type -> hyapp.wallet.v1.PurchaseResourceShopItemResponse + 116, // 325: hyapp.wallet.v1.WalletService.ListRechargeBills:output_type -> hyapp.wallet.v1.ListRechargeBillsResponse + 119, // 326: hyapp.wallet.v1.WalletService.GetRechargeBillSummary:output_type -> hyapp.wallet.v1.GetRechargeBillSummaryResponse + 122, // 327: hyapp.wallet.v1.WalletService.BatchGetUserRechargeStats:output_type -> hyapp.wallet.v1.BatchGetUserRechargeStatsResponse + 128, // 328: hyapp.wallet.v1.WalletService.GetRechargeBillOverview:output_type -> hyapp.wallet.v1.GetRechargeBillOverviewResponse + 131, // 329: hyapp.wallet.v1.WalletService.RefreshGooglePaymentPrices:output_type -> hyapp.wallet.v1.RefreshGooglePaymentPricesResponse + 134, // 330: hyapp.wallet.v1.WalletService.GetWalletOverview:output_type -> hyapp.wallet.v1.GetWalletOverviewResponse + 137, // 331: hyapp.wallet.v1.WalletService.GetWalletValueSummary:output_type -> hyapp.wallet.v1.GetWalletValueSummaryResponse + 140, // 332: hyapp.wallet.v1.WalletService.GetUserGiftWall:output_type -> hyapp.wallet.v1.GetUserGiftWallResponse + 143, // 333: hyapp.wallet.v1.WalletService.ListRechargeProducts:output_type -> hyapp.wallet.v1.ListRechargeProductsResponse + 145, // 334: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:output_type -> hyapp.wallet.v1.ConfirmGooglePaymentResponse + 147, // 335: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:output_type -> hyapp.wallet.v1.ListAdminRechargeProductsResponse + 151, // 336: hyapp.wallet.v1.WalletService.CreateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse + 151, // 337: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse + 152, // 338: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:output_type -> hyapp.wallet.v1.DeleteRechargeProductResponse + 156, // 339: hyapp.wallet.v1.WalletService.ListThirdPartyPaymentChannels:output_type -> hyapp.wallet.v1.ListThirdPartyPaymentChannelsResponse + 158, // 340: hyapp.wallet.v1.WalletService.SetThirdPartyPaymentMethodStatus:output_type -> hyapp.wallet.v1.ThirdPartyPaymentMethodResponse + 158, // 341: hyapp.wallet.v1.WalletService.UpdateThirdPartyPaymentRate:output_type -> hyapp.wallet.v1.ThirdPartyPaymentMethodResponse + 162, // 342: hyapp.wallet.v1.WalletService.SyncThirdPartyPaymentMethods:output_type -> hyapp.wallet.v1.SyncThirdPartyPaymentMethodsResponse + 164, // 343: hyapp.wallet.v1.WalletService.ListH5RechargeOptions:output_type -> hyapp.wallet.v1.H5RechargeOptionsResponse + 173, // 344: hyapp.wallet.v1.WalletService.CreateH5RechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse + 173, // 345: hyapp.wallet.v1.WalletService.CreateTemporaryRechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse + 173, // 346: hyapp.wallet.v1.WalletService.GetTemporaryRechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse + 170, // 347: hyapp.wallet.v1.WalletService.ListTemporaryRechargeOrders:output_type -> hyapp.wallet.v1.ListTemporaryRechargeOrdersResponse + 173, // 348: hyapp.wallet.v1.WalletService.SubmitH5RechargeTx:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse + 173, // 349: hyapp.wallet.v1.WalletService.GetH5RechargeOrder:output_type -> hyapp.wallet.v1.H5RechargeOrderResponse + 175, // 350: hyapp.wallet.v1.WalletService.VerifyCoinSellerRechargeReceipt:output_type -> hyapp.wallet.v1.VerifyCoinSellerRechargeReceiptResponse + 177, // 351: hyapp.wallet.v1.WalletService.HandleMifapayNotify:output_type -> hyapp.wallet.v1.HandleMifapayNotifyResponse + 179, // 352: hyapp.wallet.v1.WalletService.HandleV5PayNotify:output_type -> hyapp.wallet.v1.HandleV5PayNotifyResponse + 182, // 353: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:output_type -> hyapp.wallet.v1.GetDiamondExchangeConfigResponse + 185, // 354: hyapp.wallet.v1.WalletService.ListWalletTransactions:output_type -> hyapp.wallet.v1.ListWalletTransactionsResponse + 195, // 355: hyapp.wallet.v1.WalletService.ListVipPackages:output_type -> hyapp.wallet.v1.ListVipPackagesResponse + 207, // 356: hyapp.wallet.v1.WalletService.GetVipProgramConfig:output_type -> hyapp.wallet.v1.GetVipProgramConfigResponse + 197, // 357: hyapp.wallet.v1.WalletService.GetMyVip:output_type -> hyapp.wallet.v1.GetMyVipResponse + 229, // 358: hyapp.wallet.v1.WalletService.CheckVipBenefit:output_type -> hyapp.wallet.v1.CheckVipBenefitResponse + 199, // 359: hyapp.wallet.v1.WalletService.PurchaseVip:output_type -> hyapp.wallet.v1.PurchaseVipResponse + 201, // 360: hyapp.wallet.v1.WalletService.DebitCPBreakupFee:output_type -> hyapp.wallet.v1.DebitCPBreakupFeeResponse + 203, // 361: hyapp.wallet.v1.WalletService.DebitWheelDraw:output_type -> hyapp.wallet.v1.DebitWheelDrawResponse + 205, // 362: hyapp.wallet.v1.WalletService.GrantVip:output_type -> hyapp.wallet.v1.GrantVipResponse + 223, // 363: hyapp.wallet.v1.WalletService.GrantVipTrialCard:output_type -> hyapp.wallet.v1.GrantVipTrialCardResponse + 225, // 364: hyapp.wallet.v1.WalletService.EquipVipTrialCard:output_type -> hyapp.wallet.v1.EquipVipTrialCardResponse + 227, // 365: hyapp.wallet.v1.WalletService.UnequipVipTrialCard:output_type -> hyapp.wallet.v1.UnequipVipTrialCardResponse + 232, // 366: hyapp.wallet.v1.WalletService.ListAdminVipLevels:output_type -> hyapp.wallet.v1.ListAdminVipLevelsResponse + 234, // 367: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:output_type -> hyapp.wallet.v1.UpdateAdminVipLevelsResponse + 209, // 368: hyapp.wallet.v1.WalletService.UpdateAdminVipProgramConfig:output_type -> hyapp.wallet.v1.UpdateAdminVipProgramConfigResponse + 211, // 369: hyapp.wallet.v1.WalletService.UpdateMyVipSettings:output_type -> hyapp.wallet.v1.UpdateMyVipSettingsResponse + 217, // 370: hyapp.wallet.v1.WalletService.GetMyCurrentVipDailyCoinRebate:output_type -> hyapp.wallet.v1.GetMyCurrentVipDailyCoinRebateResponse + 219, // 371: hyapp.wallet.v1.WalletService.ListMyVipDailyCoinRebateStatuses:output_type -> hyapp.wallet.v1.ListMyVipDailyCoinRebateStatusesResponse + 221, // 372: hyapp.wallet.v1.WalletService.ClaimVipDailyCoinRebate:output_type -> hyapp.wallet.v1.ClaimVipDailyCoinRebateResponse + 236, // 373: hyapp.wallet.v1.WalletService.CreditTaskReward:output_type -> hyapp.wallet.v1.CreditTaskRewardResponse + 238, // 374: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:output_type -> hyapp.wallet.v1.CreditLuckyGiftRewardResponse + 240, // 375: hyapp.wallet.v1.WalletService.CreditWheelReward:output_type -> hyapp.wallet.v1.CreditWheelRewardResponse + 242, // 376: hyapp.wallet.v1.WalletService.CreditRoomTurnoverReward:output_type -> hyapp.wallet.v1.CreditRoomTurnoverRewardResponse + 244, // 377: hyapp.wallet.v1.WalletService.CreditInviteActivityReward:output_type -> hyapp.wallet.v1.CreditInviteActivityRewardResponse + 246, // 378: hyapp.wallet.v1.WalletService.CreditAgencyOpeningReward:output_type -> hyapp.wallet.v1.CreditAgencyOpeningRewardResponse + 248, // 379: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:output_type -> hyapp.wallet.v1.ApplyGameCoinChangeResponse + 253, // 380: hyapp.wallet.v1.WalletService.GetRedPacketConfig:output_type -> hyapp.wallet.v1.GetRedPacketConfigResponse + 255, // 381: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:output_type -> hyapp.wallet.v1.UpdateRedPacketConfigResponse + 257, // 382: hyapp.wallet.v1.WalletService.CreateRedPacket:output_type -> hyapp.wallet.v1.CreateRedPacketResponse + 259, // 383: hyapp.wallet.v1.WalletService.ClaimRedPacket:output_type -> hyapp.wallet.v1.ClaimRedPacketResponse + 261, // 384: hyapp.wallet.v1.WalletService.ListRedPackets:output_type -> hyapp.wallet.v1.ListRedPacketsResponse + 263, // 385: hyapp.wallet.v1.WalletService.GetRedPacket:output_type -> hyapp.wallet.v1.GetRedPacketResponse + 265, // 386: hyapp.wallet.v1.WalletService.ExpireRedPackets:output_type -> hyapp.wallet.v1.ExpireRedPacketsResponse + 267, // 387: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:output_type -> hyapp.wallet.v1.RetryRedPacketRefundResponse + 266, // [266:388] is the sub-list for method output_type + 144, // [144:266] is the sub-list for method input_type + 144, // [144:144] is the sub-list for extension type_name + 144, // [144:144] is the sub-list for extension extendee + 0, // [0:144] is the sub-list for field type_name } func init() { file_proto_wallet_v1_wallet_proto_init() } @@ -27235,15 +30691,17 @@ func file_proto_wallet_v1_wallet_proto_init() { } file_proto_wallet_v1_wallet_proto_msgTypes[62].OneofWrappers = []any{} file_proto_wallet_v1_wallet_proto_msgTypes[63].OneofWrappers = []any{} - file_proto_wallet_v1_wallet_proto_msgTypes[145].OneofWrappers = []any{} - file_proto_wallet_v1_wallet_proto_msgTypes[146].OneofWrappers = []any{} + file_proto_wallet_v1_wallet_proto_msgTypes[148].OneofWrappers = []any{} + file_proto_wallet_v1_wallet_proto_msgTypes[149].OneofWrappers = []any{} + file_proto_wallet_v1_wallet_proto_msgTypes[210].OneofWrappers = []any{} + file_proto_wallet_v1_wallet_proto_msgTypes[222].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_wallet_v1_wallet_proto_rawDesc, NumEnums: 0, - NumMessages: 244, + NumMessages: 276, NumExtensions: 0, NumServices: 2, }, diff --git a/api/proto/wallet/v1/wallet.proto b/api/proto/wallet/v1/wallet.proto index 8043aa6e..a29ab30c 100644 --- a/api/proto/wallet/v1/wallet.proto +++ b/api/proto/wallet/v1/wallet.proto @@ -1267,6 +1267,26 @@ message GetRechargeBillSummaryResponse { RechargeBillSummaryBucket coin_seller = 4; } +// UserRechargeStats 是 wallet-service 已维护的用户累计充值聚合,不允许后台回扫充值流水临时计算。 +message UserRechargeStats { + int64 user_id = 1; + int64 recharge_count = 2; + int64 total_coin_amount = 3; + int64 total_usd_minor_amount = 4; + int64 first_recharged_at_ms = 5; + int64 updated_at_ms = 6; +} + +message BatchGetUserRechargeStatsRequest { + string request_id = 1; + string app_code = 2; + repeated int64 user_ids = 3; +} + +message BatchGetUserRechargeStatsResponse { + repeated UserRechargeStats items = 1; +} + message GetRechargeBillOverviewRequest { string request_id = 1; string app_code = 2; @@ -1887,6 +1907,54 @@ message VipRewardItem { string animation_url = 9; } +// VipProgramConfig 是按 App 隔离的 VIP 规则开关。业务服务只能依据这些显式策略执行, +// 禁止通过 app_code 分支推断升级有效期、权益继承或后台发放语义。 +message VipProgramConfig { + string app_code = 1; + // program_type: legacy_timed/tiered_privilege_v1。 + string program_type = 2; + int32 level_count = 3; + // same_level_expiry_policy: extend_remaining;同级购买从当前有效截止时间续期。 + string same_level_expiry_policy = 4; + // upgrade_expiry_policy: extend_remaining/replace_from_now。 + string upgrade_expiry_policy = 5; + // downgrade_purchase_policy 首版固定 reject,保留字段用于后台完整展示当前规则。 + string downgrade_purchase_policy = 6; + // benefit_inheritance_policy 当前固定 target_only;每级提交最终完整集合,不做自动继承。 + string benefit_inheritance_policy = 7; + // grant_mode: direct_membership/trial_card,决定后台“赠送 VIP”的真实账务对象。 + string grant_mode = 8; + bool trial_card_enabled = 9; + string status = 10; + int64 config_version = 11; + int64 updated_by_admin_id = 12; + int64 created_at_ms = 13; + int64 updated_at_ms = 14; +} + +// VipBenefit 是服务端可执行的权益事实。resource_id 为 0 表示纯功能特权,非 0 时 +// 指向钱包资源;trial_enabled=false 的权益不会进入体验卡产生的 effective_benefits。 +message VipBenefit { + string benefit_code = 1; + string name = 2; + // benefit_type: decoration/function。 + string benefit_type = 3; + // unlock_level 只作为 P1 默认矩阵的来源信息;后台仍按每个等级提交完整权益集合, + // 运行时不得据此自动补齐高等级权益。 + int32 unlock_level = 4; + string status = 5; + bool trial_enabled = 6; + int64 resource_id = 7; + string resource_type = 8; + // execution_scope 标识 wallet/room/user/notice 等实际权限执行方,不代表服务间直连。 + string execution_scope = 9; + bool auto_equip = 10; + int32 sort_order = 11; + string metadata_json = 12; + int64 created_at_ms = 13; + int64 updated_at_ms = 14; +} + message VipLevel { int32 level = 1; string name = 2; @@ -1903,6 +1971,9 @@ message VipLevel { string purchase_locked_reason = 13; int64 created_at_ms = 14; int64 updated_at_ms = 15; + // benefits 是后台为该等级显式保存的最终权益集合,运行时不按 unlock_level 自动继承。 + repeated VipBenefit benefits = 16; + int64 config_version = 17; } message UserVip { @@ -1913,6 +1984,54 @@ message UserVip { int64 started_at_ms = 5; int64 expires_at_ms = 6; int64 updated_at_ms = 7; + string program_type = 8; + int64 config_version = 9; +} + +// VipTrialCard 是体验卡背包权益的 VIP 投影。entitlement_id 复用通用背包佩戴事实, +// 切换卡片只改变装备记录,不修改任何卡片自身的 expires_at_ms。 +message VipTrialCard { + string trial_card_id = 1; + string entitlement_id = 2; + int64 resource_id = 3; + int64 user_id = 4; + int32 level = 5; + string name = 6; + string status = 7; + bool equipped = 8; + int64 duration_ms = 9; + int64 effective_at_ms = 10; + int64 expires_at_ms = 11; + int64 remaining_duration_ms = 12; + string grant_source = 13; + string source_grant_id = 14; + int64 created_at_ms = 15; + int64 updated_at_ms = 16; +} + +// VipUserSettings 是用户按 App 隔离的可关闭 VIP 功能偏好。没有持久记录时 wallet +// 仍返回两个默认开启值,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; +} + +// VipState 同时返回付费会员、当前佩戴体验卡和最终生效会员,避免调用方自行合并两层状态。 +// effective_benefits 是钱包按 paid/trial 来源、该等级显式矩阵和 trial_enabled 过滤后的资格事实; +// 对可关闭通知,执行方还必须结合 user_settings 或调用 CheckVipBenefit。 +message VipState { + UserVip paid_vip = 1; + VipTrialCard equipped_trial_card = 2; + UserVip effective_vip = 3; + // effective_source: paid/trial/none。 + string effective_source = 4; + repeated VipBenefit effective_benefits = 5; + int64 evaluated_at_ms = 6; + VipProgramConfig program_config = 7; + VipUserSettings user_settings = 8; } message ListVipPackagesRequest { @@ -1924,6 +2043,8 @@ message ListVipPackagesRequest { message ListVipPackagesResponse { UserVip current_vip = 1; repeated VipLevel packages = 2; + VipState state = 3; + VipProgramConfig program_config = 4; } message GetMyVipRequest { @@ -1934,6 +2055,7 @@ message GetMyVipRequest { message GetMyVipResponse { UserVip vip = 1; + VipState state = 2; } message PurchaseVipRequest { @@ -1950,6 +2072,7 @@ message PurchaseVipResponse { int64 coin_spent = 4; int64 coin_balance_after = 5; repeated VipRewardItem reward_items = 6; + VipState state = 7; } message DebitCPBreakupFeeRequest { @@ -1999,6 +2122,205 @@ message GrantVipResponse { UserVip vip = 2; repeated VipRewardItem reward_items = 3; int64 server_time_ms = 4; + VipState state = 5; +} + +message GetVipProgramConfigRequest { + string request_id = 1; + string app_code = 2; +} + +message GetVipProgramConfigResponse { + VipProgramConfig config = 1; + repeated VipBenefit benefits = 2; + int64 server_time_ms = 3; +} + +// UpdateAdminVipProgramConfigRequest 以完整配置替换单 App 当前规则;config_version 由服务端递增, +// 客户端提交的审计时间和操作者字段不会被信任。 +message UpdateAdminVipProgramConfigRequest { + string request_id = 1; + string app_code = 2; + VipProgramConfig config = 3; + int64 operator_user_id = 4; +} + +message UpdateAdminVipProgramConfigResponse { + VipProgramConfig config = 1; + int64 server_time_ms = 2; +} + +// UpdateMyVipSettingsRequest 使用 optional 保留 PATCH 语义;显式 false 不能被当成未提交。 +message UpdateMyVipSettingsRequest { + string request_id = 1; + string app_code = 2; + int64 user_id = 3; + optional bool room_entry_notice_enabled = 4; + optional bool online_global_notice_enabled = 5; +} + +message UpdateMyVipSettingsResponse { + VipUserSettings settings = 1; + int64 server_time_ms = 2; +} + +// VipDailyCoinRebateRun 固化某个 UTC 自然日的返现金额矩阵。批任务开始后即使后台 +// 修改等级权益,后续分页也只能复用本 run 的 config_version/level_amounts_json。 +message VipDailyCoinRebateRun { + string run_id = 1; + string task_day = 2; + int64 day_start_ms = 3; + int64 day_end_ms = 4; + int64 config_version = 5; + string level_amounts_json = 6; + string status = 7; + int64 last_user_id = 8; + int64 scanned_count = 9; + int64 created_count = 10; + int64 created_at_ms = 11; + int64 updated_at_ms = 12; + int64 completed_at_ms = 13; +} + +// VipDailyCoinRebate 是付费 VIP 在 UTC 日切时生成的可领取金币事实。体验卡不会生成; +// status 返回 claimable/claimed/expired,expired 可由查询时钟投影而不改写历史行。 +message VipDailyCoinRebate { + string rebate_id = 1; + int64 user_id = 2; + string task_day = 3; + int32 vip_level = 4; + string vip_name = 5; + int64 coin_amount = 6; + string status = 7; + int64 available_at_ms = 8; + int64 expires_at_ms = 9; + int64 config_version = 10; + int64 claimed_at_ms = 11; + string wallet_transaction_id = 12; + int64 created_at_ms = 13; + int64 updated_at_ms = 14; +} + +// ProcessVipDailyCoinRebateBatchRequest 由 WalletCronService 接收。task_day 为空时按 +// wallet-service 当前 UTC 日期处理;同 App+task_day 始终创建或复用同一个 run。 +message ProcessVipDailyCoinRebateBatchRequest { + string request_id = 1; + string app_code = 2; + string task_day = 3; + int32 batch_size = 4; +} + +message ProcessVipDailyCoinRebateBatchResponse { + VipDailyCoinRebateRun run = 1; + int32 scanned_count = 2; + int32 created_count = 3; + bool has_more = 4; + int64 server_time_ms = 5; +} + +message GetMyCurrentVipDailyCoinRebateRequest { + string request_id = 1; + string app_code = 2; + int64 user_id = 3; +} + +message GetMyCurrentVipDailyCoinRebateResponse { + bool found = 1; + VipDailyCoinRebate rebate = 2; + int64 server_time_ms = 3; +} + +message ListMyVipDailyCoinRebateStatusesRequest { + string request_id = 1; + string app_code = 2; + int64 user_id = 3; + int32 page = 4; + int32 page_size = 5; + // rebate_ids 非空时精确恢复指定通知的领取状态,最多 100 个;仍强制按 user_id 隔离。 + repeated string rebate_ids = 6; +} + +message ListMyVipDailyCoinRebateStatusesResponse { + repeated VipDailyCoinRebate rebates = 1; + int64 total = 2; + int64 server_time_ms = 3; +} + +message ClaimVipDailyCoinRebateRequest { + string command_id = 1; + string app_code = 2; + int64 user_id = 3; + string rebate_id = 4; +} + +message ClaimVipDailyCoinRebateResponse { + VipDailyCoinRebate rebate = 1; + string transaction_id = 2; + AssetBalance coin_balance = 3; + int64 server_time_ms = 4; +} + +// GrantVipTrialCardRequest 允许后台直接按 level+duration_ms 发卡;resource_id 为空时按 +// vip_trial_card_{level} 解析同 App 预置资源,非空时也必须匹配该等级。 +message GrantVipTrialCardRequest { + string command_id = 1; + string app_code = 2; + int64 target_user_id = 3; + int32 level = 4; + int64 duration_ms = 5; + optional int64 resource_id = 6; + string grant_source = 7; + int64 operator_user_id = 8; + string reason = 9; +} + +message GrantVipTrialCardResponse { + VipTrialCard trial_card = 1; + VipState state = 2; + int64 server_time_ms = 3; +} + +message EquipVipTrialCardRequest { + string request_id = 1; + string app_code = 2; + int64 user_id = 3; + // entitlement_id 是背包实例标识,保证同资源的多张卡也能被精确佩戴。 + string entitlement_id = 4; +} + +message EquipVipTrialCardResponse { + VipTrialCard trial_card = 1; + VipState state = 2; + int64 server_time_ms = 3; +} + +message UnequipVipTrialCardRequest { + string request_id = 1; + string app_code = 2; + int64 user_id = 3; +} + +message UnequipVipTrialCardResponse { + bool unequipped = 1; + VipState state = 2; + int64 server_time_ms = 3; +} + +// CheckVipBenefit 供 room/user 等权益执行方校验单个特权。调用方不能只比较 VIP level, +// 因为体验卡排除项和 App 配置会改变最终可执行权益集合。 +message CheckVipBenefitRequest { + string request_id = 1; + string app_code = 2; + int64 user_id = 3; + string benefit_code = 4; +} + +message CheckVipBenefitResponse { + bool allowed = 1; + VipBenefit benefit = 2; + VipState state = 3; + string denial_reason = 4; + int64 evaluated_at_ms = 5; } message AdminVipLevelInput { @@ -2010,6 +2332,8 @@ message AdminVipLevelInput { int64 reward_resource_group_id = 6; int32 sort_order = 7; int64 required_recharge_coin_amount = 8; + // benefits 是该等级完整、显式的权益集合;服务端不根据 unlock_level 自动继承。 + repeated VipBenefit benefits = 9; } message ListAdminVipLevelsRequest { @@ -2020,6 +2344,7 @@ message ListAdminVipLevelsRequest { message ListAdminVipLevelsResponse { repeated VipLevel levels = 1; int64 server_time_ms = 2; + VipProgramConfig program_config = 3; } message UpdateAdminVipLevelsRequest { @@ -2032,6 +2357,7 @@ message UpdateAdminVipLevelsRequest { message UpdateAdminVipLevelsResponse { repeated VipLevel levels = 1; int64 server_time_ms = 2; + VipProgramConfig program_config = 3; } // CreditTaskRewardRequest 是 activity-service 领取任务奖励时调用的钱包入账命令。 @@ -2440,6 +2766,7 @@ service WalletCronService { rpc ProcessHostSalaryDailySettlementBatch(CronBatchRequest) returns (CronBatchResponse); rpc ProcessHostSalaryHalfMonthSettlementBatch(CronBatchRequest) returns (CronBatchResponse); rpc ProcessHostSalaryMonthEndBatch(CronBatchRequest) returns (CronBatchResponse); + rpc ProcessVipDailyCoinRebateBatch(ProcessVipDailyCoinRebateBatchRequest) returns (ProcessVipDailyCoinRebateBatchResponse); } // WalletService 是内部账务 gRPC 边界,外部 HTTP 入口仍由 gateway-service 承载。 @@ -2502,6 +2829,7 @@ service WalletService { rpc PurchaseResourceShopItem(PurchaseResourceShopItemRequest) returns (PurchaseResourceShopItemResponse); rpc ListRechargeBills(ListRechargeBillsRequest) returns (ListRechargeBillsResponse); rpc GetRechargeBillSummary(GetRechargeBillSummaryRequest) returns (GetRechargeBillSummaryResponse); + rpc BatchGetUserRechargeStats(BatchGetUserRechargeStatsRequest) returns (BatchGetUserRechargeStatsResponse); rpc GetRechargeBillOverview(GetRechargeBillOverviewRequest) returns (GetRechargeBillOverviewResponse); rpc RefreshGooglePaymentPrices(RefreshGooglePaymentPricesRequest) returns (RefreshGooglePaymentPricesResponse); rpc GetWalletOverview(GetWalletOverviewRequest) returns (GetWalletOverviewResponse); @@ -2530,13 +2858,23 @@ service WalletService { rpc GetDiamondExchangeConfig(GetDiamondExchangeConfigRequest) returns (GetDiamondExchangeConfigResponse); rpc ListWalletTransactions(ListWalletTransactionsRequest) returns (ListWalletTransactionsResponse); rpc ListVipPackages(ListVipPackagesRequest) returns (ListVipPackagesResponse); + rpc GetVipProgramConfig(GetVipProgramConfigRequest) returns (GetVipProgramConfigResponse); rpc GetMyVip(GetMyVipRequest) returns (GetMyVipResponse); + rpc CheckVipBenefit(CheckVipBenefitRequest) returns (CheckVipBenefitResponse); rpc PurchaseVip(PurchaseVipRequest) returns (PurchaseVipResponse); rpc DebitCPBreakupFee(DebitCPBreakupFeeRequest) returns (DebitCPBreakupFeeResponse); rpc DebitWheelDraw(DebitWheelDrawRequest) returns (DebitWheelDrawResponse); rpc GrantVip(GrantVipRequest) returns (GrantVipResponse); + rpc GrantVipTrialCard(GrantVipTrialCardRequest) returns (GrantVipTrialCardResponse); + rpc EquipVipTrialCard(EquipVipTrialCardRequest) returns (EquipVipTrialCardResponse); + rpc UnequipVipTrialCard(UnequipVipTrialCardRequest) returns (UnequipVipTrialCardResponse); rpc ListAdminVipLevels(ListAdminVipLevelsRequest) returns (ListAdminVipLevelsResponse); rpc UpdateAdminVipLevels(UpdateAdminVipLevelsRequest) returns (UpdateAdminVipLevelsResponse); + rpc UpdateAdminVipProgramConfig(UpdateAdminVipProgramConfigRequest) returns (UpdateAdminVipProgramConfigResponse); + rpc UpdateMyVipSettings(UpdateMyVipSettingsRequest) returns (UpdateMyVipSettingsResponse); + rpc GetMyCurrentVipDailyCoinRebate(GetMyCurrentVipDailyCoinRebateRequest) returns (GetMyCurrentVipDailyCoinRebateResponse); + rpc ListMyVipDailyCoinRebateStatuses(ListMyVipDailyCoinRebateStatusesRequest) returns (ListMyVipDailyCoinRebateStatusesResponse); + rpc ClaimVipDailyCoinRebate(ClaimVipDailyCoinRebateRequest) returns (ClaimVipDailyCoinRebateResponse); rpc CreditTaskReward(CreditTaskRewardRequest) returns (CreditTaskRewardResponse); rpc CreditLuckyGiftReward(CreditLuckyGiftRewardRequest) returns (CreditLuckyGiftRewardResponse); rpc CreditWheelReward(CreditWheelRewardRequest) returns (CreditWheelRewardResponse); diff --git a/api/proto/wallet/v1/wallet_grpc.pb.go b/api/proto/wallet/v1/wallet_grpc.pb.go index 47c93648..8e16fcf7 100644 --- a/api/proto/wallet/v1/wallet_grpc.pb.go +++ b/api/proto/wallet/v1/wallet_grpc.pb.go @@ -22,6 +22,7 @@ const ( WalletCronService_ProcessHostSalaryDailySettlementBatch_FullMethodName = "/hyapp.wallet.v1.WalletCronService/ProcessHostSalaryDailySettlementBatch" WalletCronService_ProcessHostSalaryHalfMonthSettlementBatch_FullMethodName = "/hyapp.wallet.v1.WalletCronService/ProcessHostSalaryHalfMonthSettlementBatch" WalletCronService_ProcessHostSalaryMonthEndBatch_FullMethodName = "/hyapp.wallet.v1.WalletCronService/ProcessHostSalaryMonthEndBatch" + WalletCronService_ProcessVipDailyCoinRebateBatch_FullMethodName = "/hyapp.wallet.v1.WalletCronService/ProcessVipDailyCoinRebateBatch" ) // WalletCronServiceClient is the client API for WalletCronService service. @@ -33,6 +34,7 @@ type WalletCronServiceClient interface { ProcessHostSalaryDailySettlementBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) ProcessHostSalaryHalfMonthSettlementBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) ProcessHostSalaryMonthEndBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) + ProcessVipDailyCoinRebateBatch(ctx context.Context, in *ProcessVipDailyCoinRebateBatchRequest, opts ...grpc.CallOption) (*ProcessVipDailyCoinRebateBatchResponse, error) } type walletCronServiceClient struct { @@ -73,6 +75,16 @@ func (c *walletCronServiceClient) ProcessHostSalaryMonthEndBatch(ctx context.Con return out, nil } +func (c *walletCronServiceClient) ProcessVipDailyCoinRebateBatch(ctx context.Context, in *ProcessVipDailyCoinRebateBatchRequest, opts ...grpc.CallOption) (*ProcessVipDailyCoinRebateBatchResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ProcessVipDailyCoinRebateBatchResponse) + err := c.cc.Invoke(ctx, WalletCronService_ProcessVipDailyCoinRebateBatch_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // WalletCronServiceServer is the server API for WalletCronService service. // All implementations must embed UnimplementedWalletCronServiceServer // for forward compatibility. @@ -82,6 +94,7 @@ type WalletCronServiceServer interface { ProcessHostSalaryDailySettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) ProcessHostSalaryHalfMonthSettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) ProcessHostSalaryMonthEndBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) + ProcessVipDailyCoinRebateBatch(context.Context, *ProcessVipDailyCoinRebateBatchRequest) (*ProcessVipDailyCoinRebateBatchResponse, error) mustEmbedUnimplementedWalletCronServiceServer() } @@ -101,6 +114,9 @@ func (UnimplementedWalletCronServiceServer) ProcessHostSalaryHalfMonthSettlement func (UnimplementedWalletCronServiceServer) ProcessHostSalaryMonthEndBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ProcessHostSalaryMonthEndBatch not implemented") } +func (UnimplementedWalletCronServiceServer) ProcessVipDailyCoinRebateBatch(context.Context, *ProcessVipDailyCoinRebateBatchRequest) (*ProcessVipDailyCoinRebateBatchResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ProcessVipDailyCoinRebateBatch not implemented") +} func (UnimplementedWalletCronServiceServer) mustEmbedUnimplementedWalletCronServiceServer() {} func (UnimplementedWalletCronServiceServer) testEmbeddedByValue() {} @@ -176,6 +192,24 @@ func _WalletCronService_ProcessHostSalaryMonthEndBatch_Handler(srv interface{}, return interceptor(ctx, in, info, handler) } +func _WalletCronService_ProcessVipDailyCoinRebateBatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ProcessVipDailyCoinRebateBatchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletCronServiceServer).ProcessVipDailyCoinRebateBatch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletCronService_ProcessVipDailyCoinRebateBatch_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletCronServiceServer).ProcessVipDailyCoinRebateBatch(ctx, req.(*ProcessVipDailyCoinRebateBatchRequest)) + } + return interceptor(ctx, in, info, handler) +} + // WalletCronService_ServiceDesc is the grpc.ServiceDesc for WalletCronService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -195,6 +229,10 @@ var WalletCronService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ProcessHostSalaryMonthEndBatch", Handler: _WalletCronService_ProcessHostSalaryMonthEndBatch_Handler, }, + { + MethodName: "ProcessVipDailyCoinRebateBatch", + Handler: _WalletCronService_ProcessVipDailyCoinRebateBatch_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "proto/wallet/v1/wallet.proto", @@ -258,6 +296,7 @@ const ( WalletService_PurchaseResourceShopItem_FullMethodName = "/hyapp.wallet.v1.WalletService/PurchaseResourceShopItem" WalletService_ListRechargeBills_FullMethodName = "/hyapp.wallet.v1.WalletService/ListRechargeBills" WalletService_GetRechargeBillSummary_FullMethodName = "/hyapp.wallet.v1.WalletService/GetRechargeBillSummary" + WalletService_BatchGetUserRechargeStats_FullMethodName = "/hyapp.wallet.v1.WalletService/BatchGetUserRechargeStats" WalletService_GetRechargeBillOverview_FullMethodName = "/hyapp.wallet.v1.WalletService/GetRechargeBillOverview" WalletService_RefreshGooglePaymentPrices_FullMethodName = "/hyapp.wallet.v1.WalletService/RefreshGooglePaymentPrices" WalletService_GetWalletOverview_FullMethodName = "/hyapp.wallet.v1.WalletService/GetWalletOverview" @@ -286,13 +325,23 @@ const ( WalletService_GetDiamondExchangeConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/GetDiamondExchangeConfig" WalletService_ListWalletTransactions_FullMethodName = "/hyapp.wallet.v1.WalletService/ListWalletTransactions" WalletService_ListVipPackages_FullMethodName = "/hyapp.wallet.v1.WalletService/ListVipPackages" + WalletService_GetVipProgramConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/GetVipProgramConfig" WalletService_GetMyVip_FullMethodName = "/hyapp.wallet.v1.WalletService/GetMyVip" + WalletService_CheckVipBenefit_FullMethodName = "/hyapp.wallet.v1.WalletService/CheckVipBenefit" WalletService_PurchaseVip_FullMethodName = "/hyapp.wallet.v1.WalletService/PurchaseVip" WalletService_DebitCPBreakupFee_FullMethodName = "/hyapp.wallet.v1.WalletService/DebitCPBreakupFee" WalletService_DebitWheelDraw_FullMethodName = "/hyapp.wallet.v1.WalletService/DebitWheelDraw" WalletService_GrantVip_FullMethodName = "/hyapp.wallet.v1.WalletService/GrantVip" + WalletService_GrantVipTrialCard_FullMethodName = "/hyapp.wallet.v1.WalletService/GrantVipTrialCard" + WalletService_EquipVipTrialCard_FullMethodName = "/hyapp.wallet.v1.WalletService/EquipVipTrialCard" + WalletService_UnequipVipTrialCard_FullMethodName = "/hyapp.wallet.v1.WalletService/UnequipVipTrialCard" WalletService_ListAdminVipLevels_FullMethodName = "/hyapp.wallet.v1.WalletService/ListAdminVipLevels" WalletService_UpdateAdminVipLevels_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateAdminVipLevels" + WalletService_UpdateAdminVipProgramConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateAdminVipProgramConfig" + WalletService_UpdateMyVipSettings_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateMyVipSettings" + WalletService_GetMyCurrentVipDailyCoinRebate_FullMethodName = "/hyapp.wallet.v1.WalletService/GetMyCurrentVipDailyCoinRebate" + WalletService_ListMyVipDailyCoinRebateStatuses_FullMethodName = "/hyapp.wallet.v1.WalletService/ListMyVipDailyCoinRebateStatuses" + WalletService_ClaimVipDailyCoinRebate_FullMethodName = "/hyapp.wallet.v1.WalletService/ClaimVipDailyCoinRebate" WalletService_CreditTaskReward_FullMethodName = "/hyapp.wallet.v1.WalletService/CreditTaskReward" WalletService_CreditLuckyGiftReward_FullMethodName = "/hyapp.wallet.v1.WalletService/CreditLuckyGiftReward" WalletService_CreditWheelReward_FullMethodName = "/hyapp.wallet.v1.WalletService/CreditWheelReward" @@ -374,6 +423,7 @@ type WalletServiceClient interface { PurchaseResourceShopItem(ctx context.Context, in *PurchaseResourceShopItemRequest, opts ...grpc.CallOption) (*PurchaseResourceShopItemResponse, error) ListRechargeBills(ctx context.Context, in *ListRechargeBillsRequest, opts ...grpc.CallOption) (*ListRechargeBillsResponse, error) GetRechargeBillSummary(ctx context.Context, in *GetRechargeBillSummaryRequest, opts ...grpc.CallOption) (*GetRechargeBillSummaryResponse, error) + BatchGetUserRechargeStats(ctx context.Context, in *BatchGetUserRechargeStatsRequest, opts ...grpc.CallOption) (*BatchGetUserRechargeStatsResponse, error) GetRechargeBillOverview(ctx context.Context, in *GetRechargeBillOverviewRequest, opts ...grpc.CallOption) (*GetRechargeBillOverviewResponse, error) RefreshGooglePaymentPrices(ctx context.Context, in *RefreshGooglePaymentPricesRequest, opts ...grpc.CallOption) (*RefreshGooglePaymentPricesResponse, error) GetWalletOverview(ctx context.Context, in *GetWalletOverviewRequest, opts ...grpc.CallOption) (*GetWalletOverviewResponse, error) @@ -402,13 +452,23 @@ type WalletServiceClient interface { GetDiamondExchangeConfig(ctx context.Context, in *GetDiamondExchangeConfigRequest, opts ...grpc.CallOption) (*GetDiamondExchangeConfigResponse, error) ListWalletTransactions(ctx context.Context, in *ListWalletTransactionsRequest, opts ...grpc.CallOption) (*ListWalletTransactionsResponse, error) ListVipPackages(ctx context.Context, in *ListVipPackagesRequest, opts ...grpc.CallOption) (*ListVipPackagesResponse, error) + GetVipProgramConfig(ctx context.Context, in *GetVipProgramConfigRequest, opts ...grpc.CallOption) (*GetVipProgramConfigResponse, error) GetMyVip(ctx context.Context, in *GetMyVipRequest, opts ...grpc.CallOption) (*GetMyVipResponse, error) + CheckVipBenefit(ctx context.Context, in *CheckVipBenefitRequest, opts ...grpc.CallOption) (*CheckVipBenefitResponse, error) PurchaseVip(ctx context.Context, in *PurchaseVipRequest, opts ...grpc.CallOption) (*PurchaseVipResponse, error) DebitCPBreakupFee(ctx context.Context, in *DebitCPBreakupFeeRequest, opts ...grpc.CallOption) (*DebitCPBreakupFeeResponse, error) DebitWheelDraw(ctx context.Context, in *DebitWheelDrawRequest, opts ...grpc.CallOption) (*DebitWheelDrawResponse, error) GrantVip(ctx context.Context, in *GrantVipRequest, opts ...grpc.CallOption) (*GrantVipResponse, error) + GrantVipTrialCard(ctx context.Context, in *GrantVipTrialCardRequest, opts ...grpc.CallOption) (*GrantVipTrialCardResponse, error) + EquipVipTrialCard(ctx context.Context, in *EquipVipTrialCardRequest, opts ...grpc.CallOption) (*EquipVipTrialCardResponse, error) + UnequipVipTrialCard(ctx context.Context, in *UnequipVipTrialCardRequest, opts ...grpc.CallOption) (*UnequipVipTrialCardResponse, error) ListAdminVipLevels(ctx context.Context, in *ListAdminVipLevelsRequest, opts ...grpc.CallOption) (*ListAdminVipLevelsResponse, error) UpdateAdminVipLevels(ctx context.Context, in *UpdateAdminVipLevelsRequest, opts ...grpc.CallOption) (*UpdateAdminVipLevelsResponse, error) + UpdateAdminVipProgramConfig(ctx context.Context, in *UpdateAdminVipProgramConfigRequest, opts ...grpc.CallOption) (*UpdateAdminVipProgramConfigResponse, error) + UpdateMyVipSettings(ctx context.Context, in *UpdateMyVipSettingsRequest, opts ...grpc.CallOption) (*UpdateMyVipSettingsResponse, error) + GetMyCurrentVipDailyCoinRebate(ctx context.Context, in *GetMyCurrentVipDailyCoinRebateRequest, opts ...grpc.CallOption) (*GetMyCurrentVipDailyCoinRebateResponse, error) + ListMyVipDailyCoinRebateStatuses(ctx context.Context, in *ListMyVipDailyCoinRebateStatusesRequest, opts ...grpc.CallOption) (*ListMyVipDailyCoinRebateStatusesResponse, error) + ClaimVipDailyCoinRebate(ctx context.Context, in *ClaimVipDailyCoinRebateRequest, opts ...grpc.CallOption) (*ClaimVipDailyCoinRebateResponse, error) CreditTaskReward(ctx context.Context, in *CreditTaskRewardRequest, opts ...grpc.CallOption) (*CreditTaskRewardResponse, error) CreditLuckyGiftReward(ctx context.Context, in *CreditLuckyGiftRewardRequest, opts ...grpc.CallOption) (*CreditLuckyGiftRewardResponse, error) CreditWheelReward(ctx context.Context, in *CreditWheelRewardRequest, opts ...grpc.CallOption) (*CreditWheelRewardResponse, error) @@ -1004,6 +1064,16 @@ func (c *walletServiceClient) GetRechargeBillSummary(ctx context.Context, in *Ge return out, nil } +func (c *walletServiceClient) BatchGetUserRechargeStats(ctx context.Context, in *BatchGetUserRechargeStatsRequest, opts ...grpc.CallOption) (*BatchGetUserRechargeStatsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(BatchGetUserRechargeStatsResponse) + err := c.cc.Invoke(ctx, WalletService_BatchGetUserRechargeStats_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *walletServiceClient) GetRechargeBillOverview(ctx context.Context, in *GetRechargeBillOverviewRequest, opts ...grpc.CallOption) (*GetRechargeBillOverviewResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetRechargeBillOverviewResponse) @@ -1284,6 +1354,16 @@ func (c *walletServiceClient) ListVipPackages(ctx context.Context, in *ListVipPa return out, nil } +func (c *walletServiceClient) GetVipProgramConfig(ctx context.Context, in *GetVipProgramConfigRequest, opts ...grpc.CallOption) (*GetVipProgramConfigResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetVipProgramConfigResponse) + err := c.cc.Invoke(ctx, WalletService_GetVipProgramConfig_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *walletServiceClient) GetMyVip(ctx context.Context, in *GetMyVipRequest, opts ...grpc.CallOption) (*GetMyVipResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetMyVipResponse) @@ -1294,6 +1374,16 @@ func (c *walletServiceClient) GetMyVip(ctx context.Context, in *GetMyVipRequest, return out, nil } +func (c *walletServiceClient) CheckVipBenefit(ctx context.Context, in *CheckVipBenefitRequest, opts ...grpc.CallOption) (*CheckVipBenefitResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CheckVipBenefitResponse) + err := c.cc.Invoke(ctx, WalletService_CheckVipBenefit_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *walletServiceClient) PurchaseVip(ctx context.Context, in *PurchaseVipRequest, opts ...grpc.CallOption) (*PurchaseVipResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(PurchaseVipResponse) @@ -1334,6 +1424,36 @@ func (c *walletServiceClient) GrantVip(ctx context.Context, in *GrantVipRequest, return out, nil } +func (c *walletServiceClient) GrantVipTrialCard(ctx context.Context, in *GrantVipTrialCardRequest, opts ...grpc.CallOption) (*GrantVipTrialCardResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GrantVipTrialCardResponse) + err := c.cc.Invoke(ctx, WalletService_GrantVipTrialCard_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *walletServiceClient) EquipVipTrialCard(ctx context.Context, in *EquipVipTrialCardRequest, opts ...grpc.CallOption) (*EquipVipTrialCardResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(EquipVipTrialCardResponse) + err := c.cc.Invoke(ctx, WalletService_EquipVipTrialCard_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *walletServiceClient) UnequipVipTrialCard(ctx context.Context, in *UnequipVipTrialCardRequest, opts ...grpc.CallOption) (*UnequipVipTrialCardResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UnequipVipTrialCardResponse) + err := c.cc.Invoke(ctx, WalletService_UnequipVipTrialCard_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *walletServiceClient) ListAdminVipLevels(ctx context.Context, in *ListAdminVipLevelsRequest, opts ...grpc.CallOption) (*ListAdminVipLevelsResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ListAdminVipLevelsResponse) @@ -1354,6 +1474,56 @@ func (c *walletServiceClient) UpdateAdminVipLevels(ctx context.Context, in *Upda return out, nil } +func (c *walletServiceClient) UpdateAdminVipProgramConfig(ctx context.Context, in *UpdateAdminVipProgramConfigRequest, opts ...grpc.CallOption) (*UpdateAdminVipProgramConfigResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UpdateAdminVipProgramConfigResponse) + err := c.cc.Invoke(ctx, WalletService_UpdateAdminVipProgramConfig_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *walletServiceClient) UpdateMyVipSettings(ctx context.Context, in *UpdateMyVipSettingsRequest, opts ...grpc.CallOption) (*UpdateMyVipSettingsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UpdateMyVipSettingsResponse) + err := c.cc.Invoke(ctx, WalletService_UpdateMyVipSettings_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *walletServiceClient) GetMyCurrentVipDailyCoinRebate(ctx context.Context, in *GetMyCurrentVipDailyCoinRebateRequest, opts ...grpc.CallOption) (*GetMyCurrentVipDailyCoinRebateResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetMyCurrentVipDailyCoinRebateResponse) + err := c.cc.Invoke(ctx, WalletService_GetMyCurrentVipDailyCoinRebate_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *walletServiceClient) ListMyVipDailyCoinRebateStatuses(ctx context.Context, in *ListMyVipDailyCoinRebateStatusesRequest, opts ...grpc.CallOption) (*ListMyVipDailyCoinRebateStatusesResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListMyVipDailyCoinRebateStatusesResponse) + err := c.cc.Invoke(ctx, WalletService_ListMyVipDailyCoinRebateStatuses_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *walletServiceClient) ClaimVipDailyCoinRebate(ctx context.Context, in *ClaimVipDailyCoinRebateRequest, opts ...grpc.CallOption) (*ClaimVipDailyCoinRebateResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ClaimVipDailyCoinRebateResponse) + err := c.cc.Invoke(ctx, WalletService_ClaimVipDailyCoinRebate_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *walletServiceClient) CreditTaskReward(ctx context.Context, in *CreditTaskRewardRequest, opts ...grpc.CallOption) (*CreditTaskRewardResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(CreditTaskRewardResponse) @@ -1568,6 +1738,7 @@ type WalletServiceServer interface { PurchaseResourceShopItem(context.Context, *PurchaseResourceShopItemRequest) (*PurchaseResourceShopItemResponse, error) ListRechargeBills(context.Context, *ListRechargeBillsRequest) (*ListRechargeBillsResponse, error) GetRechargeBillSummary(context.Context, *GetRechargeBillSummaryRequest) (*GetRechargeBillSummaryResponse, error) + BatchGetUserRechargeStats(context.Context, *BatchGetUserRechargeStatsRequest) (*BatchGetUserRechargeStatsResponse, error) GetRechargeBillOverview(context.Context, *GetRechargeBillOverviewRequest) (*GetRechargeBillOverviewResponse, error) RefreshGooglePaymentPrices(context.Context, *RefreshGooglePaymentPricesRequest) (*RefreshGooglePaymentPricesResponse, error) GetWalletOverview(context.Context, *GetWalletOverviewRequest) (*GetWalletOverviewResponse, error) @@ -1596,13 +1767,23 @@ type WalletServiceServer interface { GetDiamondExchangeConfig(context.Context, *GetDiamondExchangeConfigRequest) (*GetDiamondExchangeConfigResponse, error) ListWalletTransactions(context.Context, *ListWalletTransactionsRequest) (*ListWalletTransactionsResponse, error) ListVipPackages(context.Context, *ListVipPackagesRequest) (*ListVipPackagesResponse, error) + GetVipProgramConfig(context.Context, *GetVipProgramConfigRequest) (*GetVipProgramConfigResponse, error) GetMyVip(context.Context, *GetMyVipRequest) (*GetMyVipResponse, error) + CheckVipBenefit(context.Context, *CheckVipBenefitRequest) (*CheckVipBenefitResponse, error) PurchaseVip(context.Context, *PurchaseVipRequest) (*PurchaseVipResponse, error) DebitCPBreakupFee(context.Context, *DebitCPBreakupFeeRequest) (*DebitCPBreakupFeeResponse, error) DebitWheelDraw(context.Context, *DebitWheelDrawRequest) (*DebitWheelDrawResponse, error) GrantVip(context.Context, *GrantVipRequest) (*GrantVipResponse, error) + GrantVipTrialCard(context.Context, *GrantVipTrialCardRequest) (*GrantVipTrialCardResponse, error) + EquipVipTrialCard(context.Context, *EquipVipTrialCardRequest) (*EquipVipTrialCardResponse, error) + UnequipVipTrialCard(context.Context, *UnequipVipTrialCardRequest) (*UnequipVipTrialCardResponse, error) ListAdminVipLevels(context.Context, *ListAdminVipLevelsRequest) (*ListAdminVipLevelsResponse, error) UpdateAdminVipLevels(context.Context, *UpdateAdminVipLevelsRequest) (*UpdateAdminVipLevelsResponse, error) + UpdateAdminVipProgramConfig(context.Context, *UpdateAdminVipProgramConfigRequest) (*UpdateAdminVipProgramConfigResponse, error) + UpdateMyVipSettings(context.Context, *UpdateMyVipSettingsRequest) (*UpdateMyVipSettingsResponse, error) + GetMyCurrentVipDailyCoinRebate(context.Context, *GetMyCurrentVipDailyCoinRebateRequest) (*GetMyCurrentVipDailyCoinRebateResponse, error) + ListMyVipDailyCoinRebateStatuses(context.Context, *ListMyVipDailyCoinRebateStatusesRequest) (*ListMyVipDailyCoinRebateStatusesResponse, error) + ClaimVipDailyCoinRebate(context.Context, *ClaimVipDailyCoinRebateRequest) (*ClaimVipDailyCoinRebateResponse, error) CreditTaskReward(context.Context, *CreditTaskRewardRequest) (*CreditTaskRewardResponse, error) CreditLuckyGiftReward(context.Context, *CreditLuckyGiftRewardRequest) (*CreditLuckyGiftRewardResponse, error) CreditWheelReward(context.Context, *CreditWheelRewardRequest) (*CreditWheelRewardResponse, error) @@ -1799,6 +1980,9 @@ func (UnimplementedWalletServiceServer) ListRechargeBills(context.Context, *List func (UnimplementedWalletServiceServer) GetRechargeBillSummary(context.Context, *GetRechargeBillSummaryRequest) (*GetRechargeBillSummaryResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetRechargeBillSummary not implemented") } +func (UnimplementedWalletServiceServer) BatchGetUserRechargeStats(context.Context, *BatchGetUserRechargeStatsRequest) (*BatchGetUserRechargeStatsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method BatchGetUserRechargeStats not implemented") +} func (UnimplementedWalletServiceServer) GetRechargeBillOverview(context.Context, *GetRechargeBillOverviewRequest) (*GetRechargeBillOverviewResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetRechargeBillOverview not implemented") } @@ -1883,9 +2067,15 @@ func (UnimplementedWalletServiceServer) ListWalletTransactions(context.Context, func (UnimplementedWalletServiceServer) ListVipPackages(context.Context, *ListVipPackagesRequest) (*ListVipPackagesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListVipPackages not implemented") } +func (UnimplementedWalletServiceServer) GetVipProgramConfig(context.Context, *GetVipProgramConfigRequest) (*GetVipProgramConfigResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetVipProgramConfig not implemented") +} func (UnimplementedWalletServiceServer) GetMyVip(context.Context, *GetMyVipRequest) (*GetMyVipResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetMyVip not implemented") } +func (UnimplementedWalletServiceServer) CheckVipBenefit(context.Context, *CheckVipBenefitRequest) (*CheckVipBenefitResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CheckVipBenefit not implemented") +} func (UnimplementedWalletServiceServer) PurchaseVip(context.Context, *PurchaseVipRequest) (*PurchaseVipResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method PurchaseVip not implemented") } @@ -1898,12 +2088,36 @@ func (UnimplementedWalletServiceServer) DebitWheelDraw(context.Context, *DebitWh func (UnimplementedWalletServiceServer) GrantVip(context.Context, *GrantVipRequest) (*GrantVipResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GrantVip not implemented") } +func (UnimplementedWalletServiceServer) GrantVipTrialCard(context.Context, *GrantVipTrialCardRequest) (*GrantVipTrialCardResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GrantVipTrialCard not implemented") +} +func (UnimplementedWalletServiceServer) EquipVipTrialCard(context.Context, *EquipVipTrialCardRequest) (*EquipVipTrialCardResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method EquipVipTrialCard not implemented") +} +func (UnimplementedWalletServiceServer) UnequipVipTrialCard(context.Context, *UnequipVipTrialCardRequest) (*UnequipVipTrialCardResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UnequipVipTrialCard not implemented") +} func (UnimplementedWalletServiceServer) ListAdminVipLevels(context.Context, *ListAdminVipLevelsRequest) (*ListAdminVipLevelsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListAdminVipLevels not implemented") } func (UnimplementedWalletServiceServer) UpdateAdminVipLevels(context.Context, *UpdateAdminVipLevelsRequest) (*UpdateAdminVipLevelsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateAdminVipLevels not implemented") } +func (UnimplementedWalletServiceServer) UpdateAdminVipProgramConfig(context.Context, *UpdateAdminVipProgramConfigRequest) (*UpdateAdminVipProgramConfigResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateAdminVipProgramConfig not implemented") +} +func (UnimplementedWalletServiceServer) UpdateMyVipSettings(context.Context, *UpdateMyVipSettingsRequest) (*UpdateMyVipSettingsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateMyVipSettings not implemented") +} +func (UnimplementedWalletServiceServer) GetMyCurrentVipDailyCoinRebate(context.Context, *GetMyCurrentVipDailyCoinRebateRequest) (*GetMyCurrentVipDailyCoinRebateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetMyCurrentVipDailyCoinRebate not implemented") +} +func (UnimplementedWalletServiceServer) ListMyVipDailyCoinRebateStatuses(context.Context, *ListMyVipDailyCoinRebateStatusesRequest) (*ListMyVipDailyCoinRebateStatusesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListMyVipDailyCoinRebateStatuses not implemented") +} +func (UnimplementedWalletServiceServer) ClaimVipDailyCoinRebate(context.Context, *ClaimVipDailyCoinRebateRequest) (*ClaimVipDailyCoinRebateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClaimVipDailyCoinRebate not implemented") +} func (UnimplementedWalletServiceServer) CreditTaskReward(context.Context, *CreditTaskRewardRequest) (*CreditTaskRewardResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreditTaskReward not implemented") } @@ -2996,6 +3210,24 @@ func _WalletService_GetRechargeBillSummary_Handler(srv interface{}, ctx context. return interceptor(ctx, in, info, handler) } +func _WalletService_BatchGetUserRechargeStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BatchGetUserRechargeStatsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).BatchGetUserRechargeStats(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_BatchGetUserRechargeStats_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).BatchGetUserRechargeStats(ctx, req.(*BatchGetUserRechargeStatsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _WalletService_GetRechargeBillOverview_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetRechargeBillOverviewRequest) if err := dec(in); err != nil { @@ -3500,6 +3732,24 @@ func _WalletService_ListVipPackages_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } +func _WalletService_GetVipProgramConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetVipProgramConfigRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).GetVipProgramConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_GetVipProgramConfig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).GetVipProgramConfig(ctx, req.(*GetVipProgramConfigRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _WalletService_GetMyVip_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetMyVipRequest) if err := dec(in); err != nil { @@ -3518,6 +3768,24 @@ func _WalletService_GetMyVip_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _WalletService_CheckVipBenefit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CheckVipBenefitRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).CheckVipBenefit(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_CheckVipBenefit_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).CheckVipBenefit(ctx, req.(*CheckVipBenefitRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _WalletService_PurchaseVip_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(PurchaseVipRequest) if err := dec(in); err != nil { @@ -3590,6 +3858,60 @@ func _WalletService_GrantVip_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _WalletService_GrantVipTrialCard_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GrantVipTrialCardRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).GrantVipTrialCard(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_GrantVipTrialCard_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).GrantVipTrialCard(ctx, req.(*GrantVipTrialCardRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WalletService_EquipVipTrialCard_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EquipVipTrialCardRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).EquipVipTrialCard(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_EquipVipTrialCard_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).EquipVipTrialCard(ctx, req.(*EquipVipTrialCardRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WalletService_UnequipVipTrialCard_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UnequipVipTrialCardRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).UnequipVipTrialCard(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_UnequipVipTrialCard_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).UnequipVipTrialCard(ctx, req.(*UnequipVipTrialCardRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _WalletService_ListAdminVipLevels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListAdminVipLevelsRequest) if err := dec(in); err != nil { @@ -3626,6 +3948,96 @@ func _WalletService_UpdateAdminVipLevels_Handler(srv interface{}, ctx context.Co return interceptor(ctx, in, info, handler) } +func _WalletService_UpdateAdminVipProgramConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateAdminVipProgramConfigRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).UpdateAdminVipProgramConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_UpdateAdminVipProgramConfig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).UpdateAdminVipProgramConfig(ctx, req.(*UpdateAdminVipProgramConfigRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WalletService_UpdateMyVipSettings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateMyVipSettingsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).UpdateMyVipSettings(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_UpdateMyVipSettings_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).UpdateMyVipSettings(ctx, req.(*UpdateMyVipSettingsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WalletService_GetMyCurrentVipDailyCoinRebate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetMyCurrentVipDailyCoinRebateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).GetMyCurrentVipDailyCoinRebate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_GetMyCurrentVipDailyCoinRebate_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).GetMyCurrentVipDailyCoinRebate(ctx, req.(*GetMyCurrentVipDailyCoinRebateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WalletService_ListMyVipDailyCoinRebateStatuses_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListMyVipDailyCoinRebateStatusesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).ListMyVipDailyCoinRebateStatuses(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_ListMyVipDailyCoinRebateStatuses_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).ListMyVipDailyCoinRebateStatuses(ctx, req.(*ListMyVipDailyCoinRebateStatusesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WalletService_ClaimVipDailyCoinRebate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ClaimVipDailyCoinRebateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).ClaimVipDailyCoinRebate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_ClaimVipDailyCoinRebate_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).ClaimVipDailyCoinRebate(ctx, req.(*ClaimVipDailyCoinRebateRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _WalletService_CreditTaskReward_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreditTaskRewardRequest) if err := dec(in); err != nil { @@ -4131,6 +4543,10 @@ var WalletService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetRechargeBillSummary", Handler: _WalletService_GetRechargeBillSummary_Handler, }, + { + MethodName: "BatchGetUserRechargeStats", + Handler: _WalletService_BatchGetUserRechargeStats_Handler, + }, { MethodName: "GetRechargeBillOverview", Handler: _WalletService_GetRechargeBillOverview_Handler, @@ -4243,10 +4659,18 @@ var WalletService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListVipPackages", Handler: _WalletService_ListVipPackages_Handler, }, + { + MethodName: "GetVipProgramConfig", + Handler: _WalletService_GetVipProgramConfig_Handler, + }, { MethodName: "GetMyVip", Handler: _WalletService_GetMyVip_Handler, }, + { + MethodName: "CheckVipBenefit", + Handler: _WalletService_CheckVipBenefit_Handler, + }, { MethodName: "PurchaseVip", Handler: _WalletService_PurchaseVip_Handler, @@ -4263,6 +4687,18 @@ var WalletService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GrantVip", Handler: _WalletService_GrantVip_Handler, }, + { + MethodName: "GrantVipTrialCard", + Handler: _WalletService_GrantVipTrialCard_Handler, + }, + { + MethodName: "EquipVipTrialCard", + Handler: _WalletService_EquipVipTrialCard_Handler, + }, + { + MethodName: "UnequipVipTrialCard", + Handler: _WalletService_UnequipVipTrialCard_Handler, + }, { MethodName: "ListAdminVipLevels", Handler: _WalletService_ListAdminVipLevels_Handler, @@ -4271,6 +4707,26 @@ var WalletService_ServiceDesc = grpc.ServiceDesc{ MethodName: "UpdateAdminVipLevels", Handler: _WalletService_UpdateAdminVipLevels_Handler, }, + { + MethodName: "UpdateAdminVipProgramConfig", + Handler: _WalletService_UpdateAdminVipProgramConfig_Handler, + }, + { + MethodName: "UpdateMyVipSettings", + Handler: _WalletService_UpdateMyVipSettings_Handler, + }, + { + MethodName: "GetMyCurrentVipDailyCoinRebate", + Handler: _WalletService_GetMyCurrentVipDailyCoinRebate_Handler, + }, + { + MethodName: "ListMyVipDailyCoinRebateStatuses", + Handler: _WalletService_ListMyVipDailyCoinRebateStatuses_Handler, + }, + { + MethodName: "ClaimVipDailyCoinRebate", + Handler: _WalletService_ClaimVipDailyCoinRebate_Handler, + }, { MethodName: "CreditTaskReward", Handler: _WalletService_CreditTaskReward_Handler, diff --git a/docs/App消息Tab架构.md b/docs/App消息Tab架构.md index 0eda01af..45773602 100644 --- a/docs/App消息Tab架构.md +++ b/docs/App消息Tab架构.md @@ -516,7 +516,7 @@ tasks: timeout: 10s lock_ttl: 30s batch_size: 500 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] ``` 如果消息 owner 后续拆成独立 `message-service`,这些配置迁移到新服务;gateway 只需要更新 message gRPC 地址。 diff --git a/docs/Fami_VIP_Flutter对接方案.md b/docs/Fami_VIP_Flutter对接方案.md new file mode 100644 index 00000000..47492970 --- /dev/null +++ b/docs/Fami_VIP_Flutter对接方案.md @@ -0,0 +1,1109 @@ +# Fami VIP Flutter 对接方案 + +本文只定义 Flutter 与已落地后端的对接契约,不要在客户端重复实现 VIP 状态机。界面和文案统一使用“VIP”,不再使用“SVIP”。 + +## 1. 通用约定 + +- 地址前缀:`/api/v1`,实际 host 按环境配置。 +- 所有接口需携带 `Authorization: Bearer `。`app_code` 和 `user_id` 从登录态解析,Flutter 不在 body 中传。 +- 所有成功响应使用统一外壳: + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_xxx", + "data": {} +} +``` + +- `request_id` 由后端生成,只用于追踪,不是幂等键。购买幂等键是 `command_id`。 +- 所有 `*_at_ms` / `duration_ms` 都是 Unix epoch milliseconds。业务切日使用 UTC,Flutter 只在展示层转本地时间。 +- 客户端展示当前身份只读 `state.effective_vip`,权益资格只读 `state.effective_benefits`。不要根据等级、`unlock_level` 或 App 名自行继承权益;进房/上线通知还要结合 `state.user_settings`。 + +## 2. VIP 套餐 + +### 接口地址 + +`GET /api/v1/vip/packages` + +### 参数 + +无 query/body 参数。 + +### 返回值 + +以下 JSON 仅保留对接所需的代表字段;后端会按本节字段表返回完整对象。 + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_01", + "data": { + "current_vip": { + "level": 3, + "name": "VIP3", + "active": true, + "started_at_ms": 1780000000000, + "expires_at_ms": 1782592000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 + }, + "packages": [ + { + "level": 4, + "name": "VIP4", + "status": "active", + "price_coin": 4000, + "duration_ms": 2592000000, + "reward_resource_group_id": 0, + "reward_items": [], + "can_purchase": true, + "sort_order": 40, + "recharge_gate_required": false, + "required_recharge_coin_amount": 0, + "user_recharge_coin_amount": 0, + "purchase_locked_reason": "", + "benefits": [ + { + "benefit_code": "custom_room_background", + "name": "自定义房间背景", + "benefit_type": "function", + "unlock_level": 3, + "status": "active", + "trial_enabled": true, + "resource_id": 0, + "resource_type": "", + "execution_scope": "room", + "auto_equip": false, + "sort_order": 110, + "metadata_json": "", + "created_at_ms": 0, + "updated_at_ms": 0 + } + ], + "config_version": 7 + } + ], + "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": { + "paid_vip": { + "level": 3, + "name": "VIP3", + "active": true, + "expires_at_ms": 1782592000000 + }, + "equipped_trial_card": null, + "effective_vip": { + "level": 3, + "name": "VIP3", + "active": true, + "expires_at_ms": 1782592000000 + }, + "effective_source": "paid", + "effective_benefits": [ + { + "benefit_code": "custom_room_background", + "status": "active" + } + ], + "evaluated_at_ms": 1780000000000, + "program_config": { + "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, + "updated_at_ms": 0 + } + } + } +} +``` + +`packages` 只返回后台已启用的等级。Flutter 必须动态渲染,不得硬编码 9 个套餐。Fami 初始 VIP1–VIP9 均为 `disabled`,运营配置价格并启用前,`packages` 为空是正常结果。 + +### 相关 IM + +无。 + +### 场景处理 + +- 购买按钮以 `can_purchase` 为准;`false` 时可用 `purchase_locked_reason` 决定禁用态。 +- `benefits` 已是该等级的完整集合。`unlock_level` 仅是配置来源信息,不参与 Flutter 权益计算。 +- `current_vip` 是兼容字段,新代码优先使用 `state.effective_vip`。 + +## 3. 当前 VIP 状态 + +### 接口地址 + +`GET /api/v1/vip/me` + +### 参数 + +无 query/body 参数。 + +### 返回值 + +以下为结构示例,`state` 和 `program_config` 实际返回完整字段。 + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_02", + "data": { + "level": 8, + "name": "VIP8", + "active": true, + "started_at_ms": 1780100000000, + "expires_at_ms": 1782692000000, + "program_type": "tiered_privilege_v1", + "config_version": 7, + "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": { + "paid_vip": { + "level": 3, + "name": "VIP3", + "active": true, + "started_at_ms": 1780000000000, + "expires_at_ms": 1782592000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 + }, + "equipped_trial_card": { + "trial_card_id": "vip_trial_card_xxx", + "entitlement_id": "ent_xxx", + "resource_id": 108, + "user_id": 10001, + "level": 8, + "name": "VIP8", + "status": "active", + "equipped": true, + "duration_ms": 2592000000, + "effective_at_ms": 1780100000000, + "expires_at_ms": 1782692000000, + "remaining_duration_ms": 2591000000, + "grant_source": "admin_grant", + "source_grant_id": "grant_xxx", + "created_at_ms": 1780100000000, + "updated_at_ms": 1780100000000 + }, + "effective_vip": { + "level": 8, + "name": "VIP8", + "active": true, + "started_at_ms": 1780100000000, + "expires_at_ms": 1782692000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 + }, + "effective_source": "trial", + "effective_benefits": [ + { + "benefit_code": "room_entry_notice", + "name": "进房高亮通知", + "benefit_type": "function", + "unlock_level": 8, + "status": "active", + "trial_enabled": true, + "resource_id": 0, + "resource_type": "", + "execution_scope": "room", + "auto_equip": false, + "sort_order": 290, + "metadata_json": "" + } + ], + "evaluated_at_ms": 1780101000000, + "program_config": { + "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, + "updated_at_ms": 0 + } + } + } +} +``` + +`data.level/name/active/...` 是兼容旧版的最终生效 VIP 扁平投影,新 Flutter 代码应读 `data.state`。 + +### 相关 IM + +本接口自身不发 IM。收到购买/发放的 `vip_notice` 后,应调用本接口刷新最终状态。 + +### 场景处理 + +- `effective_source` 取值为 `paid` / `trial` / `none`。 +- `paid_vip` 是付费会员事实;`equipped_trial_card` 是当前佩戴卡;`effective_vip` 是页面和房间展示的唯一真值。 +- 后台关闭 `trial_card_enabled` 时,`equipped_trial_card` 原始背包事实仍返回,但 `effective_source` 会立即回落为 `paid`;Flutter 不得继续沿用旧体验卡权限缓存。 +- 当体验卡被佩戴时,不限制卡等级高低,它会覆盖付费 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 时也保留,但不会单独授权。 + +## 4. 购买、续期和升级 + +### 接口地址 + +`POST /api/v1/vip/purchase` + +### 参数 + +```json +{ + "command_id": "vip_purchase_10001_4_1780100000000", + "level": 4 +} +``` + +| 字段 | 说明 | +|---|---| +| `command_id` | 必填,同一次购买的网络重试必须复用同一值;新的购买动作必须生成新值。 | +| `level` | 必填,目标 VIP 等级,必须来自 `packages`。 | + +### 返回值 + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_03", + "data": { + "order_id": "vip_order_xxx", + "transaction_id": "tx_xxx", + "vip": { + "level": 4, + "name": "VIP4", + "active": true, + "started_at_ms": 1780100000000, + "expires_at_ms": 1782692000000, + "program_type": "tiered_privilege_v1", + "config_version": 7 + }, + "coin_spent": 4000, + "coin_balance_after": 6000, + "reward_items": [], + "program_config": { + "app_code": "fami", + "program_type": "tiered_privilege_v1", + "upgrade_expiry_policy": "replace_from_now", + "config_version": 7 + }, + "state": { + "effective_source": "paid", + "paid_vip": { + "level": 4, + "name": "VIP4", + "active": true, + "expires_at_ms": 1782692000000 + }, + "equipped_trial_card": null, + "effective_vip": { + "level": 4, + "name": "VIP4", + "active": true, + "expires_at_ms": 1782692000000 + }, + "effective_benefits": [ + { + "benefit_code": "custom_room_background", + "status": "active" + } + ], + "evaluated_at_ms": 1780100000000, + "program_config": { + "app_code": "fami", + "program_type": "tiered_privilege_v1", + "config_version": 7 + } + } + } +} +``` + +### 相关 IM + +购买或后台直接激活成功后,notice-service 向该用户发送 C2C `TIMCustomElem`: + +```json +{ + "Ext": "vip_notice", + "Desc": "VipActivated", + "Data": "{\"event_type\":\"VipActivated\",\"event_id\":\"evt_xxx\",\"app_code\":\"fami\",\"transaction_id\":\"tx_xxx\",\"command_id\":\"vip_purchase_10001_4_1780100000000\",\"user_id\":\"10001\",\"asset_type\":\"VIP\",\"available_delta\":0,\"frozen_delta\":0,\"source\":\"vip_purchase\",\"action\":\"upgrade\",\"previous_level\":3,\"previous_expires_at_ms\":1781396000000,\"level\":4,\"vip_name\":\"VIP4\",\"started_at_ms\":1780100000000,\"expires_at_ms\":1782692000000,\"program_type\":\"tiered_privilege_v1\",\"config_version\":7,\"expiry_policy\":\"replace_from_now\",\"reward_resource_group_id\":0,\"resource_grant_id\":\"\",\"reward_items\":[],\"created_at_ms\":1780100000000,\"source_created_at_ms\":1780100000000}" +} +``` + +Flutter 收到后用 `event_id` 做会话内去重,再调 `GET /vip/me`。不要用 IM payload 自行拼出最终权益。 + +### 场景处理 + +- Fami 无有效会员时:新截止时间 = 购买时间 + `duration_ms`。 +- Fami 同级续期:新截止时间 = 旧 `expires_at_ms` + `duration_ms`,保留剩余时间。 +- Fami 高级升级:新截止时间 = 购买时间 + `duration_ms`,旧低等级剩余时间丢弃。例如 VIP3 剩 15 天购买 VIP4 30 天,结果是 VIP4 30 天。 +- 购买更低等级由后端拒绝,错误 `VIP_DOWNGRADE_NOT_ALLOWED`。 +- 余额不足返回 `INSUFFICIENT_BALANCE`;等级未启用返回 `VIP_LEVEL_DISABLED`。 +- 如果购买时仍佩戴体验卡,购买结果会写入 `paid_vip`,但当前展示仍可能是 `effective_source="trial"`。购买成功页也必须以返回的 `state.effective_vip` 为准。 + +## 5. 体验卡背包列表 + +### 接口地址 + +`GET /api/v1/users/me/resources?resource_type=vip_trial_card` + +### 参数 + +| 参数 | 位置 | 值 | +|---|---|---| +| `resource_type` | query | 固定 `vip_trial_card` | + +### 返回值 + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_04", + "data": { + "items": [ + { + "entitlement_id": "ent_card_a", + "resource_id": 101, + "resource": { + "resource_id": 101, + "resource_code": "vip_trial_card_3", + "resource_type": "vip_trial_card", + "name": "VIP3体验卡", + "status": "active", + "grantable": true, + "grant_strategy": "new_entitlement", + "usage_scopes": [], + "asset_url": "", + "preview_url": "", + "animation_url": "", + "metadata_json": "{\"vip_level\":3}", + "sort_order": 30 + }, + "status": "active", + "quantity": 1, + "remaining_quantity": 1, + "effective_at_ms": 1780100000000, + "expires_at_ms": 1781309600000, + "source_grant_id": "grant_a", + "created_at_ms": 1780100000000, + "updated_at_ms": 1780100000000, + "equipped": false + } + ], + "total": 1 + } +} +``` + +`metadata_json` 是 JSON 字符串,如需读取 `vip_level` 必须再解析一次;但当前生效等级仍以 `/vip/me` 为准。 + +### 相关 IM + +无。后台发卡目前不会自动佩戴,也没有已定义的体验卡 C2C 消息。 + +### 场景处理 + +- 体验卡从发放时的 `effective_at_ms` 开始绝对计时,不是首次佩戴时才开始。 +- 切换、卸下都不修改任何卡的 `expires_at_ms`,也不删除旧卡。 +- 列表仅返回当前有效的背包实例。卡过期后会自然从 active 列表消失。 +- 预置卡素材初始为空,Flutter 需提供无图兜底,不得拼接本地固定素材 URL。 + +## 6. 佩戴体验卡 + +### 接口地址 + +`POST /api/v1/vip/trial-cards/{entitlement_id}/equip` + +### 参数 + +- path `entitlement_id`:必须使用背包列表的实例 ID,不能使用 `resource_id`。 +- 无 body。 + +### 返回值 + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_05", + "data": { + "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 + }, + "program_config": { + "app_code": "fami", + "program_type": "tiered_privilege_v1", + "trial_card_enabled": true + }, + "state": { + "effective_source": "trial", + "effective_vip": { + "level": 4, + "name": "VIP4", + "active": true, + "expires_at_ms": 1781928000000 + }, + "effective_benefits": [] + }, + "server_time_ms": 1780228000000 + } +} +``` + +### 相关 IM + +无。 + +### 场景处理 + +- 任意等级可自由切换,不比较新旧卡高低。 +- 切换 A 到 B 后,B 成为 `equipped=true`,A 仍在背包中,A/B 的绝对截止时间均不变。 +- 必须直接用返回的 `state` 更新全局 VIP,不要等待 IM。 +- 倒计时使用 `expires_at_ms - server_time_ms`,不要在每次切换时重置为 `duration_ms`。 +- Flutter 的 VIP 流程固定调用本接口,不调用通用 `/users/me/resources/{resource_id}/equip`。后端虽兼容通用背包装备并会内部转交同一 VIP 状态机,但通用响应没有完整 `state`;历史通用背包组件若触发成功,必须立即补拉 `GET /vip/me`。 + +## 7. 卸下体验卡 + +### 接口地址 + +`DELETE /api/v1/vip/trial-cards/equipped` + +### 参数 + +无 path/query/body 参数。 + +### 返回值 + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_06", + "data": { + "unequipped": true, + "program_config": { + "app_code": "fami", + "program_type": "tiered_privilege_v1" + }, + "state": { + "effective_source": "paid", + "paid_vip": { + "level": 3, + "name": "VIP3", + "active": true + }, + "equipped_trial_card": null, + "effective_vip": { + "level": 3, + "name": "VIP3", + "active": true + }, + "effective_benefits": [] + }, + "server_time_ms": 1780229000000 + } +} +``` + +### 相关 IM + +无。 + +### 场景处理 + +- Flutter 的 VIP 流程固定调用本接口,不调用通用 `/users/me/resources/vip_trial_card/unequip`。后端对历史通用背包调用同样会转交专用状态机,但通用响应不包含回落后的完整 `state`。 + +- `unequipped=true` 表示本次确实解除了佩戴;重复调用可返回 `false`,仍按成功处理。 +- 卸下只删除佩戴关系,不删卡、不暂停卡、不修改卡的截止时间。 +- 卸下后优先回落到有效 `paid_vip`;没有付费 VIP 则 `effective_source="none"`。 + +## 8. 经理中心发放 VIP + +经理中心页面如果复用 Flutter,仍调用原地址,不需要按 Fami/Lalu 写分支。gateway 会读取当前 App 的 `program_config.grant_mode`:Lalu 调直接会员发放,Fami 调体验卡专用发放。 + +### 接口地址 + +`POST /api/v1/manager-center/vip-grants` + +### 参数 + +```json +{ + "command_id": "mgr_vip_10001_1780300000000", + "target_user_id": "10001", + "level": 5, + "reason": "manager_center" +} +``` + +- `command_id` 必填且最长 128 字节;重试必须复用同一个值和同一业务参数。 +- 经理中心现有权限仍只允许 VIP1–VIP5,目标用户国家与经理权限校验保持不变。 + +### 返回值 + +Lalu(`direct_membership`)直接激活会员: + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_08a", + "data": { + "grant_mode": "direct_membership", + "transaction_id": "tx_xxx", + "level": 5, + "active": true, + "expires_at_ms": 1782892000000, + "server_time_ms": 1780300000000 + } +} +``` + +Fami(`trial_card`)发一张 30 天体验卡到背包,不自动佩戴: + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_08b", + "data": { + "grant_mode": "trial_card", + "transaction_id": "", + "trial_card_id": "vip_card_xxx", + "entitlement_id": "ent_xxx", + "source_grant_id": "grant_xxx", + "level": 5, + "active": false, + "card_status": "active", + "equipped": false, + "expires_at_ms": 1782892000000, + "server_time_ms": 1780300000000 + } +} +``` + +### 相关 IM + +无。Fami 发卡成功后,被发放用户下次进入背包或收到后续资源刷新信号时重新拉取资源列表;当前接口不会替用户佩戴。 + +### 场景处理 + +- 只根据响应 `grant_mode` 展示“VIP 已生效”或“体验卡已发到背包”,不能仅按 `level` 判断。 +- `trial_card` 返回的 `active=false` 表示没有直接激活会员;卡片本身状态看 `card_status`。 +- 配置恰好在 gateway 查询后被后台切换时,wallet 会拒绝旧模式写入;Flutter 展示接口错误并允许使用同一 `command_id` 重试。 + +## 9. 进房通知 IM + +### 接口地址 + +进房仍使用现有 `POST /api/v1/rooms/join`。VIP 展示不新增 Flutter HTTP 请求。 + +### 参数 + +沿用现有进房参数: + +```json +{ + "room_id": "room_1001", + "command_id": "join_10001_room_1001_1780300000000", + "role": "audience", + "password": "", + "response_mode": "full" +} +``` + +### 返回值 + +`response_mode=full` 和 `response_mode=lite` 均会在进房成功响应的 `data` 中返回当前用户的进房 VIP 快照: + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_join_xxx", + "data": { + "result": { + "applied": true, + "room_version": 18, + "server_time_ms": 1780300000000 + }, + "room": {}, + "viewer": {}, + "seats": [], + "profiles": [], + "im": { + "group_id": "room_1001", + "need_join_group": true + }, + "rtc": {}, + "effective_vip": { + "program_type": "tiered_privilege_v1", + "level": 8, + "name": "VIP8", + "room_entry_notice_enabled": true + }, + "server_time_ms": 1780300000000 + } +} +``` + +`effective_vip` 是当前进房用户在本次 Join 时的轻量快照,可用于本人首屏。完整会员状态和权益集仍以 `/vip/me.state` 为准。 + +### 相关 IM + +进房成功后只向**当前房间的腾讯 IM 群**发送 `TIMCustomElem`,不发全服群: + +```json +{ + "Ext": "room_system_message", + "Desc": "room_user_joined", + "Data": "{\"event_id\":\"evt_join_xxx\",\"room_id\":\"room_1001\",\"event_type\":\"room_user_joined\",\"actor_user_id\":10001,\"target_user_id\":10001,\"room_version\":18,\"role\":\"audience\",\"nickname\":\"Nina\",\"avatar\":\"https://cdn.example/avatar.png\",\"display_user_id\":\"100042\",\"pretty_display_user_id\":\"888042\",\"vip_program_type\":\"tiered_privilege_v1\",\"effective_vip_level\":\"8\",\"effective_vip_name\":\"VIP8\",\"room_entry_notice_enabled\":\"true\",\"attributes\":{\"role\":\"audience\",\"nickname\":\"Nina\",\"avatar\":\"https://cdn.example/avatar.png\",\"display_user_id\":\"100042\",\"pretty_display_user_id\":\"888042\",\"vip_program_type\":\"tiered_privilege_v1\",\"effective_vip_level\":\"8\",\"effective_vip_name\":\"VIP8\",\"room_entry_notice_enabled\":\"true\"}}" +} +``` + +`effective_vip_level` 和 `room_entry_notice_enabled` 在 Data 中是字符串,Flutter 需做兼容解析。 + +### 场景处理 + +- 当前用户进房成功后,可直接用 HTTP `data.effective_vip` 初始化本人进房效果;其他成员的进房展示仍以房间 IM 为准。 +- 仅当 `event_type == "room_user_joined"` 且 `room_entry_notice_enabled == "true"` 时显示 VIP 进房高亮效果。 +- 消息所在 IM GroupID 就是当前 `room_id`;不要转发到 App 全局播报群。 +- 用 `event_id` 去重。重连/重复 Join 仍可收到进房展示事件,不要以本地 presence 猜测是否展示。 +- 进房 VIP 查询失败时后端会降级为普通进房,不阻断进房主链路。 + +## 10. VIP 通知开关 + +### 接口地址 + +- `GET /api/v1/vip/settings` +- `PATCH /api/v1/vip/settings` + +`GET /api/v1/vip/me` 的 `data.state.user_settings` 与 GET 接口是同一份事实。VIP 页面已经拉取 `/vip/me` 时,不必再为展示开关多发一次请求。 + +### 参数 + +GET 无参数。PATCH 是局部更新,两个字段至少传一个;显式 `false` 不能被当成未传: + +```json +{ + "room_entry_notice_enabled": false +} +``` + +```json +{ + "online_global_notice_enabled": true +} +``` + +Flutter 不传 `app_code` 和 `user_id`,后端只从登录态解析。空对象 `{}` 返回 `INVALID_ARGUMENT`。 + +### 返回值 + +GET: + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_settings_get", + "data": { + "settings": { + "app_code": "fami", + "user_id": 10001, + "room_entry_notice_enabled": true, + "online_global_notice_enabled": false, + "updated_at_ms": 1780300000000 + }, + "evaluated_at_ms": 1780300001000 + } +} +``` + +PATCH: + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_settings_patch", + "data": { + "settings": { + "app_code": "fami", + "user_id": 10001, + "room_entry_notice_enabled": false, + "online_global_notice_enabled": false, + "updated_at_ms": 1780300010000 + }, + "server_time_ms": 1780300010000 + } +} +``` + +用户从未修改过时,两项默认为 `true`,`updated_at_ms=0`。PATCH 只改本次提交的字段,不会覆盖另一项。 + +### 相关 IM + +修改开关本身不发 IM。进房开关会在下一次 Join 时影响当前房间 `room_user_joined`;上线开关会在触发 `/vip/online-notice` 时由服务端再校验。 + +### 场景处理 + +- 开关是用户偏好,不是权益;无 VIP 时也可保存,但不会产生进房或上线播报。 +- 进房展示必须同时满足 `effective_benefits` 含 `room_entry_notice` 且 `room_entry_notice_enabled=true`。 +- 上线展示必须同时满足 `online_global_notice` 权益和开关;最终以触发接口的服务端判定为准。 +- 设置按 App 隔离,Fami 的修改不影响 Lalu。 + +## 11. 每日 VIP 金币返现 + +### 接口地址 + +- `GET /api/v1/vip/coin-rebates/current`:查当前 UTC 日资格。 +- `POST /api/v1/vip/coin-rebates/statuses`:批量恢复系统消息中的真实状态,或分页查历史。 +- `POST /api/v1/vip/coin-rebates/{rebate_id}/claim`:手动领取。 +- `GET /api/v1/messages?section=system&page_size=20&page_token=`:查“VIP金币返现”系统消息。 + +### 参数 + +current 无 query/body。statuses 有两种用法: + +```json +{ + "rebate_ids": ["vip_rebate_xxx", "vip_rebate_yyy"], + "page": 1, + "page_size": 20 +} +``` + +`rebate_ids` 最多 100 个,后端只返回当前登录用户拥有的记录。传空数组或不传时使用 `page/page_size` 查历史,`page_size` 最大 100。 + +claim: + +```json +{ + "command_id": "vip_rebate_claim_10001_20260710" +} +``` + +`rebate_id` 只来自 current/statuses/系统消息。Flutter 不传金额、VIP 等级、`app_code` 或 `user_id`。 + +### 返回值 + +current 已生成资格: + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_rebate_current", + "data": { + "found": true, + "rebate": { + "rebate_id": "vip_rebate_xxx", + "user_id": "10001", + "task_day": "2026-07-10", + "vip_level": 6, + "vip_name": "VIP6", + "coin_amount": 100, + "status": "claimable", + "available_at_ms": 1783641600000, + "expires_at_ms": 1783728000000, + "config_version": 8, + "claimed_at_ms": 0, + "wallet_transaction_id": "", + "created_at_ms": 1783641605000, + "updated_at_ms": 1783641605000 + }, + "server_time_ms": 1783641610000 + } +} +``` + +无资格或 cron 尚未生成时也是成功响应: + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_rebate_none", + "data": { + "found": false, + "rebate": null, + "server_time_ms": 1783641610000 + } +} +``` + +statuses: + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_rebate_statuses", + "data": { + "rebates": [ + { + "rebate_id": "vip_rebate_xxx", + "user_id": "10001", + "task_day": "2026-07-10", + "vip_level": 6, + "vip_name": "VIP6", + "coin_amount": 100, + "status": "claimable", + "available_at_ms": 1783641600000, + "expires_at_ms": 1783728000000, + "config_version": 8, + "claimed_at_ms": 0, + "wallet_transaction_id": "", + "created_at_ms": 1783641605000, + "updated_at_ms": 1783641605000 + } + ], + "total": 1, + "server_time_ms": 1783641610000 + } +} +``` + +claim: + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_rebate_claim", + "data": { + "rebate": { + "rebate_id": "vip_rebate_xxx", + "user_id": "10001", + "task_day": "2026-07-10", + "vip_level": 6, + "vip_name": "VIP6", + "coin_amount": 100, + "status": "claimed", + "available_at_ms": 1783641600000, + "expires_at_ms": 1783728000000, + "config_version": 8, + "claimed_at_ms": 1783641700000, + "wallet_transaction_id": "wallet_tx_xxx", + "created_at_ms": 1783641605000, + "updated_at_ms": 1783641700000 + }, + "transaction_id": "wallet_tx_xxx", + "coin_balance": { + "asset_type": "COIN", + "available_amount": 20100, + "frozen_amount": 0, + "version": 18 + }, + "server_time_ms": 1783641700000 + } +} +``` + +`status` 只处理 `claimable` / `claimed` / `expired`。`expired` 是 wallet 根据当前 UTC 时间的投影,不要仅凭手机时钟自行改状态。 + +### 相关 IM + +返现可领取通知进入后端 system inbox,不新增腾讯云 `TIMCustomElem`。`GET /messages?section=system` 的条目示例: + +```json +{ + "message_id": "msg_vip_rebate_xxx", + "title": "VIP金币返现", + "summary": "尊敬的VIP用户,平台今日返现100金币,请及时领取。", + "body": "尊敬的VIP用户,平台今日返现100金币,请及时领取。", + "icon_url": "", + "image_url": "", + "action_type": "vip_coin_rebate_claim", + "action_param": "{\"coin_amount\":100,\"expires_at_ms\":1783728000000,\"rebate_id\":\"vip_rebate_xxx\",\"task_day\":\"2026-07-10\"}", + "read": false, + "sent_at_ms": 1783641600000 +} +``` + +Flutter 先把 `action_param` 再解析为 JSON。点击前可将页面上所有 `rebate_id` 合并调 statuses,用后端状态刷新“去领取/已领取/已过期”。 + +### 场景处理 + +- 资格按 UTC 0 点时的有效付费 VIP 还原;0 点后才购买或升级的状态从次日参与,体验卡不参与。 +- 领取窗口是 `[UTC 当日0点,UTC 次日0点)`。到次日0点后服务端返回 `VIP_COIN_REBATE_EXPIRED`,不再入账。 +- 金额取当日首个成功 cron run 固化的后台配置;同一 run 不会因运营中途改价而分裂。 +- 领取按钮要防连点,网络重试复用同一 `command_id`。同一返现换新 `command_id` 重复提交也只返回原成功回执,不会重复加币。 +- 领取成功后用 `data.coin_balance` 替换 COIN 余额快照,不在 Flutter 本地做 `balance += coin_amount`。 +- 记录不存在或不属于当前用户时返回 `VIP_COIN_REBATE_NOT_FOUND`;复用一个 `command_id` 改投另一笔返现时返回 `IDEMPOTENCY_CONFLICT`。 + +## 12. 上线全服通知 + +### 接口地址 + +`POST /api/v1/vip/online-notice` + +调用前先完成 `GET /api/v1/im/usersig` 的 IM 登录,并按 `join_groups` 加入 `type=global_broadcast` 的全局播报群。Flutter 只请求后端发送,不向全局群自行发消息。 + +### 参数 + +```json +{ + "command_id": "vip_online_550e8400-e29b-41d4-a716-446655440000_2026-07-10" +} +``` + +`command_id` 最长 128,用“进程启动唯一 ID + UTC 日期”生成。同一进程当日网络重试必须复用同一值。 + +### 返回值 + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req_online_notice", + "data": { + "event_id": "vip_online_notice:10001:sha256_digest", + "group_id": "hy_fami_bc_g_v2", + "status": "pending", + "created": true, + "evaluated_at_ms": 1783641610000 + } +} +``` + +`status=pending` 表示已持久化到 activity 播报 outbox,腾讯云 IM 由 worker 异步投递。相同 `command_id` 重试返回同一 `event_id`,`created=false` 是幂等命中,不是失败。 + +### 相关 IM + +全局播报群下发 `TIMCustomElem`: + +| 字段 | 值 | +|---|---| +| `Ext` | `im_broadcast` | +| `Desc` | `vip_online_notice` | +| `Data` | 下方 JSON 字符串 | +| `CloudCustomData` | 与 `Data` 相同的 JSON 字符串 | + +```json +{ + "event_id": "vip_online_notice:10001:sha256_digest", + "broadcast_type": "vip_online_notice", + "scope": "global", + "app_code": "fami", + "user_id": 10001, + "sender_user_id": 10001, + "nickname": "Nina", + "avatar": "https://cdn.example/avatar.png", + "avatar_frame_url": "https://cdn.example/frame.png", + "avatar_frame_resource_id": 108, + "avatar_frame_code": "frame_vip9", + "avatar_frame_asset_url": "https://cdn.example/frame.png", + "avatar_frame_preview_url": "https://cdn.example/frame-preview.png", + "avatar_frame_animation_url": "https://cdn.example/frame-animation.svga", + "display_user_id": "888042", + "raw_display_user_id": "100042", + "pretty_display_user_id": "888042", + "vip_program_type": "tiered_privilege_v1", + "vip_level": 9, + "vip_name": "VIP9", + "message": "欢迎进入Fami,祝你有美好的一天", + "action": { + "type": "none" + }, + "sent_at_ms": 1783641610500 +} +``` + +`display_user_id` 优先美号,无美号时回落 `raw_display_user_id`。`avatar_frame_url` 是兼容字段,固定等于 `avatar_frame_asset_url`;无当前佩戴头像框时 ID 为 `0`、URL/code 为空字符串。用户资料、VIP 等级和头像框都由服务端取当前事实,Flutter 不能用请求伪造。用 `event_id` 做会话内去重。 + +### 场景处理 + +- 在进程内保存 `process_boot_id`、当前 UTC 日和该日 `command_id`,不写 SharedPreferences/数据库/磁盘文件。 +- 同进程同 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`。 +- 不把“每日一次”放到服务端持久化去重,否则无法满足杀进程后同日可再展示。 + +## 13. 权益场景和完成边界 + +| 场景 | Flutter 处理 | 当前后端状态 | +|---|---|---| +| App 维度 VIP 体系 | 始终渲染 `program_config` 和接口返回的动态等级,不按 Fami/Lalu 写死业务分支 | 已强制。Fami 为 `tiered_privilege_v1`,Lalu 为 `legacy_timed` | +| Fami 高级升级 | 直接展示购买响应的新截止时间 | 已强制,旧低级剩余时间丢弃 | +| 同级续期 | 不在本地计算,以响应为准 | 已强制,从旧截止时间累加 | +| 体验卡自由切换 | 按 `entitlement_id` 佩戴,每次直接替换全局 `state` | 已强制,不限等级,不作废旧卡,不改绝对截止时间 | +| 体验卡权益 | 只渲染 `effective_benefits` 资格 | 已强制过滤 `trial_enabled=false`,金币返现不给体验卡 | +| VIP 通知开关 | 读 `state.user_settings`,用 PATCH 局部修改 | 已按 App 持久化,无记录默认两项开启,开关不单独授权 | +| 进房高亮通知 | 本人首屏读 Join HTTP `effective_vip`,其他成员消费当前房间 `room_user_joined` | 后端已同时校验权益与用户开关,并透传 Join HTTP 和当前房间 IM;不发全服 | +| 防踢 | 房管操作返回 `PERMISSION_DENIED` 时显示不可踢,不做本地预判 | 已在 room-service 强制;只阻止普通房主/管理员的 KickUser | +| 防禁言 | 房管操作返回 `PERMISSION_DENIED` 时显示不可禁言,解禁始终可发起 | 已在 room-service 强制;只阻止普通房主/管理员新增禁言 | +| 平台封禁/风控/超级管理 | Flutter 不作 VIP 免责提示 | 独立 `SystemEvictUser` 治理链路会绕过防踢,VIP 不能绕过平台治理 | +| 自定义房间背景 | 按现有房间背景页面调用 | `tiered_privilege_v1` 已由 room-service 强制校验 `custom_room_background` | +| 金币返现 | 消费 system inbox,批量恢复状态,手动领取后使用响应余额 | 已完成 UTC 日资格、异步系统消息、24 小时窗口和 wallet 原子入账;体验卡不参与 | +| 上线全服通知 | 按进程内 UTC 日规则请求后端,消费全局播报群 `vip_online_notice` | 已完成权益/开关校验、服务端资料与头像框、activity outbox 和腾讯云 IM;服务端不做日级去重 | +| 其他 VIP 装扮/功能 | 可根据 `effective_benefits` 展示锁定/解锁态;有素材时使用后端 URL | 权益矩阵已配置,但不等于各 owner 均已强制。Fami 初始 `resource_id=0`、素材为空,未绑定 owner/资源前不能宣称已实现 | + +## 14. Flutter 建议状态流 + +1. 进 VIP 页并发请求 `/vip/packages` 和 `/vip/me`,套餐用前者,用户生效状态用后者。 +2. 购买成功、佩戴成功、卸下成功时,立即用响应中的 `state` 替换全局 VIP store。 +3. App 冷启动、登录成功、回前台以及收到 `vip_notice` 后调 `/vip/me` 校准;同时更新 `user_settings`。 +4. 背包页用 `vip_trial_card` 列表展示每张独立卡;当前佩戴态以 `/vip/me.state.equipped_trial_card.entitlement_id` 为准。 +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`。 diff --git a/docs/VIP系统架构.md b/docs/VIP系统架构.md index ca920b48..5b82fe60 100644 --- a/docs/VIP系统架构.md +++ b/docs/VIP系统架构.md @@ -1,462 +1,182 @@ -# VIP 系统架构设计 - -## 目标 - -VIP 是用户可直接用金币购买的限时会员权益。每个 VIP 等级都可以单独购买,单次购买有效期固定 7 天,不同等级价格不同。购买成功后,系统根据后台配置的资源组发放头像框、座驾、气泡、徽章、礼物等权益。 - -首版只做当前业务真实需要的能力: - -- 用户可以购买任意有效 VIP 等级。 -- 用户可以从低等级升级到高等级。 -- 用户当前 VIP 未过期时,不能购买比当前等级低的 VIP。 -- 同等级重复购买按续期处理。 -- VIP 扣金币、会员状态变更、资源组发放必须在 `wallet-service` 内形成一致账务闭环。 -- 后台只配置 VIP 等级、金币价格、有效期和赠送资源组;客户端不能传价格或资源明细。 +# 可配置 VIP 系统 -## 服务边界 +## 目标与边界 -VIP 属于 `wallet-service` 的账务和权益域,不放在 `user-service`。 +VIP 是 `wallet-service` 按 `app_code` 隔离的会员与权益域。每个 App 通过一份 `vip_program_configs` 选择等级数量、购买有效期策略、后台发放模式和体验卡开关;gateway、room、admin 和客户端只能消费这份显式配置,不得通过 `app_code` 写第二套状态机。 -原因: +- `wallet-service`:会员、体验卡、用户功能开关、权益矩阵、购买扣费、每日返现、资源发放、历史和 outbox 的 owner。 +- `gateway-service`:App HTTP 鉴权、协议转换和钱包 gRPC 编排。 +- `room-service`:只执行房间权限并通过腾讯云 IM 投递当前房间事件,不能拥有会员状态。 +- `server/admin`:配置 program、等级和每级完整权益,发放真实 VIP 或体验卡。 +- Flutter:展示后端状态、操作背包佩戴并处理客户端生命周期效果;不参与购买规则计算。 -- 购买 VIP 必须先扣金币,扣费成功才允许生成 VIP 状态和权益。 -- 购买 VIP 会发放后台资源组,资源组、资源权益和钱包资产已经归 `wallet-service` 管。 -- 如果 VIP 状态放在 `user-service`,扣费、会员状态、资源发放会跨服务,需要分布式事务或补偿,复杂度和失败窗口都更大。 - -服务职责: +全链路业务时间使用 UTC epoch milliseconds。每日结算或刷新按 UTC 0 点切日;用户本地时间只用于展示。 -- `gateway-service`:提供 App HTTP API,做鉴权、参数校验、生成 `request_id`、透传客户端 `command_id`,调用 `wallet-service`。 -- `wallet-service`:拥有 VIP 等级配置、用户 VIP 状态、VIP 购买订单、金币扣费、资源组发放、VIP 事件 outbox。 -- `user-service`:只在用户资料聚合时读取 VIP 摘要,不拥有 VIP 状态。 -- `room-service`:需要展示 VIP 标识时读取用户资料/VIP 投影,不参与 VIP 购买主链路。 -- `server/admin`:后台配置 VIP 等级和资源组,具体后台接口单独设计。 +## 当前 App 策略 -## 核心模型 +| 配置 | Lalu | Fami | +| --- | --- | --- | +| `program_type` | `legacy_timed` | `tiered_privilege_v1` | +| `level_count` | 10 | 9 | +| 同级购买 | 从当前截止时间续期 | 从当前截止时间续期 | +| 高级升级 | 保留剩余时间后追加新时长 | 立即替换为高级,从购买时刻重新计时,旧等级剩余时间丢弃 | +| 低级购买 | 拒绝 | 拒绝 | +| 后台发放 | `direct_membership`,直接写真实 VIP | `trial_card`,发到背包后由用户佩戴 | +| 体验卡 | 关闭 | 开启 | +| 权益集合 | 每级显式保存 | 每级显式保存完整集合,不按 `unlock_level` 自动继承 | -### VIP 等级 +Fami 的 VIP1–VIP9 初始全部为 `disabled`。30 天只是不产生零时长脏配置的占位值;价格和资源组保持 0,运营完成配置并启用前不可购买或发卡。 -`vip_levels` +## 数据模型 -| 字段 | 说明 | -| -------------------------- | -------------------------------------------------- | -| `id` | 内部主键 | -| `level` | VIP 等级,数字越大等级越高 | -| `name` | 展示名称,例如 VIP1、VIP2 | -| `coin_price` | 购买该等级需要消耗的金币数 | -| `duration_ms` | 有效期,首版固定 `7 * 24 * 60 * 60 * 1000` | -| `reward_resource_group_id` | 购买成功后发放的资源组 | -| `status` | `draft` / `active` / `disabled` | -| `sort_order` | App 展示排序 | -| `display_config_json` | 展示配置快照,例如颜色、权益说明、角标,不参与结算 | -| `created_at_ms` | 创建时间 | -| `updated_at_ms` | 更新时间 | +### App 级 program -约束: +`vip_program_configs` 是行为规则的唯一来源: -- `level` 唯一。 -- `coin_price > 0`。 -- `duration_ms` 首版必须等于 7 天,不允许后台临时改成其它值。 -- `active` 状态必须绑定有效资源组。 +- `program_type` +- `level_count` +- `same_level_expiry_policy` +- `upgrade_expiry_policy` +- `downgrade_purchase_policy` +- `benefit_inheritance_policy`,当前固定 `target_only` +- `grant_mode` +- `trial_card_enabled` +- `status` +- `config_version` -### 用户 VIP 当前状态 +后台修改 program、等级或权益时递增 `config_version`。会员、订单和体验卡保留创建时的 program/version 快照,当前权限判断使用最新有效 program 和等级显式权益集合。 -`user_vip_memberships` +### 等级和权益 -| 字段 | 说明 | -| --------------- | ---------------------------- | -| `user_id` | 用户 ID,唯一 | -| `level` | 当前等级 | -| `status` | `active` / `expired` | -| `started_at_ms` | 当前等级周期开始时间 | -| `expires_at_ms` | 当前 VIP 到期时间 | -| `last_order_id` | 最近一次购买订单 | -| `version` | 乐观版本,配合行锁防并发覆盖 | -| `created_at_ms` | 创建时间 | -| `updated_at_ms` | 更新时间 | +- `vip_levels`:等级名称、状态、金币价格、时长、可选资源组和排序。 +- `vip_level_benefits`:以 `(app_code, level, benefit_code)` 保存该等级最终完整权益集合。 -读取时以 `expires_at_ms > now` 判断是否有效,`status` 只作为后台检索和事件处理的辅助状态。这样即使过期任务延迟,App 也不会把过期 VIP 当成有效权益。 +`unlock_level` 只记录 P1 初始化来源,运行时和后台保存都不能据此给高等级自动补权益。纯功能权益的 `resource_id=0`;装扮权益可以绑定同 App 的实际资源。 -### VIP 购买订单 +### 付费会员 -`vip_purchase_orders` +`user_vip_memberships` 保存用户付费会员事实。有效条件是 `level > 0 && expires_at_ms > now_ms`;不依赖异步过期任务才能失效。 -| 字段 | 说明 | -| ---------------------------- | --------------------------------- | -| `order_id` | VIP 订单号 | -| `command_id` | 客户端生成的幂等命令 ID | -| `user_id` | 购买用户 | -| `target_level` | 目标 VIP 等级 | -| `coin_price_snapshot` | 下单时价格快照 | -| `duration_ms_snapshot` | 下单时有效期快照 | -| `resource_group_id_snapshot` | 下单时资源组快照 | -| `previous_level` | 购买前有效等级,无有效 VIP 则为 0 | -| `previous_expires_at_ms` | 购买前到期时间 | -| `new_level` | 购买后等级 | -| `new_expires_at_ms` | 购买后到期时间 | -| `wallet_transaction_id` | 金币扣费交易 ID | -| `resource_grant_id` | 资源组发放记录 ID | -| `status` | `succeeded` / `failed` | -| `failure_reason` | 失败原因 | -| `request_hash` | 幂等请求摘要 | -| `created_at_ms` | 创建时间 | -| `updated_at_ms` | 更新时间 | - -约束: - -- `(user_id, command_id)` 唯一。 -- 相同 `command_id` + 相同 `request_hash` 返回原订单结果。 -- 相同 `command_id` + 不同 `request_hash` 返回幂等冲突。 - -### VIP 变更历史 - -`user_vip_history` - -记录每次购买、续期、升级、过期,供客服、后台账单、风控排查使用。历史表不参与 App 主链路强查询。 - -核心字段: - -- `history_id` -- `user_id` -- `event_type`: `purchase` / `renew` / `upgrade` / `expire` -- `from_level` -- `to_level` -- `from_expires_at_ms` -- `to_expires_at_ms` -- `order_id` -- `created_at_ms` - -## 购买和升级规则 - -定义: - -- 当前有效 VIP:`membership.expires_at_ms > now && membership.level > 0` -- 目标等级:用户本次购买的 `vip_level` - -规则: - -| 场景 | 处理 | -| ---------------------- | ------------------------------------------------------------------------ | -| 无有效 VIP | 可以购买任意 active 等级,`expires_at_ms = now_ms + 7d_ms` | -| 有效 VIP,购买同等级 | 续期,`expires_at_ms = current_expires_at_ms + 7d_ms` | -| 有效 VIP,购买更高等级 | 立即升级,`level = target_level`,`expires_at_ms = current_expires_at_ms + 7d_ms` | -| 有效 VIP,购买更低等级 | 拒绝,返回 `VIP_DOWNGRADE_NOT_ALLOWED` | -| VIP 已过期 | 按无有效 VIP 处理,可以购买任意 active 等级 | - -首版升级采用“保留剩余时间并升级”的策略:如果用户 VIP1 还剩 3 天,又购买 VIP3,则 VIP3 到期时间为当前 VIP1 到期时间再加 7 天。这个规则实现简单、用户感知清晰,也避免升级时损失已付费时长。 - -如果后续业务希望“补差价升级”或“升级只生效 7 天”,只需要扩展 VIP 等级的升级策略,不改变主链路表结构。 - -## 资源组发放规则 - -购买 VIP 成功后,`wallet-service` 根据 `vip_levels.reward_resource_group_id` 发放资源组。 - -资源组继续复用现有资源组能力: - -- 头像框:`avatar_frame` -- 资料卡:`profile_card` -- 座驾:`vehicle` -- 聊天气泡:`chat_bubble` -- 徽章:`badge` -- 飘屏:`floating_screen` -- 礼物:`gift` -- 金币等钱包资产:仅在明确配置时发放,默认不建议 VIP 购买返金币,避免账务绕圈。 - -VIP 资源组需要增加一个明确约束: - -- VIP 专属装扮类资源默认与 VIP 到期时间对齐。 -- 资源组 item 如果配置了独立 `duration_ms`,后台必须能看到它和 VIP 7 天周期的差异。 -- 首版推荐新增 `duration_policy = inherit_vip_expiry`,购买 VIP 时将资源权益到期时间直接设置为 `new_expires_at_ms`。 - -续期和升级时: - -- 同一资源重复发放时,使用资源权益的 `extend_expiry` 或 `align_to_expiry` 策略,避免重复插入导致用户出现多个同资源有效权益。 -- 升级后只发放目标等级配置的资源组;低等级已获得的资源不立即删除,到期后自然失效。 -- App 展示和自动佩戴时按用户当前有效资源、资源等级和佩戴状态决定,不从 VIP 等级反推资源。 - -## 主链路流程 - -```mermaid -sequenceDiagram - autonumber - participant App - participant Gateway as gateway-service - participant Wallet as wallet-service - participant DB as Wallet MySQL - participant Outbox as Wallet Outbox - - App->>Gateway: POST /api/v1/vip/purchase {level, command_id} - Gateway->>Wallet: PurchaseVip(user_id, level, command_id, request_meta) - Wallet->>DB: BEGIN - Wallet->>DB: 查询并锁定 vip_levels(level) - Wallet->>DB: 查询并锁定 user_vip_memberships(user_id) - Wallet->>DB: 校验不能降级、计算 new_expires_at_ms - Wallet->>DB: 锁定用户 COIN 钱包账户 - Wallet->>DB: 扣减金币,写 wallet_transaction / wallet_entries - Wallet->>DB: 发放 VIP 资源组,写 resource_entitlements - Wallet->>DB: upsert user_vip_memberships - Wallet->>DB: 写 vip_purchase_orders / user_vip_history - Wallet->>Outbox: 写 VipPurchased / VipUpgraded / VipRenewed - Wallet->>DB: COMMIT - Wallet-->>Gateway: 返回当前 VIP、扣费、权益摘要 - Gateway-->>App: {code,message,request_id,data} -``` - -关键点: - -- 金币扣费、VIP 状态、资源组发放必须在同一个 `wallet-service` 数据库事务中完成。 -- 客户端只传 `level` 和 `command_id`,价格和资源组完全由服务端配置决定。 -- 扣费成功但资源发放失败不能提交事务;否则用户会付费但拿不到权益。 -- 资源发放成功但 VIP 状态更新失败也不能提交事务;否则权益和会员状态会不一致。 - -## App 一级接口 - -### 查询 VIP 等级 - -`GET /api/v1/vip/levels` - -返回: - -```json -{ - "current_vip": { - "level": 2, - "name": "VIP2", - "expires_at_ms": 1760000000000, - "remaining_ms": 604800000 - }, - "levels": [ - { - "level": 1, - "name": "VIP1", - "coin_price": 1000, - "duration_ms": 604800000, - "can_purchase": true, - "purchase_block_reason": "", - "benefits": [ - { - "resource_type": "avatar_frame", - "resource_id": "vip1_frame", - "name": "VIP1 Avatar Frame", - "duration_policy": "inherit_vip_expiry" - } - ] - } - ] -} -``` - -说明: - -- `can_purchase=false` 通常表示当前有效 VIP 等级高于该等级。 -- App 可以展示所有等级,但购买按钮状态以服务端返回为准。 - -### 查询我的 VIP - -`GET /api/v1/vip/me` - -返回: - -```json -{ - "level": 2, - "name": "VIP2", - "status": "active", - "expires_at_ms": 1760000000000, - "remaining_ms": 604800000, - "renewable": true, - "upgradeable_levels": [3, 4, 5] -} -``` - -说明: - -- 底部“我的”页面只需要拿 VIP 摘要,不要拉完整资源列表。 -- 完整装扮资源仍从资源/背包接口查询。 - -### 购买 VIP - -`POST /api/v1/vip/purchase` - -请求: - -```json -{ - "level": 3, - "command_id": "client-generated-id" -} -``` - -返回: - -```json -{ - "order_id": "vip_order_123", - "event_type": "upgrade", - "coin_spent": 3000, - "vip": { - "level": 3, - "name": "VIP3", - "expires_at_ms": 1760604800000 - }, - "granted_resources": [ - { - "resource_type": "vehicle", - "resource_id": "vip3_vehicle", - "expires_at_ms": 1760604800000 - } - ] -} -``` +购买事务同时完成: -## gRPC 契约建议 - -新增 `wallet.v1.VipService`: - -```protobuf -service VipService { - rpc ListVipLevels(ListVipLevelsRequest) returns (ListVipLevelsResponse); - rpc GetMyVip(GetMyVipRequest) returns (GetMyVipResponse); - rpc PurchaseVip(PurchaseVipRequest) returns (PurchaseVipResponse); -} -``` - -核心字段: - -- `RequestMeta meta` -- `int64 user_id` -- `int32 level` -- `string command_id` -- `int64 now_ms` 不由客户端传,由服务端生成;测试可通过 clock 注入。 +1. 锁定 program、目标等级和当前会员; +2. 根据 program 计算有效期,拒绝降级; +3. 锁定 COIN 账户并扣费; +4. 发放目标资源组; +5. 更新会员,写订单、历史和 wallet outbox; +6. 一次事务提交。 -错误码建议纳入 `pkg/xerr` catalog: +`command_id` 是购买幂等键,`request_id` 仅用于链路追踪。 -- `VIP_LEVEL_NOT_FOUND` -- `VIP_LEVEL_DISABLED` -- `VIP_DOWNGRADE_NOT_ALLOWED` -- `VIP_PRICE_CHANGED`,仅在未来支持客户端价格确认时使用 -- `WALLET_INSUFFICIENT_BALANCE` -- `IDEMPOTENCY_CONFLICT` +`vip_command_locks` 在任何会员、账户或资源业务锁之前串行化 `(app_code, command_id)`。购买、直接会员赠送和体验卡发放共享该守卫空间;同命令并发重试会等待原事务提交后读取稳定回执,三种业务也不能交叉复用同一命令号。 -gRPC status 仍保持少量通用 code: +### 体验卡 -- 参数错误:`InvalidArgument` -- 余额不足、不能降级:`FailedPrecondition` -- 等级不存在或禁用:`NotFound` / `FailedPrecondition` -- 幂等冲突:`AlreadyExists` -- 内部事务失败:`Internal` +体验卡使用三层事实: -业务错误放在 `google.rpc.ErrorInfo.reason`。 +- `resources(resource_type=vip_trial_card)`:卡面与等级元数据; +- `user_resource_entitlements`:背包实例和绝对有效期; +- `user_resource_equipment`:当前单选佩戴指针; +- `user_vip_trial_cards`:等级、来源、时长和 program/version 快照。 -## 并发和幂等 +发卡时即写入 `effective_at_ms` 和 `expires_at_ms`,但不自动佩戴。切换卡片只替换 `user_resource_equipment` 指针,不修改、删除、暂停或延长任一卡片。 -同一用户可能快速点击多次购买或同时升级,必须按用户串行化处理。 +例如 A=14 天、B=20 天、C=30 天:佩戴 A 后立刻切 B,B 生效,A 仍保留原绝对到期时间;之后只要 A 未过期即可重新佩戴。体验卡等级不受当前付费 VIP 或上一张体验卡等级限制。 -事务内锁顺序固定: +### 用户功能开关 -1. 锁 `vip_levels(level)`,读取配置快照。 -2. 锁 `user_vip_memberships(user_id)`。 -3. 锁用户 `COIN` 钱包账户。 -4. 写订单、流水、权益、会员状态。 +`user_vip_settings` 按 `(app_code,user_id)` 保存两个用户偏好: -如果 `user_vip_memberships` 不存在,先插入一行占位再锁,或者用用户级 advisory lock。不要只依赖应用内 mutex,因为多实例部署时无效。 +- `room_entry_notice_enabled`:进房 VIP 高亮通知; +- `online_global_notice_enabled`:上线 VIP 全服飘屏。 -幂等规则: +无记录时两项默认为 `true`,首次修改才写行。偏好不授予权益:无 VIP 或对应等级没有权益时,即使开关为开也不会放行。用户可在无 VIP、VIP 过期或切换体验卡时保留偏好;Fami 与 Lalu 互不影响。 -- `command_id` 是购买命令幂等键,不使用 `request_id`。 -- 已成功订单重复请求直接返回原结果。 -- 已失败订单是否允许重试取决于失败类型:余额不足可以用新 `command_id` 重试;系统错误如果事务未提交,可以继续用原 `command_id` 重试。 -- 订单内保存价格、资源组、有效期快照,后台改配置不影响已成功订单解释。 +### 每日金币返现 -## VIP 过期 +`daily_coin_rebate` 的 `metadata_json.coin_amount` 是该等级每日可领金币正整数。只有启用的付费 VIP 参与,体验卡即使历史配置误开 `trial_enabled` 也会被 wallet 二次排除。 -VIP 是否有效以 `expires_at_ms` 为准。过期处理分两层: +每个 App 每个 UTC 日期只有一个 `vip_daily_coin_rebate_runs`: -- App 查询时实时判断,过期立即返回 `status=expired`。 -- 后台定时任务扫描过期会员,写 `user_vip_history(expire)` 和 `VipExpired` outbox,用于消息通知、缓存清理和搜索投影更新。 +1. 首个成功批次固化当时的 `config_version` 和等级金额矩阵;后续分页不重读新配置。 +2. wallet 根据会员历史还原 UTC 0 点时的付费 VIP;0 点后才购买或升级的状态从次日起参与。 +3. 生成 `vip_daily_coin_rebates` 资格,领取窗口固定为 `[UTC 当日0点,UTC 次日0点)`。 +4. 同事务写 `VipDailyCoinRebateAvailable` outbox;activity-service 幂等投影为“VIP金币返现”系统消息。 +5. 用户手动领取时,返现行锁、COIN 余额、交易、分录和 `WalletBalanceChanged` outbox 在一个事务内提交。 -资源权益也以自己的 `expires_at_ms` 判断有效性。如果使用 `inherit_vip_expiry`,VIP 到期后头像框、座驾等权益自然失效,不需要额外删除。 +“日切资格”严格按 UTC 0 点;“金额配置”是当日首个成功 run 的快照,不伪造系统尚未保存的 0 点历史配置。正常情况下 cron 每分钟触发;如零点后 wallet/cron 长时间不可用,恢复前的后台金额修改会进入当日快照。运营若要保证修改次日生效,应在当日 run 已创建后修改。 -## Outbox 事件 +## 最终生效状态 -`wallet-service` 写出以下事件: - -- `VipPurchased` -- `VipRenewed` -- `VipUpgraded` -- `VipExpired` +所有调用方统一消费 `VipState`: -事件内容: +- `paid_vip`:真实购买会员; +- `equipped_trial_card`:当前有效且已佩戴的体验卡; +- `effective_vip`:最终展示和权限使用的 VIP; +- `effective_source`:`paid`、`trial` 或 `none`; +- `effective_benefits`:最终身份拥有的权益资格;可关闭的通知类权益还要与 `user_settings` 做 AND; +- `program_config`:当前 App 规则; +- `user_settings`:当前 App 下的进房/上线通知偏好。 -- `event_id` -- `user_id` -- `order_id` -- `from_level` -- `to_level` -- `expires_at_ms` -- `coin_spent` -- `resource_group_id` -- `occurred_at_ms` +program 启用时的优先级固定为:`trial_card_enabled=true` 且体验卡有效并已佩戴时覆盖展示;否则使用有效付费会员;二者都无效则为 `none`。关闭体验卡开关只停止它参与最终权限合并,背包和佩戴原始事实仍保留;关闭整个 program 时付费与卡片原始事实仍可查询,但最终身份为 `none`、不下发权益。 -消费者: +钱包只读取 `effective_vip.level` 对应的显式权益行。来源为 `trial` 时,再移除 `trial_enabled=false` 的权益;当前 `daily_coin_rebate` 不对体验卡开放。owner service 必须按 `benefit_code` 判断,不能改回 `level >= N`;进房和上线通知的执行方必须使用 wallet 已合并用户开关的结果。 -- `user-service` 可消费后更新用户资料投影,便于列表页快速展示 VIP 标识。 -- `room-service` 如需房间内展示 VIP 角标,可消费投影事件或通过用户资料聚合读取,不接入购买主链路。 -- `activity-service` 可用于 VIP 活动任务统计。 +## P1 权益编码 -## 缓存策略 +| 等级 | 本级新增权益 | +| --- | --- | +| VIP1 | `vip_badge_identity`、`vip_medal`、`avatar_frame`、`vip_title` | +| VIP2 | `chat_bubble`、`vip_gift`、`entry_effect`、`visitor_history` | +| VIP3 | `voice_wave`、`profile_card`、`custom_room_background`、`room_image_message` | +| VIP4 | `animated_avatar`、`animated_room_cover`、`mic_skin`、`room_border`、`vehicle` | +| VIP5 | `colored_room_name`、`colored_nickname`、`colored_id`、`gift_tray_skin` | +| VIP6 | `hide_profile_data`、`custom_avatar_frame`、`leaderboard_invisible`、`daily_coin_rebate` | +| VIP7 | `custom_profile_card`、`anonymous_profile_visit`、`custom_gift` | +| VIP8 | `room_entry_notice`、`custom_pretty_id`、`custom_vehicle` | +| VIP9 | `anti_kick`、`anti_mute`、`online_global_notice` | -VIP 配置可以缓存,用户 VIP 状态不要只放 Redis。 +初始化时高等级行已展开为完整集合,但这是 seed 结果,不是运行时继承规则。后台可以显式移除任一等级的某项权益。 -- `vip_levels`:本地内存缓存 + 短 TTL,后台改配置后通过版本号或事件刷新。 -- `user_vip_memberships`:MySQL 为准,Redis 只做读优化。 -- 购买成功后删除或刷新 `vip:me:{user_id}` 缓存。 -- 过期时间短且强相关权益展示,缓存 TTL 不能超过 `min(60s, expires_at_ms-now)`。 +## 房间权限和 IM -## 后台配置约束 +`room-service` 在需要房间权限时读取 wallet 的 `GetMyVip.state`: -后台配置 VIP 等级时必须校验: +- `custom_room_background`:P1 program 的房主保存或切换自定义背景前强校验;Lalu 保持原逻辑。 +- `anti_kick`:普通房主/管理员踢人时拒绝操作。 +- `anti_mute`:普通房主/管理员新增禁言时拒绝操作。 +- 平台封禁、风控、超级管理员使用独立系统治理入口,不经过上述普通房管守卫。 +- `room_entry_notice`:权益有效且用户开关开启时,随 `JoinRoomResponse`、`RoomUserJoined` 和腾讯云 IM 当前房间系统消息携带;只在用户进入的当前房间展示,不做全服广播。 -- 等级唯一且大于 0。 -- 金币价格大于 0。 -- 有效期首版固定 7 天。 -- 绑定资源组必须存在且可用。 -- 资源组里的装扮资源建议使用 `inherit_vip_expiry`。 -- 禁用等级只影响新购买,不影响已购买用户的剩余有效期。 -- 修改价格只影响修改后的新订单,不回改历史订单。 +`online_global_notice` 由 `POST /vip/online-notice` 触发:gateway 先调用 wallet `CheckVipBenefit`,同时校验权益资格和用户开关;然后从 user-service 取服务端用户资料,最后写 activity-service 全局播报 outbox。腾讯云 IM 使用 `TIMCustomElem`,`Ext=im_broadcast`、`Desc=vip_online_notice`、`broadcast_type=vip_online_notice`、`scope=global`。Flutter 在进程内按 UTC 日控制触发:同一进程每天最多触发一次,不持久化该标记;杀进程重启后允许再次触发。服务端不做用户日级去重,但相同 `command_id` 的 HTTP 重试映射到同一 `event_id`。Flutter 不能直接向全服群发消息。 -后台可以修改资源组,但已成功订单使用订单快照解释;用户已经拿到的权益不因为后台换资源组被自动替换。 +## App HTTP API -## 数据一致性原则 +统一前缀 `/api/v1`,响应使用 `{code,message,request_id,data}`: -- VIP 购买不是普通“资源组发放”,它必须先扣金币。 -- 不允许 gateway 先扣金币再单独调用资源发放。 -- 不允许 user-service 写 VIP 状态。 -- 不允许客户端传资源 ID、资源组 ID、价格。 -- 不允许用 Redis 作为 VIP 当前状态唯一来源。 -- 不允许后台直接改用户 VIP 状态来修单,修单必须走后台补单/补偿命令,并写历史和审计。 +- `GET /vip/packages`:program、可购买等级、每级权益和完整 state。 +- `GET /vip/me`:付费、体验卡、最终 VIP、权益资格和用户功能开关。 +- `POST /vip/purchase`:请求 `{command_id,level}`;价格、时长和资源由服务端读取。 +- `GET|PATCH /vip/settings`:读取或局部修改进房/上线通知偏好;空 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` 恢复系统消息真实状态,或用受限分页查历史。 +- `POST /vip/coin-rebates/{rebate_id}/claim`:请求 `{command_id}`,金额、归属、过期和入账全由 wallet 裁决。 +- `GET /users/me/resources?resource_type=vip_trial_card&active_only=true`:查询背包体验卡资源实例。 +- `POST /vip/trial-cards/{entitlement_id}/equip`:佩戴指定背包实例。 +- `DELETE /vip/trial-cards/equipped`:卸下当前体验卡。 +- 历史通用背包装备/卸下接口命中 `vip_trial_card` 时由 wallet service 委托上述专用状态机,禁止仓储层直接改装备槽;Flutter VIP 流程仍使用专用接口以一次取得完整 `VipState`。 +- `POST /manager-center/vip-grants`:gateway 按当前 program 自动选择直接会员或 30 天体验卡发放;Fami 发卡不自动佩戴。 -## 实现顺序 +后台接口: -1. 扩展 protobuf:新增 `VipService`、VIP 等级、我的 VIP、购买 VIP 响应结构。 -2. 增加 MySQL 表:`vip_levels`、`user_vip_memberships`、`vip_purchase_orders`、`user_vip_history`。 -3. 在 `wallet-service` 实现 VIP repository,先完成等级查询和用户 VIP 查询。 -4. 实现 `PurchaseVip` 事务:等级校验、幂等、行锁、扣金币、资源组发放、会员状态更新、历史和 outbox。 -5. 在 `gateway-service` 增加 App HTTP API:`/api/v1/vip/levels`、`/api/v1/vip/me`、`/api/v1/vip/purchase`。 -6. 接入用户资料聚合:底部“我的”和房间用户信息只展示 VIP 摘要。 -7. 增加过期扫描任务和 outbox 消费投影。 -8. 再做后台 VIP 配置页面和后台补单/审计能力。 +- `GET|PUT /v1/admin/activity/vip-program` +- `GET|PUT /v1/admin/activity/vip-levels` +- `POST /v1/admin/activity/vip-trial-card-grants` +- `POST /v1/admin/activity/vip-grants`,仅用于 `direct_membership` program -## 测试重点 +## 权益落地边界 -必须覆盖: +当前服务端已强制执行购买有效期、体验卡状态合并、用户通知开关、每日金币返现资格/消息/手动领取入账、自定义房间背景、防踢、防禁言、房内进场通知和上线全服通知。装扮类权益由已绑定的钱包资源与 Flutter 展示链路执行。 -- 无 VIP 购买 VIP1 成功。 -- VIP1 未过期时续费 VIP1,到期时间追加 7 天。 -- VIP1 未过期时购买 VIP3,等级变 VIP3,到期时间追加 7 天。 -- VIP3 未过期时购买 VIP1 被拒绝。 -- VIP 过期后可以购买任意等级。 -- 金币不足时不写 VIP 状态、不发资源。 -- 资源组发放失败时金币扣费回滚。 -- 同一 `command_id` 重试返回同一订单。 -- 同一用户并发购买时只产生符合顺序的一条最终状态。 -- 后台禁用等级后不能新购买,但不影响已购买用户有效期。 +以下权益仍只有稳定编码和资格下发,不能仅凭本架构宣称业务已完整闭环:访客匿名/隐藏、榜单隐身、房间发图、动态媒体、彩色样式和礼物托盘等。各 owner 实现时必须调用 `CheckVipBenefit` 或消费 `effective_benefits`,并补自己的存储、审计、风控和边界测试。 diff --git a/docs/flutter对接/Huwaa首页房间筛选Flutter对接.md b/docs/flutter对接/Huwaa首页房间筛选Flutter对接.md new file mode 100644 index 00000000..7a2c8694 --- /dev/null +++ b/docs/flutter对接/Huwaa首页房间筛选Flutter对接.md @@ -0,0 +1,82 @@ +# Huwaa 首页房间筛选 Flutter 对接 + +## 地址 + +筛选目录: + +```http +GET /api/v1/rooms/filters +Authorization: Bearer +X-App-Code: huwaa +``` + +房间列表: + +```http +GET /api/v1/rooms?tab=hot®ion_id=1001 +GET /api/v1/rooms?tab=hot&country_code=AE +``` + +目录接口要求用户已登录并完成资料。租户权威值是 access token claims 中的 `app_code`;`X-App-Code`/包名只参与请求入口解析,不能覆盖 token 或用来跨租户切换。Huwaa 返回本 App 的全部 active 区域和其中 enabled 国家;其他 App 只返回当前用户所在 active 区域及其国家。 + +## 参数 + +目录接口没有 query 参数。每个 option 都返回 `query_key` 和 `query_value`,Flutter 按下面规则调用房间列表: + +- All:`query_key`、`query_value` 都为空,不传 `region_id` 和 `country_code`。 +- 区域:把 option 的 `query_key=region_id`、`query_value` 原样放进 query。 +- 国家:把 option 的 `query_key=country_code`、`query_value` 原样放进 query。 +- `region_id` 与 `country_code` 不能同时传;切换筛选项时清空旧 cursor,再从第一页请求。 +- 旧参数 `country` 继续兼容,新代码统一使用 `country_code`。 + +`parent_region_id` 只用于把国家展示在所属区域下。筛选国家时只传 `country_code`,不要把 `parent_region_id` 同时作为 `region_id` 传入。 + +## 返回值 + +```json +{ + "code": "OK", + "message": "ok", + "request_id": "req-room-filters", + "data": { + "all": { + "filter_type": "all", + "query_key": "", + "query_value": "" + }, + "regions": [ + { + "filter_type": "region", + "query_key": "region_id", + "query_value": "1001", + "region_id": 1001, + "region_code": "MIDDLE_EAST", + "region_name": "Middle East", + "sort_order": 10 + } + ], + "countries": [ + { + "filter_type": "country", + "query_key": "country_code", + "query_value": "AE", + "parent_region_id": 1001, + "country_id": 971, + "country_code": "AE", + "country_name": "United Arab Emirates", + "country_display_name": "UAE", + "country_flag": "🇦🇪", + "sort_order": 10 + } + ] + } +} +``` + +目录的数组顺序已经使用后台 `sort_order`。国家只在“国家 enabled 且所属区域 active”时下发,客户端不要自行拼接国家码或区域 ID。 + +`GET /api/v1/rooms` 响应中的旧 `data.countries` 字段继续保留,供旧版当前区域国家筛选使用;Huwaa 新版完整目录以本接口为准。 + +## 相关 IM/RTC + +筛选目录和列表筛选不创建房间、不入腾讯云 IM 群,也不签发 RTC token。用户实际进入房间后,继续按现有 JoinRoom 流程处理 IM/RTC。 diff --git a/docs/openapi/gateway.swagger.yaml b/docs/openapi/gateway.swagger.yaml index 13716a7c..9f42b175 100644 --- a/docs/openapi/gateway.swagger.yaml +++ b/docs/openapi/gateway.swagger.yaml @@ -123,7 +123,7 @@ responses: schema: $ref: "#/definitions/ErrorEnvelope" Forbidden: - description: 已认证但被禁用、封禁或无权限。 + description: 已认证但资料未完成、被禁用、封禁或无权限;常见 `code` 为 `PROFILE_REQUIRED`、`USER_DISABLED`、`PERMISSION_DENIED`。 schema: $ref: "#/definitions/ErrorEnvelope" NotFound: @@ -1014,13 +1014,41 @@ paths: $ref: "#/responses/Internal" "502": $ref: "#/responses/UpstreamError" + /api/v1/rooms/filters: + get: + tags: + - rooms + summary: 首页房间区域与国家筛选目录 + operationId: listRoomFilters + description: >- + 返回可直接用于房间发现列表的筛选项。每个 option 的 query_key/query_value 可原样作为 + GET /api/v1/rooms 的查询参数;All 的两个字段为空,表示不附加 region_id/country_code。 + Huwaa 返回当前 app scope 的全部 active 区域及其 enabled 国家,其他 App 只返回当前登录用户所在 active 区域,防止下发不可用的跨区选项。 + 该路由要求 access token 有效且用户资料已完成;资料未完成返回 403/PROFILE_REQUIRED。 + security: + - BearerAuth: [] + responses: + "200": + description: 查询成功;国家项只包含 enabled 国家与 active 区域映射的交集。 + schema: + $ref: "#/definitions/RoomFilterCatalogEnvelope" + "401": + $ref: "#/responses/Unauthorized" + "403": + $ref: "#/responses/Forbidden" + "502": + $ref: "#/responses/UpstreamError" /api/v1/rooms: get: tags: - rooms summary: 房间发现列表 operationId: listRooms - description: 按当前登录用户的服务端 region_id 查询房间发现列表;响应卡片显式返回 `im_group_id`,当前值等于 `room_id`,但客户端不能硬编码该映射。 + description: >- + Huwaa 不传 region_id/country_code 时查询 All,传 region_id 时查指定 active 区域,传 country_code 时查指定 enabled 国家,两者互斥。 + 非 Huwaa App 仍按当前登录用户的服务端 region_id 隔离,不接受客户端 region_id。 + 置顶之后的普通房依次是本国家有人、其他国家/区域有人、本国家没人、其他国家/区域没人。 + 响应卡片显式返回 im_group_id,当前值等于 room_id,但客户端不能硬编码该映射。 security: - BearerAuth: [] parameters: @@ -1049,6 +1077,23 @@ paths: in: query required: false type: string + - name: region_id + in: query + required: false + type: integer + format: int64 + minimum: 1 + description: Huwaa 区域筛选;必须原样使用 `/api/v1/rooms/filters` 的 active `region_id`,不得与 `country_code` 同传。 + - name: country_code + in: query + required: false + type: string + description: Huwaa 国家筛选;必须原样使用 `/api/v1/rooms/filters` 的 enabled 大写国家码,不得与 `region_id` 同传。 + - name: country + in: query + required: false + type: string + description: 旧客户端兼容别名,等价于 `country_code`;新客户端统一使用 `country_code`。 responses: "200": description: 查询成功,`data.rooms[*].im_group_id` 是 JoinRoom 成功后客户端加入的腾讯 IM 房间群 ID。 @@ -2155,6 +2200,7 @@ paths: tags: - resources summary: 佩戴我的资源 + description: vip_trial_card 会在 wallet-service 内部委托 VIP 专用状态机;该通用响应不含完整 VipState,VIP 客户端应使用 /api/v1/vip/trial-cards/{entitlement_id}/equip。 operationId: equipMyResource security: - BearerAuth: [] @@ -2475,6 +2521,7 @@ definitions: - DISPLAY_USER_ID_LEASE_EXPIRED - DISPLAY_USER_ID_PAYMENT_REQUIRED - USER_DISABLED + - PROFILE_REQUIRED - PERMISSION_DENIED - NOT_FOUND - CONFLICT @@ -2492,6 +2539,7 @@ definitions: - conflict - insufficient balance - permission denied + - profile required - not found request_id: type: string @@ -4829,6 +4877,12 @@ definitions: type: string room_short_id: type: string + country_code: + type: string + description: 房主国家投影的大写国家码,首页国家筛选和卡片展示均以该字段为准。 + country_flag: + type: string + description: 根据 `country_code` 派生的国旗 emoji;无有效国家投影时省略。 RoomListData: type: object properties: @@ -4838,6 +4892,134 @@ definitions: $ref: "#/definitions/RoomListItemData" next_cursor: type: string + countries: + type: array + description: 兼容旧客户端的当前用户区域国家列表;完整跨区域目录请使用 `/api/v1/rooms/filters`。 + items: + $ref: "#/definitions/RoomListCountryData" + RoomListCountryData: + type: object + required: + - country_code + properties: + country_id: + type: integer + format: int64 + country_code: + type: string + country_name: + type: string + country_display_name: + type: string + country_flag: + type: string + sort_order: + type: integer + format: int32 + RoomFilterAllData: + type: object + required: + - filter_type + - query_key + - query_value + properties: + filter_type: + type: string + enum: [all] + query_key: + type: string + description: 固定为空字符串;客户端不附加筛选参数。 + query_value: + type: string + description: 固定为空字符串。 + RoomFilterRegionData: + type: object + required: + - filter_type + - query_key + - query_value + - region_id + - region_code + - region_name + - sort_order + properties: + filter_type: + type: string + enum: [region] + query_key: + type: string + enum: [region_id] + query_value: + type: string + description: region_id 的十进制字符串,可原样回传。 + region_id: + type: integer + format: int64 + region_code: + type: string + region_name: + type: string + sort_order: + type: integer + format: int32 + RoomFilterCountryData: + type: object + required: + - filter_type + - query_key + - query_value + - parent_region_id + - country_id + - country_code + - country_name + - country_display_name + - country_flag + - sort_order + properties: + filter_type: + type: string + enum: [country] + query_key: + type: string + enum: [country_code] + query_value: + type: string + description: 规范化后的大写 country_code,可原样回传。 + parent_region_id: + type: integer + format: int64 + description: 仅用于客户端把国家分组到区域;筛选国家时不要同时传 region_id。 + country_id: + type: integer + format: int64 + country_code: + type: string + country_name: + type: string + country_display_name: + type: string + country_flag: + type: string + sort_order: + type: integer + format: int32 + RoomFilterCatalogData: + type: object + required: + - all + - regions + - countries + properties: + all: + $ref: "#/definitions/RoomFilterAllData" + regions: + type: array + items: + $ref: "#/definitions/RoomFilterRegionData" + countries: + type: array + items: + $ref: "#/definitions/RoomFilterCountryData" MyRoomData: type: object required: @@ -5581,6 +5763,13 @@ definitions: properties: data: $ref: "#/definitions/RoomListData" + RoomFilterCatalogEnvelope: + allOf: + - $ref: "#/definitions/GatewayOKEnvelopeBase" + - type: object + properties: + data: + $ref: "#/definitions/RoomFilterCatalogData" MyRoomEnvelope: allOf: - $ref: "#/definitions/GatewayOKEnvelopeBase" diff --git a/docs/主播公会BD后台架构.md b/docs/主播公会BD后台架构.md index b3fa03d8..b00c4b50 100644 --- a/docs/主播公会BD后台架构.md +++ b/docs/主播公会BD后台架构.md @@ -79,6 +79,8 @@ graph LR 当前 `user_id` 是内部稳定主键,后台仍必须在所有 host/Agency/BD 查询、幂等和审计 detail 中带上 `app_code`。如果某些现有表还使用全局 `PRIMARY KEY(user_id)`、`PRIMARY KEY(command_id)` 或 `PRIMARY KEY(event_id)`,这只能说明当前实现暂时要求这些 ID 全局唯一;不能据此省略 `app_code`,也不能在多 App 写入前声称同一个 `command_id` 可以跨 App 复用。 +经理中心创建 BD Leader 时,`app_code` 必须来自已验证的 App token,不接受客户端自报租户。Huwaa 的 `manager_add_bd_leader` 搜索和创建可跨国家/区域;其他 App 仍要求经理和目标用户同国家。两类路径都必须保留 active Manager 和 `manager_add_bd_leader` 能力校验。 + ```sql admin_operation_logs( id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, @@ -432,8 +434,9 @@ service UserHostAdminService { } ``` -`CreateBDLeaderRequest` 必须携带 `region_id`。user-service 校验该区域 active,锁定目标用户行,必要时更新 `users.region_id`,再创建 `bd_profiles`;同一个 `command_id` 重试只返回已创建的 BD Leader 事实,不重复迁移。 -这属于允许改变用户区域的后台关系管理路径之一;完整来源见 [User Region Change Sources](./用户区域与国家开发.md#user-region-change-sources)。 +`CreateBDLeaderRequest` 不接受 `region_id`。user-service 锁定目标用户行,读取其当前 active `users.region_id`,再使用该区域创建或恢复 BD Leader 事实;不会因创建角色而迁移用户国家/区域。同一个 `command_id` 重试只返回已创建的 BD Leader 事实。 + +Agency 邀请、Host 主动申请、BD 邀请的区域例外也由 `user-service` 按 `app_code` 执行:仅 Huwaa 在邀请/申请创建及接受/审核阶段允许跨区,其他 App 保留区域校验。Agency 主动邀请 Host 不在例外内。Coin Seller 列表、子币商申请/审批和转账授权对所有 App 仍为同区域。 当前项目仍在开发阶段,proto 可以按当前事实调整;修改 `api/proto` 后必须运行 `make proto` 并提交生成文件。 @@ -445,7 +448,7 @@ service UserHostAdminService { - Cycle calculation 使用 deterministic item key。重跑同一个 `draft` cycle 可以替换 draft items 或返回现有结果,不能重复插入。 - Cycle approve 必须锁 cycle 当前状态为 `draft`。 - Posting 使用 `salary_item_id` 作为钱包幂等键。`post_failed` 重试只处理未 posted item。 -- Relationship admin action 要锁目标用户的 `users`、`host_profiles`、`agencies`、`bd_profiles`,避免和 App 邀请接受并发造成身份冲突。后台创建 BD Leader 需要在同一事务内更新 `users.region_id` 和 `bd_profiles.region_id`。 +- Relationship admin action 要锁目标用户的 `users`、`host_profiles`、`agencies`、`bd_profiles`,避免和 App 邀请接受并发造成身份冲突。创建 BD Leader 使用目标用户当前 `users.region_id`,不在角色事务内改写用户区域。 ## Event And Outbox @@ -511,6 +514,9 @@ Outbox consumers can update App message inbox, BI, risk systems, and export jobs | Posting fails after partial success | Retry posts only unposted items | | Posted item needs correction | Adjustment item created; original item remains immutable | | Admin closes Agency | Agency hidden from App search; existing facts remain auditable | +| Huwaa Manager creates a BD Leader in another country/region | Creation succeeds; target keeps its current region | +| Other App Manager creates a BD Leader in another country | Request is rejected before `CreateBDLeader` is called | +| Huwaa Coin Seller creates or approves a cross-region sub-seller relation | Request is rejected with the existing region boundary | ## Critical Rules @@ -520,4 +526,5 @@ Outbox consumers can update App message inbox, BI, risk systems, and export jobs - BD/BD Leader base is downstream host salary only. - Leader direct Agency salary source must be de-duplicated. - Every admin mutation must be audited and idempotent. +- Huwaa 跨区例外只适用于 Agency 邀请、Host 主动申请、BD 邀请和经理创建 BD Leader;Coin Seller 仍为同区域。 - Redis cannot be the source of truth for policies, salary, relationships, or audit. diff --git a/docs/主播公会BD架构.md b/docs/主播公会BD架构.md index 146e7735..57a0bb88 100644 --- a/docs/主播公会BD架构.md +++ b/docs/主播公会BD架构.md @@ -9,7 +9,7 @@ ## Goals - 用户申请加入 Agency 并通过后成为主播;Agency 踢出用户只解除 Agency 归属,不取消主播身份。 -- 用户只能搜索并申请加入自己所属区域的 active Agency。 +- Huwaa 用户可搜索并申请加入本 App 内的跨区域 active Agency;其他 App 保留现有国家/区域限制。 - Agency 归属于 BD;BD 归属于 BD Leader。BD Leader 也是 BD,只是具备邀请 BD 的能力。 - BD 可以邀请用户成为 Agency;BD Leader 可以邀请用户成为 BD,也可以直接邀请用户成为 Agency。 - 用户被邀请成为 Agency 时自动成为主播;但已是主播的用户不能再成为 Agency。 @@ -279,22 +279,20 @@ agency_memberships( ## Region Rules -用户所属区域来自 `user-service.users.region_id`,不能由客户端提交。 +用户所属区域来自 `user-service.users.region_id`,不能由客户端提交。`app_code` 来自 gateway 已验证的 token 并写入 `RequestMeta`;客户端不能通过请求体或请求头伪造 Huwaa 例外。 国家/区域后台管理边界在 `hyapp-admin-server`:创建国家、启用/禁用国家、创建区域、启用/禁用区域不属于 App 侧 user-service RPC。App 侧只消费 user-service 已计算好的 `region_id` 和区域投影。 -后台创建 BD Leader 是关系管理命令,不是客户端区域提交:`hyapp-admin-server` 负责权限和审计,`user-service` 在同一事务里把目标用户的 `users.region_id` 更新为后台选择的区域,并用同一个区域创建 `bd_profiles`。 -用户区域允许变化的完整来源以 [User Region Change Sources](./用户区域与国家开发.md#user-region-change-sources) 为准;Host/Agency/BD 关系只消费当前 `users.region_id` 和各关系表里的区域快照。 +用户区域允许变化的完整来源以 [User Region Change Sources](./用户区域与国家开发.md#user-region-change-sources) 为准;Host/Agency/BD 关系创建后保留目标用户当前区域,Huwaa 跨区组织关系不会顺带迁移 `users.region_id`。 | Action | Region Rule | | --- | --- | -| 后台创建 BD Leader | 后台必须选择 active 区域;目标用户当前区域可以不同,创建成功后目标用户 `users.region_id` 和 BD Leader `bd_profiles.region_id` 都变为所选区域 | -| 搜索 Agency | 只返回 `agency.region_id == user.region_id` 且 active/join_enabled | -| 申请加入 Agency | 申请人 `region_id` 必须等于 Agency `region_id` | -| BD 邀请 Agency | BD 和被邀请人必须在同一区域,除非后台显式跨区授权 | -| Leader 邀请 BD | Leader 和被邀请人必须在同一区域,除非后台显式跨区授权 | -| Leader 邀请 Agency | Leader 和被邀请人必须在同一区域,除非后台显式跨区授权 | -| 用户改国家导致区域变化 | 不自动迁移 Agency/BD 归属;新申请按新区域限制,历史统计按事件快照归属 | - -如果后续业务需要跨区 Agency 或跨区 BD,必须增加显式 `region_scope` 和后台审批,不能绕过区域规则直接查全局 Agency。 +| 经理创建 BD Leader | Huwaa 经理可搜索并创建其他国家/区域的 BD Leader;其他 App 保持经理与目标用户同国家。创建后 BD Leader 使用目标用户已有 `users.region_id`,不迁移用户国家/区域 | +| 搜索 Agency | Huwaa 返回本 App 内所有 active/join_enabled Agency;其他 App 保留按当前用户国家过滤 | +| 申请加入 Agency | Huwaa 申请创建和 Agency 审核通过均允许跨区;其他 App 要求申请人与 Agency 同区域 | +| Agency 主动邀请 Host | 所有 App 仍要求目标用户与 Agency 同区域;Huwaa 例外只适用于 Host 主动申请 | +| BD/Leader 邀请 Agency | Huwaa 的邀请创建和接受均允许跨区;其他 App 要求邀请人与目标用户同区域 | +| Leader 邀请 BD | Huwaa 的邀请创建和接受均允许跨区;其他 App 要求 Leader 与目标用户同区域 | +| Coin Seller | 所有 App 继续按区域返回 active 币商;子币商申请创建、审批建立关系和转账前授权均要求父子币商同区域 | +| 用户改国家导致区域变化 | 不自动迁移 Agency/BD 归属;新申请或邀请按 `app_code` 对应规则处理,历史统计按事件快照归属 | ## Application And Invitation Flows @@ -309,16 +307,16 @@ sequenceDiagram C->>G: GET /agencies/search G->>U: SearchAgenciesForUser(user_id) - U->>H: load user region and active agencies - H-->>U: active agencies in region - U-->>G: active agencies in region + U->>H: load app_code policy, user country/region and active agencies + H-->>U: Huwaa all active agencies; other App same-country agencies + U-->>G: app-scoped agency list G-->>C: agency list C->>G: POST /host/applications G->>U: ApplyToAgency(user_id, agency_id) U->>H: load user region and agency H->>H: lock user host profile and agency - H->>H: create pending application + H->>H: enforce app-scoped region policy and create pending application H-->>U: application U-->>G: application ``` @@ -353,7 +351,7 @@ Kick must not delete `host_profiles` and must not delete relationship history. T BDInviteAgency(target_user_id) -> target must not be active host -> target must not own active agency - -> target region must match BD region + -> Huwaa allows cross-region; other App target region must match BD region -> create role_invitation(type=agency, inviter_bd_user_id) -> target accepts -> create agency owned by target @@ -374,7 +372,7 @@ BD can invite self only when: LeaderInviteBD(target_user_id) -> inviter must be active bd_leader -> target must not be active BD - -> target region must match leader region + -> Huwaa allows cross-region; other App target region must match leader region -> create role_invitation(type=bd) -> target accepts -> create bd_profiles(role=bd, parent_leader_user_id=leader) @@ -610,7 +608,7 @@ Host/Agency/BD 的 App 可见通知统一进入 App `消息` tab 的 `system` | BD joins another Agency | BD profile remains active; host membership is separate | | BD wants own Agency after joining another Agency | Must first leave or be removed from active host membership; then self-invite can create Agency | | Agency owner wants to leave own Agency | Not allowed through normal leave; Agency close or transfer is backend ability | -| User region changes | Existing relationships remain; new search/application uses new region; historical stats use event snapshots | +| User region changes | Existing relationships remain; new search/application/invitation follows the current App policy; historical stats use event snapshots | | App earning summary and wallet balance differ | Wallet balance is authority for withdrawable amount; earning summary is business explanation | | Client retries application or invitation action | Same `command_id` returns existing result; different `command_id` must hit uniqueness guard | @@ -622,7 +620,8 @@ Host/Agency/BD 的 App 可见通知统一进入 App `消息` tab 的 `system` | Scenario | Expected | | --- | --- | -| User searches Agency | Only same-region active joinable agencies returned | +| Huwaa user searches Agency | All active joinable agencies in Huwaa are returned, including other regions | +| Other App user searches Agency | Existing country/region restriction remains in force | | User applies and Agency approves | User becomes active host and active Agency member | | Agency kicks host | Membership ends, host profile remains active | | Kicked host reapplies to another Agency | New active membership created | @@ -630,6 +629,9 @@ Host/Agency/BD 的 App 可见通知统一进入 App `消息` tab 的 `system` | BD invites self as Agency while not host | Agency created, BD also becomes host and Agency owner | | BD joins another Agency | BD remains BD and becomes host under that Agency | | BD Leader invites BD | Target gets BD profile, not host profile | +| Huwaa cross-region Agency/BD invitation is accepted | Target keeps its own region and the invited relationship is created | +| Huwaa manager creates cross-region BD Leader | Target keeps its own region and receives active BD Leader identity | +| Huwaa user lists or invites Coin Seller | Only same-region sellers or sub-seller targets are allowed | | Host works across two Agencies in one day | Stats split by relation snapshot | | App reads earning summary before backend settlement | Shows pending/unsettled state, not withdrawable money | | Same application command retried | Returns the original pending application | @@ -640,7 +642,7 @@ Host/Agency/BD 的 App 可见通知统一进入 App `消息` tab 的 `system` - Agency owner is a host, but ordinary active host cannot become Agency. - BD and host identities can coexist; BD role alone does not imply host. - BD Leader is a BD with extra invitation rights. -- Region constraints are enforced by server-side `region_id`. +- Region policy is selected by authenticated `app_code`: Huwaa only exempts Agency invitation, Host application, BD invitation and manager-created BD Leader; other App paths and all Coin Seller relations retain server-side region restrictions. - App cannot configure policies, approve salary, post wallet balance, or mutate withdrawals. - Wallet is the only owner of salary balance and withdrawal state. - All relationship changes must be auditable and idempotent. diff --git a/docs/定时任务服务架构.md b/docs/定时任务服务架构.md index feae2e68..06621625 100644 --- a/docs/定时任务服务架构.md +++ b/docs/定时任务服务架构.md @@ -152,21 +152,21 @@ tasks: timeout: "3s" lock_ttl: "30s" batch_size: 100 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] user_region_rebuild: enabled: true interval: "5s" timeout: "5s" lock_ttl: "30s" batch_size: 500 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] message_fanout: enabled: true interval: "1s" timeout: "10s" lock_ttl: "30s" batch_size: 500 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] mic_open_session_compensation: enabled: true interval: "60s" @@ -175,7 +175,7 @@ tasks: batch_size: 100 pending_publish_max_age: "2m" publishing_session_max_age: "12h" - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] ``` ## Cron Database diff --git a/docs/接口清单.md b/docs/接口清单.md index f157b13c..06a88141 100644 --- a/docs/接口清单.md +++ b/docs/接口清单.md @@ -57,7 +57,8 @@ | GET | `/api/v1/users/me/friend-requests` | users | `listMyFriendApplications` | 我的好友申请列表 | | GET | `/api/v1/users/me/friends` | users | `listMyFriends` | 我的好友列表 | | DELETE | `/api/v1/users/{user_id}/friend` | users | `deleteFriend` | 双向删除好友关系 | -| GET | `/api/v1/rooms` | rooms | `listRooms` | 房间发现列表,支持 `tab=hot/new`,卡片返回 `im_group_id` | +| GET | `/api/v1/rooms/filters` | rooms | `listRoomFilters` | Flutter 首页区域/国家筛选目录,下发可原样回传的 `region_id/country_code` | +| GET | `/api/v1/rooms` | rooms | `listRooms` | 房间发现列表;Huwaa 默认 All,支持互斥的 `region_id/country_code` 及 `tab=hot/new`,卡片返回 `im_group_id` | | GET | `/api/v1/rooms/me` | rooms | `getMyRoom` | 查询 Mine 顶部我的房间卡片 | | GET | `/api/v1/rooms/feeds` | rooms | `listRoomFeeds` | Mine 页 Visited/Friend/Following/Followed 房间流 | | GET | `/api/v1/rooms/current` | rooms | `getCurrentRoom` | 查询当前可恢复房间 | diff --git a/docs/语音房区域房间列表架构.md b/docs/语音房区域房间列表架构.md index 6ed581a7..ce2ab8c7 100644 --- a/docs/语音房区域房间列表架构.md +++ b/docs/语音房区域房间列表架构.md @@ -1,6 +1,6 @@ # Voice Room Region Room List Architecture -本文档定义 App 房间列表的区域化架构。目标是让同一区域内的国家看到同一套房间列表,不同区域看到不同列表,同时不破坏现有 `Room Cell` 单房间状态 owner 模型。 +本文档定义 App 房间列表的区域化架构。默认 App 仍按用户区域隔离;Huwaa 首页默认读取全部区域,并允许客户端使用服务端目录下发的 active `region_id` 或 enabled `country_code` 做单一筛选。这些列表范围不改变现有 `Room Cell` 单房间状态 owner 模型。 本文的区域隔离始终发生在单个 `app_code` 内。不同 App 即使使用相同国家、区域和 `room_id`,房间列表也必须互相不可见。 @@ -13,8 +13,8 @@ | App 国家/区域解析 | `user-service` | App 注册、改国家和用户投影只读 enabled 国家与 active 区域映射 | | 用户区域归属 | `user-service` | 注册和改国家后写入 `users.region_id` | | 房间可见区域 | `room-service` | 房间创建时绑定 `visible_region_id` | -| 房间列表读模型 | `room-service` | 按 `visible_region_id` 查询列表卡片 | -| HTTP 列表入口 | `gateway-service` | 鉴权后解析用户区域并调用 room-service | +| 房间列表读模型 | `room-service` | 按默认区域、All、指定区域或指定国家查询列表卡片 | +| HTTP 列表入口 | `gateway-service` | 鉴权后解析 App 策略,并用 active 区域目录校验客户筛选 | | 实时进房校验 | `room-service` | 列表只负责发现,进入房间仍以 `JoinRoom` 为准 | 本阶段不做: @@ -22,15 +22,15 @@ | Excluded | Reason | | --- | --- | | 推荐系统 | 首版先实现区域隔离和稳定排序,不做个性化推荐 | -| 跨区域混排 | 产品语义要求不同区域列表隔离 | -| 客户端提交 `region_id` | 区域必须由服务端按用户国家计算,避免伪造 | +| 非 Huwaa App 客户端提交 `region_id` | 这些 App 仍按用户国家投影的服务端区域隔离 | +| Huwaa 客户端提交任意区域/国家值 | 只接受 `/api/v1/rooms/filters` 中 active 区域和 enabled 国家的字段值 | | IP 国家决定房间列表 | `country_by_ip` 只用于审计和风控辅助,不代表用户选择国家 | | 把列表塞进 Room Cell | Room Cell 是单房间高频状态 owner,不承担多房间列表查询 | | 创建者改国家自动迁移房间 | 房间可见区域是创建时确定的业务属性,避免直播中列表突然漂移 | ## Core Rule -房间列表按 `region_id` 隔离,而不是按 `country` 隔离。 +非 Huwaa 房间列表默认按 `region_id` 隔离,而不是按 `country` 隔离。Huwaa All 会合并所有区域;普通房在置顶之后固定排成“本国家有人 → 其他国家/区域有人 → 本国家没人 → 其他国家/区域没人”。 例如: @@ -89,10 +89,10 @@ sequenceDiagram participant R as room-service participant S as MySQL/Redis - C->>G: GET /api/v1/rooms?tab=hot&limit=20 + C->>G: GET /api/v1/rooms?tab=hot&limit=20[®ion_id|country_code] G->>U: GetUser(user_id) U-->>G: region_id - G->>R: ListRooms(region_id, tab, cursor, limit) + G->>R: ListRooms(viewer_region_id, all/filter_region_id/country_code, tab, cursor, limit) R->>S: Read room_list_entries + active room_region_pins S-->>R: RoomListItem[] R-->>G: ListRoomsResponse @@ -107,11 +107,12 @@ gateway -> room-service.JoinRoom -> Tencent IM join group callback guard 因此列表允许秒级最终一致;真正能否进入房间由 `JoinRoom` 和 IM 守卫决定。 -区域置顶只影响当前 `visible_region_id` 的公共发现列表排序。`room_region_pins` 保存 `app_code + visible_region_id + room_id` 的运营置顶关系;查询时只 join `status=active` 且 `expires_at_ms > now_ms` 的记录,排序优先级为: +默认/指定区域列表只应用全区置顶、该 `visible_region_id` 的区域置顶和已选国家置顶。Huwaa All 会合并所有区域,但每个区域/国家置顶仍只能命中房间自身 `visible_region_id` 和房主国家,不会把某区置顶扩散到其他区域。`room_region_pins` 查询只使用 `status=active` 且 `expires_at_ms > now_ms` 的记录,排序优先级为: -1. 有效区域置顶在普通房间之前。 -2. 置顶房间按 `weight DESC, expires_at_ms DESC, room_id ASC`。 -3. 普通房间继续按 `hot` 的 `sort_score DESC` 或 `new` 的 `created_at_ms DESC`。 +1. 同一房间同时命中多种置顶时固定选 `global > region > country`,次级类型不能用更高 weight 反超。 +2. 有效全区/区域置顶在国家置顶和普通房间之前。 +3. 选定置顶类型后,房间按 `weight DESC, expires_at_ms DESC, room_id ASC`。 +4. 普通房间继续按本国家/在线桶及 `hot` 的 `sort_score DESC` 或 `new` 的 `created_at_ms DESC`。 置顶不进入 Room Cell、command log 或 snapshot;它是房间列表读模型的运营控制面。房间改区域后,旧区域置顶不会自动跨区域生效,后台需要在新区域重新建立置顶。 @@ -287,6 +288,8 @@ sort_score = heat * 1000 + online_count * 100 + occupied_seat_count * 10 + fresh ```text GET /api/v1/rooms?tab=hot&cursor=&limit=20 GET /api/v1/rooms?tab=new&cursor=&limit=20 +GET /api/v1/rooms?tab=hot®ion_id=2002 +GET /api/v1/rooms?tab=hot&country_code=BD ``` 响应继续使用 gateway envelope: @@ -322,6 +325,8 @@ GET /api/v1/rooms?tab=new&cursor=&limit=20 - `limit` 默认 `20`,最大 `50`。 - `cursor` 使用不透明字符串,客户端不能解析或拼装。 - gateway 从 access token 得到 `user_id`,再查 user-service 获取 `region_id`。 +- Huwaa 不传 `region_id/country_code` 表示 All;两者互斥,且只能回传 `/api/v1/rooms/filters` 的字段值。 +- 显式 `region_id` 写入不透明 cursor,不允许把 A 区游标复用到 B 区。 - 如果 user-service 查询失败,gateway 应返回错误,不应该用 IP 国家临时兜底。 - `im_group_id` 当前等于 `room_id`,只用于客户端准备腾讯 IM 房间群;真正入群必须等 `JoinRoom` 成功后由 IM 回调守卫校验 presence。 @@ -341,12 +346,16 @@ message ListRoomsRequest { string tab = 4; string cursor = 5; int32 limit = 6; + string query = 7; + string country_code = 8; + string viewer_country_code = 9; + bool all_visible_regions = 10; + int64 filter_region_id = 11; } message RoomListItem { string room_id = 1; int64 owner_user_id = 2; - int64 host_user_id = 3; string title = 4; string cover_url = 5; string mode = 6; @@ -359,6 +368,7 @@ message RoomListItem { string app_code = 13; string room_short_id = 14; bool locked = 15; + string country_code = 16; } message ListRoomsResponse { @@ -371,7 +381,7 @@ message ListRoomsResponse { - 新增 proto 字段只能追加,不能复用字段号。 - `visible_region_id` 使用 `int64`,`0` 表示 `GLOBAL`。 -- 不要把 `country` 传给 room-service 列表接口;国家到区域的映射不属于 room-service。 +- 客户端原始 `country/country_code` 不能直传 room-service;gateway 先校验 enabled 国家与 active 区域映射,再传规范化的 `country_code` 给列表读模型。 - `app_code` 只从 `RequestMeta` 来;客户端不能在列表 query/body 里自报另一个 App。 ## Write Path Updates @@ -409,8 +419,8 @@ message ListRoomsResponse { 不允许: -- 用户看到其他区域专属列表。 -- 客户端通过伪造 `region_id` 越权获取列表。 +- 非 Huwaa/无 All 权限的用户看到其他区域专属列表。 +- Huwaa 客户端传入不在 `/api/v1/rooms/filters` active 目录中的 `region_id`,或同时传 `region_id/country_code`。 - 列表查询直接访问 Room Cell 全量内存。 - Redis 成为唯一数据源。 diff --git a/pkg/xerr/catalog.go b/pkg/xerr/catalog.go index 85c3dc00..1eab22c0 100644 --- a/pkg/xerr/catalog.go +++ b/pkg/xerr/catalog.go @@ -83,6 +83,8 @@ var catalog = map[Code]Spec{ VIPLevelDisabled: spec(codes.FailedPrecondition, httpStatusConflict, VIPLevelDisabled, "vip level is disabled"), VIPDowngradeNotAllowed: spec(codes.FailedPrecondition, httpStatusConflict, VIPDowngradeNotAllowed, "vip downgrade is not allowed"), 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"), RedPacketDisabled: spec(codes.FailedPrecondition, httpStatusConflict, RedPacketDisabled, "red packet is disabled"), RedPacketInvalidAmountTier: spec(codes.InvalidArgument, httpStatusBadRequest, RedPacketInvalidAmountTier, "invalid argument"), diff --git a/pkg/xerr/errors.go b/pkg/xerr/errors.go index db2db022..f761474e 100644 --- a/pkg/xerr/errors.go +++ b/pkg/xerr/errors.go @@ -100,6 +100,10 @@ const ( VIPDowngradeNotAllowed Code = "VIP_DOWNGRADE_NOT_ALLOWED" // VIPRechargeRequired 表示目标 VIP 等级需要用户先达到累计充值门槛。 VIPRechargeRequired Code = "VIP_RECHARGE_REQUIRED" + // VIPCoinRebateNotFound 表示返现不存在,或不属于当前 App/用户。 + VIPCoinRebateNotFound Code = "VIP_COIN_REBATE_NOT_FOUND" + // VIPCoinRebateExpired 表示返现已越过 UTC 次日日切的排他结束边界。 + VIPCoinRebateExpired Code = "VIP_COIN_REBATE_EXPIRED" // RedPacketDisabled 表示红包功能未启用。 RedPacketDisabled Code = "RED_PACKET_DISABLED" diff --git a/scripts/mysql/060_configurable_vip_program.sql b/scripts/mysql/060_configurable_vip_program.sql new file mode 100644 index 00000000..36e4cf6d --- /dev/null +++ b/scripts/mysql/060_configurable_vip_program.sql @@ -0,0 +1,357 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +USE hyapp_wallet; + +-- 本迁移只建立按 App 可配置的 VIP 规则和体验卡事实;不会为 Fami 猜测价格、有效期或资源组。 +CREATE TABLE IF NOT EXISTS vip_program_configs ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', + program_type VARCHAR(32) NOT NULL COMMENT '体系类型:legacy_timed/tiered_privilege_v1', + level_count INT NOT NULL COMMENT '该 App 可配置等级数量', + same_level_expiry_policy VARCHAR(32) NOT NULL COMMENT '同级续费有效期策略:extend_remaining', + upgrade_expiry_policy VARCHAR(32) NOT NULL COMMENT '升级有效期策略:extend_remaining/replace_from_now', + downgrade_purchase_policy VARCHAR(32) NOT NULL COMMENT '降级购买策略:reject', + benefit_inheritance_policy VARCHAR(32) NOT NULL COMMENT '权益矩阵策略:当前固定 target_only,每级保存完整集合', + grant_mode VARCHAR(32) NOT NULL COMMENT '后台赠送语义:direct_membership/trial_card', + trial_card_enabled BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否允许体验卡背包和佩戴流程', + status VARCHAR(32) NOT NULL COMMENT '业务状态:active/disabled', + config_version BIGINT NOT NULL DEFAULT 1 COMMENT '配置版本;订单和会员状态持久化该快照版本', + updated_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '最后更新管理员 ID', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code), + KEY idx_vip_program_status (status, updated_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='按 App 配置的 VIP 体系规则'; + +CREATE TABLE IF NOT EXISTS vip_level_benefits ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', + level INT NOT NULL COMMENT '拥有该权益的具体 VIP 等级', + benefit_code VARCHAR(96) NOT NULL COMMENT '稳定权益编码,跨服务权限判断只使用该值', + name VARCHAR(128) NOT NULL COMMENT '权益展示名称', + benefit_type VARCHAR(32) NOT NULL COMMENT '权益类型:decoration/function', + unlock_level INT NOT NULL COMMENT 'P1 初始解锁等级,仅用于展示来源,不参与运行时继承', + status VARCHAR(32) NOT NULL COMMENT '业务状态:active/disabled', + trial_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '体验卡是否可获得;金币返现必须为 false', + resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '绑定资源 ID;0 表示尚未绑定或纯功能权益', + resource_type VARCHAR(32) NOT NULL DEFAULT '' COMMENT '绑定资源类型;空表示纯功能或待运营配置', + execution_scope VARCHAR(32) NOT NULL COMMENT '实际执行方:wallet/room/user/notice', + auto_equip BOOLEAN NOT NULL DEFAULT FALSE COMMENT '资源下发后是否自动佩戴最高等级样式', + sort_order INT NOT NULL DEFAULT 0 COMMENT '权益展示顺序', + metadata_json JSON NULL COMMENT '执行方扩展配置;初始 P1 权益不猜测参数', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, level, benefit_code), + KEY idx_vip_benefit_code (app_code, benefit_code, status, level), + KEY idx_vip_benefit_level_sort (app_code, level, status, sort_order) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 每等级完整权益矩阵'; + +-- 体验卡元数据和通用背包事实按 entitlement_id 一一对应;佩戴切换不更新卡片绝对过期时间。 +CREATE TABLE IF NOT EXISTS user_vip_trial_cards ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', + trial_card_id VARCHAR(96) NOT NULL COMMENT '体验卡实例 ID', + command_id VARCHAR(128) NOT NULL COMMENT '发卡命令幂等 ID', + request_hash VARCHAR(128) NOT NULL COMMENT '发卡请求语义哈希', + user_id BIGINT NOT NULL COMMENT '持有用户 ID', + entitlement_id VARCHAR(96) NOT NULL COMMENT '通用背包权益实例 ID,也是佩戴入口标识', + resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '可选资源 ID;0 表示直接按等级和时长发卡', + level INT NOT NULL COMMENT '体验卡 VIP 等级快照', + name VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'VIP 等级名称快照', + status VARCHAR(32) NOT NULL COMMENT '卡片业务状态:active/revoked', + duration_ms BIGINT NOT NULL COMMENT '发卡时长快照;佩戴切换不改变该值', + effective_at_ms BIGINT NOT NULL COMMENT '卡片开始计时,UTC epoch ms', + expires_at_ms BIGINT NOT NULL COMMENT '卡片绝对过期时间,UTC epoch ms', + grant_source VARCHAR(32) NOT NULL COMMENT '发放来源', + source_grant_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '通用资源发放 ID', + operator_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '发放操作人用户 ID', + reason VARCHAR(256) NOT NULL DEFAULT '' COMMENT '发放原因', + program_type VARCHAR(32) NOT NULL COMMENT '发卡时 VIP 体系快照', + config_version BIGINT NOT NULL COMMENT '发卡时 VIP 配置版本', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, trial_card_id), + UNIQUE KEY uk_vip_trial_card_command (app_code, command_id), + UNIQUE KEY uk_vip_trial_card_entitlement (app_code, entitlement_id), + KEY idx_vip_trial_card_user (app_code, user_id, status, expires_at_ms), + KEY idx_vip_trial_card_resource (app_code, resource_id, status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 体验卡背包元数据'; + +-- purchase、直接会员赠送与体验卡发放共享同一命令守卫,先串行幂等键再获取业务行锁。 +CREATE TABLE IF NOT EXISTS vip_command_locks ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', + command_id VARCHAR(128) NOT NULL COMMENT 'VIP 写命令幂等 ID', + biz_type VARCHAR(64) NOT NULL COMMENT '命令类型:vip_purchase/vip_grant/vip_trial_card_grant', + request_hash VARCHAR(128) NOT NULL COMMENT '请求语义哈希', + created_at_ms BIGINT NOT NULL COMMENT '首次命令时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '最后写入时间,UTC epoch ms', + PRIMARY KEY (app_code, command_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 写命令串行化守卫'; + +-- 旧库按列逐项补齐;所有 ALTER 都可重复执行,且默认值保持 Lalu 的历史语义。 +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_vip_memberships' AND COLUMN_NAME = 'program_type') = 0, + 'ALTER TABLE user_vip_memberships ADD COLUMN program_type VARCHAR(32) NOT NULL DEFAULT ''legacy_timed'' COMMENT ''激活时使用的 VIP 体系快照'' AFTER status', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- 历史成功命令必须在上线前进入同一守卫空间,否则升级后一段时间内仍可能走旧唯一键竞争路径。 +INSERT IGNORE INTO vip_command_locks ( + app_code, command_id, biz_type, request_hash, created_at_ms, updated_at_ms +) +SELECT app_code, command_id, biz_type, request_hash, created_at_ms, updated_at_ms +FROM wallet_transactions +WHERE biz_type IN ('vip_purchase', 'vip_grant'); + +INSERT IGNORE INTO vip_command_locks ( + app_code, command_id, biz_type, request_hash, created_at_ms, updated_at_ms +) +SELECT app_code, command_id, 'vip_trial_card_grant', request_hash, created_at_ms, updated_at_ms +FROM user_vip_trial_cards; + +-- Lalu 显式保持现状;Fami 使用替换升级、体验卡赠送和每级完整权益集合。 +INSERT IGNORE INTO vip_program_configs ( + app_code, program_type, level_count, same_level_expiry_policy, upgrade_expiry_policy, + downgrade_purchase_policy, benefit_inheritance_policy, grant_mode, trial_card_enabled, + status, config_version, updated_by_admin_id, created_at_ms, updated_at_ms +) VALUES + ('lalu', 'legacy_timed', 10, 'extend_remaining', 'extend_remaining', + 'reject', 'target_only', 'direct_membership', FALSE, 'active', 1, 0, 0, 0), + ('fami', 'tiered_privilege_v1', 9, 'extend_remaining', 'replace_from_now', + 'reject', 'target_only', 'trial_card', TRUE, 'active', 1, 0, 0, 0); + +-- Fami 等级初始均不可购买;30 天只满足配置校验,价格与资源组保持 0,须由运营确认后启用。 +INSERT IGNORE INTO vip_levels ( + app_code, level, name, status, price_coin, duration_ms, reward_resource_group_id, + required_recharge_coin_amount, sort_order, created_at_ms, updated_at_ms +) VALUES + ('fami', 1, 'VIP1', 'disabled', 0, 2592000000, 0, 0, 10, 0, 0), + ('fami', 2, 'VIP2', 'disabled', 0, 2592000000, 0, 0, 20, 0, 0), + ('fami', 3, 'VIP3', 'disabled', 0, 2592000000, 0, 0, 30, 0, 0), + ('fami', 4, 'VIP4', 'disabled', 0, 2592000000, 0, 0, 40, 0, 0), + ('fami', 5, 'VIP5', 'disabled', 0, 2592000000, 0, 0, 50, 0, 0), + ('fami', 6, 'VIP6', 'disabled', 0, 2592000000, 0, 0, 60, 0, 0), + ('fami', 7, 'VIP7', 'disabled', 0, 2592000000, 0, 0, 70, 0, 0), + ('fami', 8, 'VIP8', 'disabled', 0, 2592000000, 0, 0, 80, 0, 0), + ('fami', 9, 'VIP9', 'disabled', 0, 2592000000, 0, 0, 90, 0, 0); + +-- 每级直接持久化最终权益集合,不在运行时根据 unlock_level 自动继承。 +INSERT IGNORE INTO vip_level_benefits ( + app_code, level, benefit_code, name, benefit_type, unlock_level, status, trial_enabled, + resource_id, resource_type, execution_scope, auto_equip, sort_order, metadata_json, + created_at_ms, updated_at_ms +) +SELECT + 'fami', levels.level, benefits.benefit_code, benefits.name, benefits.benefit_type, + benefits.unlock_level, 'active', benefits.trial_enabled, 0, '', benefits.execution_scope, + benefits.auto_equip, benefits.sort_order, + CASE + WHEN benefits.benefit_code = 'online_global_notice' + THEN JSON_OBJECT('message', '欢迎进入Fami,祝你有美好的一天') + ELSE NULL + END, + 0, 0 +FROM ( + SELECT 1 AS level UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 + UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 +) AS levels +INNER JOIN ( + SELECT 'vip_badge_identity' AS benefit_code, 'VIP标识' AS name, 'function' AS benefit_type, 1 AS unlock_level, TRUE AS trial_enabled, 'user' AS execution_scope, FALSE AS auto_equip, 10 AS sort_order + UNION ALL SELECT 'vip_medal', 'VIP勋章', 'decoration', 1, TRUE, 'user', TRUE, 20 + UNION ALL SELECT 'avatar_frame', 'VIP头像框', 'decoration', 1, TRUE, 'user', TRUE, 30 + UNION ALL SELECT 'vip_title', 'VIP称号', 'function', 1, TRUE, 'user', FALSE, 40 + UNION ALL SELECT 'chat_bubble', 'VIP聊天气泡', 'decoration', 2, TRUE, 'room', TRUE, 50 + UNION ALL SELECT 'vip_gift', 'VIP礼物', 'function', 2, TRUE, 'room', FALSE, 60 + UNION ALL SELECT 'entry_effect', 'VIP进场通知', 'function', 2, TRUE, 'room', FALSE, 70 + UNION ALL SELECT 'visitor_history', '查看访客', 'function', 2, TRUE, 'user', FALSE, 80 + UNION ALL SELECT 'voice_wave', 'VIP声波纹', 'decoration', 3, TRUE, 'room', TRUE, 90 + UNION ALL SELECT 'profile_card', 'VIP资料卡皮肤', 'decoration', 3, TRUE, 'user', TRUE, 100 + UNION ALL SELECT 'custom_room_background', '自定义房间背景', 'function', 3, TRUE, 'room', FALSE, 110 + UNION ALL SELECT 'room_image_message', '房间发图', 'function', 3, TRUE, 'room', FALSE, 120 + UNION ALL SELECT 'animated_avatar', '动态头像', 'function', 4, TRUE, 'user', FALSE, 130 + UNION ALL SELECT 'animated_room_cover', '动态房间封面', 'function', 4, TRUE, 'room', FALSE, 140 + UNION ALL SELECT 'mic_skin', '麦克风皮肤', 'decoration', 4, TRUE, 'room', TRUE, 150 + UNION ALL SELECT 'room_border', '房间边框', 'decoration', 4, TRUE, 'room', TRUE, 160 + UNION ALL SELECT 'vehicle', 'VIP座驾', 'decoration', 4, TRUE, 'room', TRUE, 170 + UNION ALL SELECT 'colored_room_name', 'VIP彩色房间名称', 'function', 5, TRUE, 'room', FALSE, 180 + UNION ALL SELECT 'colored_nickname', 'VIP彩色昵称', 'function', 5, TRUE, 'user', FALSE, 190 + UNION ALL SELECT 'colored_id', 'VIP彩色ID', 'function', 5, TRUE, 'user', FALSE, 200 + UNION ALL SELECT 'gift_tray_skin', '送礼托盘皮肤', 'function', 5, TRUE, 'room', FALSE, 210 + UNION ALL SELECT 'hide_profile_data', '隐藏个人数据', 'function', 6, TRUE, 'user', FALSE, 220 + UNION ALL SELECT 'custom_avatar_frame', '定制头框', 'function', 6, TRUE, 'user', FALSE, 230 + UNION ALL SELECT 'leaderboard_invisible', '榜单隐身', 'function', 6, TRUE, 'user', FALSE, 240 + UNION ALL SELECT 'daily_coin_rebate', '金币返现', 'function', 6, FALSE, 'wallet', FALSE, 250 + UNION ALL SELECT 'custom_profile_card', '定制资料卡', 'function', 7, TRUE, 'user', FALSE, 260 + UNION ALL SELECT 'anonymous_profile_visit', '匿名访问主页', 'function', 7, TRUE, 'user', FALSE, 270 + UNION ALL SELECT 'custom_gift', '定制礼物', 'function', 7, TRUE, 'room', FALSE, 280 + UNION ALL SELECT 'room_entry_notice', '进房高亮通知', 'function', 8, TRUE, 'room', FALSE, 290 + UNION ALL SELECT 'custom_pretty_id', '定制靓号', 'function', 8, TRUE, 'user', FALSE, 300 + UNION ALL SELECT 'custom_vehicle', '定制座驾', 'function', 8, TRUE, 'room', FALSE, 310 + UNION ALL SELECT 'anti_kick', '防踢', 'function', 9, TRUE, 'room', FALSE, 320 + UNION ALL SELECT 'anti_mute', '防禁言', 'function', 9, TRUE, 'room', FALSE, 330 + UNION ALL SELECT 'online_global_notice', '上线全服通知', 'function', 9, TRUE, 'notice', FALSE, 340 +) AS benefits ON benefits.unlock_level <= levels.level; + +-- 早期执行过本迁移的环境已有权益行;只给空元数据补默认文案,不覆盖运营已配置的 App 文案。 +UPDATE vip_level_benefits +SET metadata_json = JSON_OBJECT('message', '欢迎进入Fami,祝你有美好的一天') +WHERE app_code = 'fami' + AND benefit_code = 'online_global_notice' + AND COALESCE(JSON_LENGTH(metadata_json), 0) = 0; + +-- resource_id 使用 resources 自增主键;空素材和仅含 vip_level 的 metadata 明确等待运营补齐视觉资产。 +INSERT IGNORE INTO resources ( + app_code, resource_code, resource_type, name, status, grantable, manager_grant_enabled, + grant_strategy, wallet_asset_type, wallet_asset_amount, price_type, coin_price, gift_point_amount, + usage_scope_json, asset_url, preview_url, animation_url, metadata_json, sort_order, + created_by_user_id, updated_by_user_id, created_at_ms, updated_at_ms +) VALUES + ('fami', 'vip_trial_card_1', 'vip_trial_card', 'VIP1体验卡', 'active', TRUE, TRUE, 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":1}', 10, 0, 0, 0, 0), + ('fami', 'vip_trial_card_2', 'vip_trial_card', 'VIP2体验卡', 'active', TRUE, TRUE, 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":2}', 20, 0, 0, 0, 0), + ('fami', 'vip_trial_card_3', 'vip_trial_card', 'VIP3体验卡', 'active', TRUE, TRUE, 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":3}', 30, 0, 0, 0, 0), + ('fami', 'vip_trial_card_4', 'vip_trial_card', 'VIP4体验卡', 'active', TRUE, TRUE, 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":4}', 40, 0, 0, 0, 0), + ('fami', 'vip_trial_card_5', 'vip_trial_card', 'VIP5体验卡', 'active', TRUE, TRUE, 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":5}', 50, 0, 0, 0, 0), + ('fami', 'vip_trial_card_6', 'vip_trial_card', 'VIP6体验卡', 'active', TRUE, TRUE, 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":6}', 60, 0, 0, 0, 0), + ('fami', 'vip_trial_card_7', 'vip_trial_card', 'VIP7体验卡', 'active', TRUE, TRUE, 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":7}', 70, 0, 0, 0, 0), + ('fami', 'vip_trial_card_8', 'vip_trial_card', 'VIP8体验卡', 'active', TRUE, TRUE, 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":8}', 80, 0, 0, 0, 0), + ('fami', 'vip_trial_card_9', 'vip_trial_card', 'VIP9体验卡', 'active', TRUE, TRUE, 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":9}', 90, 0, 0, 0, 0); + +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_vip_memberships' AND COLUMN_NAME = 'config_version') = 0, + 'ALTER TABLE user_vip_memberships ADD COLUMN config_version BIGINT NOT NULL DEFAULT 1 COMMENT ''激活时使用的 VIP 配置版本'' AFTER program_type', + '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 = 'vip_purchase_orders' AND COLUMN_NAME = 'previous_expires_at_ms') = 0, + 'ALTER TABLE vip_purchase_orders ADD COLUMN previous_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''购买前会员过期时间快照,UTC epoch ms'' AFTER previous_level', + '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 = 'vip_purchase_orders' AND COLUMN_NAME = 'new_expires_at_ms') = 0, + 'ALTER TABLE vip_purchase_orders ADD COLUMN new_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''购买后会员过期时间快照,UTC epoch ms'' AFTER previous_expires_at_ms', + '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 = 'vip_purchase_orders' AND COLUMN_NAME = 'duration_ms') = 0, + 'ALTER TABLE vip_purchase_orders ADD COLUMN duration_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''购买等级的有效期配置快照'' AFTER price_coin', + '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 = 'vip_purchase_orders' AND COLUMN_NAME = 'program_type') = 0, + 'ALTER TABLE vip_purchase_orders ADD COLUMN program_type VARCHAR(32) NOT NULL DEFAULT ''legacy_timed'' COMMENT ''订单执行的 VIP 体系快照'' AFTER duration_ms', + '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 = 'vip_purchase_orders' AND COLUMN_NAME = 'config_version') = 0, + 'ALTER TABLE vip_purchase_orders ADD COLUMN config_version BIGINT NOT NULL DEFAULT 1 COMMENT ''订单执行的 VIP 配置版本'' AFTER program_type', + '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 = 'vip_purchase_orders' AND COLUMN_NAME = 'expiry_policy') = 0, + 'ALTER TABLE vip_purchase_orders ADD COLUMN expiry_policy VARCHAR(32) NOT NULL DEFAULT ''extend_remaining'' COMMENT ''本单实际采用的有效期策略'' AFTER config_version', + '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_history' AND COLUMN_NAME = 'previous_expires_at_ms') = 0, + 'ALTER TABLE user_vip_history ADD COLUMN previous_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''变更前过期时间快照,UTC epoch ms'' AFTER new_level', + '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_history' AND COLUMN_NAME = 'new_expires_at_ms') = 0, + 'ALTER TABLE user_vip_history ADD COLUMN new_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''变更后过期时间快照,UTC epoch ms'' AFTER previous_expires_at_ms', + '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_history' AND COLUMN_NAME = 'program_type') = 0, + 'ALTER TABLE user_vip_history ADD COLUMN program_type VARCHAR(32) NOT NULL DEFAULT ''legacy_timed'' COMMENT ''变更使用的 VIP 体系快照'' AFTER new_expires_at_ms', + '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_history' AND COLUMN_NAME = 'config_version') = 0, + 'ALTER TABLE user_vip_history ADD COLUMN config_version BIGINT NOT NULL DEFAULT 1 COMMENT ''变更使用的 VIP 配置版本'' AFTER program_type', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- 老库 history 在上述有效期列刚增加时只能得到 0,不能据此否定存量会员的日切资格。 +-- 仅对“完全没有新格式有效期快照”的当前会员写入一条迁移基线;previous_* 保持 0 +-- 明确表示迁移不猜测基线前状态。稳定 order_id 与 NOT EXISTS 使脚本重复执行不增行, +-- 已有完整新格式 history 的用户也不会被覆盖或改写。 +SET @vip_history_baseline_ms := CAST(UNIX_TIMESTAMP(UTC_TIMESTAMP(3)) * 1000 AS UNSIGNED); + +INSERT INTO user_vip_history ( + app_code, user_id, action, previous_level, new_level, previous_expires_at_ms, + new_expires_at_ms, program_type, config_version, order_id, created_at_ms +) +SELECT + memberships.app_code, + memberships.user_id, + 'migration_baseline', + 0, + memberships.level, + 0, + memberships.expires_at_ms, + memberships.program_type, + memberships.config_version, + 'vip_configurable_060_baseline', + @vip_history_baseline_ms +FROM user_vip_memberships AS memberships +WHERE memberships.level > 0 + AND memberships.expires_at_ms > 0 + AND NOT EXISTS ( + SELECT 1 + FROM user_vip_history AS complete_history + WHERE complete_history.app_code = memberships.app_code + AND complete_history.user_id = memberships.user_id + AND complete_history.new_level > 0 + AND complete_history.new_expires_at_ms > 0 + ) + AND NOT EXISTS ( + SELECT 1 + FROM user_vip_history AS existing_baseline + WHERE existing_baseline.app_code = memberships.app_code + AND existing_baseline.user_id = memberships.user_id + AND existing_baseline.order_id = 'vip_configurable_060_baseline' + ); diff --git a/scripts/mysql/061_vip_daily_coin_rebate.sql b/scripts/mysql/061_vip_daily_coin_rebate.sql new file mode 100644 index 00000000..810f820c --- /dev/null +++ b/scripts/mysql/061_vip_daily_coin_rebate.sql @@ -0,0 +1,75 @@ +-- VIP 每日金币返现由 wallet-service 独占:日 run 固化 UTC 日切金额矩阵,用户返现行保存资格、窗口和领取交易。 +-- 本迁移可重复执行;不猜测任一等级金额,历史空配置会安全关闭,等待运营填 metadata_json.coin_amount 后再启用。 + +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +USE hyapp_wallet; + +CREATE TABLE IF NOT EXISTS vip_daily_coin_rebate_runs ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', + task_day CHAR(10) NOT NULL COMMENT 'UTC 日期,YYYY-MM-DD', + run_id VARCHAR(96) NOT NULL COMMENT '稳定批任务 ID', + day_start_ms BIGINT NOT NULL COMMENT 'UTC 当日开始,epoch ms', + day_end_ms BIGINT NOT NULL COMMENT 'UTC 次日开始,排他结束 epoch ms', + config_version BIGINT NOT NULL COMMENT '创建 run 时 VIP 配置版本', + level_amounts_json JSON NOT NULL COMMENT '等级到返现金额的不可变快照', + status VARCHAR(32) NOT NULL COMMENT 'running/completed', + last_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '已扫描会员游标', + scanned_count BIGINT NOT NULL DEFAULT 0 COMMENT '累计扫描会员数', + created_count BIGINT NOT NULL DEFAULT 0 COMMENT '累计创建返现数', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + completed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '完成时间,UTC epoch ms', + PRIMARY KEY (app_code, task_day), + UNIQUE KEY uk_vip_rebate_run_id (app_code, run_id), + KEY idx_vip_rebate_run_status (app_code, status, task_day) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 每日金币返现运行快照'; + +CREATE TABLE IF NOT EXISTS vip_daily_coin_rebates ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', + rebate_id VARCHAR(96) NOT NULL COMMENT '返现事实 ID', + run_id VARCHAR(96) NOT NULL COMMENT '来源日 run ID', + task_day CHAR(10) NOT NULL COMMENT 'UTC 日期,YYYY-MM-DD', + user_id BIGINT NOT NULL COMMENT '领取用户 ID', + vip_level INT NOT NULL COMMENT 'UTC 日切时付费 VIP 等级快照', + vip_name VARCHAR(64) NOT NULL COMMENT 'VIP 名称快照', + coin_amount BIGINT NOT NULL COMMENT '返现金币正整数快照', + status VARCHAR(32) NOT NULL COMMENT 'claimable/claimed;expired 由查询层投影', + available_at_ms BIGINT NOT NULL COMMENT '领取开始,UTC epoch ms', + expires_at_ms BIGINT NOT NULL COMMENT '领取排他结束,UTC epoch ms', + config_version BIGINT NOT NULL COMMENT '来源 run 的 VIP 配置版本', + claimed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '实际领取时间,UTC epoch ms', + wallet_transaction_id VARCHAR(96) NOT NULL DEFAULT '' 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, rebate_id), + UNIQUE KEY uk_vip_rebate_user_day (app_code, task_day, user_id), + KEY idx_vip_rebate_user_day (app_code, user_id, task_day, rebate_id), + KEY idx_vip_rebate_expiry (app_code, status, expires_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 每日金币返现领取事实'; + +UPDATE vip_level_benefits +SET status = 'disabled', trial_enabled = FALSE +WHERE benefit_code = 'daily_coin_rebate' + AND ( + JSON_EXTRACT(metadata_json, '$.coin_amount') IS NULL + OR JSON_TYPE(JSON_EXTRACT(metadata_json, '$.coin_amount')) <> 'INTEGER' + OR CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.coin_amount')) AS DECIMAL(65, 0)) <= 0 + OR CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.coin_amount')) AS DECIMAL(65, 0)) > 9223372036854775807 + ); + +UPDATE vip_level_benefits +SET trial_enabled = FALSE, execution_scope = 'wallet' +WHERE benefit_code = 'daily_coin_rebate'; + +UPDATE vip_level_benefits +SET execution_scope = 'notice' +WHERE benefit_code = 'online_global_notice'; + +-- 已经先上线过领取交易的环境补齐统一 VIP command guard;同 command 不能再被购买、发卡或另一返现复用。 +INSERT IGNORE INTO vip_command_locks ( + app_code, command_id, biz_type, request_hash, created_at_ms, updated_at_ms +) +SELECT app_code, command_id, biz_type, request_hash, created_at_ms, updated_at_ms +FROM wallet_transactions +WHERE biz_type = 'vip_daily_coin_rebate'; diff --git a/scripts/mysql/062_vip_user_settings.sql b/scripts/mysql/062_vip_user_settings.sql new file mode 100644 index 00000000..7b5f77d5 --- /dev/null +++ b/scripts/mysql/062_vip_user_settings.sql @@ -0,0 +1,15 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +USE hyapp_wallet; + +-- 用户级通知开关只保存偏好,不改变 VIP 资格或 effective_benefits;历史用户不批量补行, +-- 查询无记录时由 wallet-service 统一返回默认开启。 +CREATE TABLE IF NOT EXISTS user_vip_settings ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', + 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 '是否开启上线全服通知', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, user_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户按 App 隔离的 VIP 功能开关'; diff --git a/server/admin/cmd/server/main.go b/server/admin/cmd/server/main.go index 2999bc0b..0ba0bc13 100644 --- a/server/admin/cmd/server/main.go +++ b/server/admin/cmd/server/main.go @@ -276,11 +276,23 @@ func main() { auth := service.NewAuthService(cfg.JWTSecret, cfg.AccessTokenTTL) auditHandler := auditmodule.New(store) countryRegionHandler := countryregionmodule.New(userclient.NewGRPC(userConn), userDB, store, roomClient, cfg, auditHandler) + appUserHandler := appusermodule.New( + userclient.NewGRPC(userConn), + activityclient.NewGRPC(activityConn), + sqlDB, + userDB, + walletDB, + cfg, + auditHandler, + appusermodule.WithWalletClient(walletclient.NewGRPC(walletConn)), + appusermodule.WithExportJobs(store, cfg), + ) var runner *jobrunner.Runner var jobStatus healthmodule.JobStatusProvider if cfg.Jobs.Enabled { runner = jobrunner.NewRunner(store, redisClient, cfg, jobrunner.WithHandler(countryregionmodule.CountryCodeRenameJobType, countryRegionHandler.Service().HandleCountryCodeRenameJob), + jobrunner.WithArtifactHandler(appusermodule.AppUserExportJobType, appUserHandler.HandleExportJob), ) runner.Start() defer runner.Close() @@ -345,7 +357,7 @@ func main() { AchievementConfig: achievementconfigmodule.New(activityclient.NewGRPC(activityConn), auditHandler), AppConfig: appconfigmodule.New(store, auditHandler), AppRegistry: appregistrymodule.New(userDB), - AppUser: appusermodule.New(userclient.NewGRPC(userConn), activityclient.NewGRPC(activityConn), sqlDB, userDB, walletDB, cfg, auditHandler), + AppUser: appUserHandler, CoinLedger: coinledgermodule.New(userDB, walletDB, sqlDB, walletclient.NewGRPC(walletConn), auditHandler), CountryRegion: countryRegionHandler, CPRelation: cprelationmodule.NewWithActivity(userDB, activityclient.NewGRPC(activityConn), auditHandler), diff --git a/server/admin/docs/权限管理.md b/server/admin/docs/权限管理.md index 376b4dbd..346448b7 100644 --- a/server/admin/docs/权限管理.md +++ b/server/admin/docs/权限管理.md @@ -217,6 +217,8 @@ | 权限码 | kind | 控制范围 | | --- | --- | --- | | `app-user:view` | `menu` | App 用户列表、详情 | +| `app-user:level` | `button` | 临时调整 App 用户富豪/魅力等级 | +| `app-user:export` | `button` | 按当前筛选条件异步导出 App 用户 | | `app-user:update` | `button` | 修改用户资料 | | `app-user:status` | `button` | 后台封禁、解封 | | `app-user:password` | `button` | 后台设置 App 用户密码 | diff --git a/server/admin/internal/cache/redis.go b/server/admin/internal/cache/redis.go index 49e2180e..94614641 100644 --- a/server/admin/internal/cache/redis.go +++ b/server/admin/internal/cache/redis.go @@ -70,6 +70,24 @@ return 0` }, nil } +// RefreshLock 只延长仍由当前 owner 持有的锁;任务 worker 续租 DB lease 时同步续租 Redis, +// 防止大导出超过初始 TTL 后被另一实例重复执行并覆盖产物。 +func (r *Redis) RefreshLock(ctx context.Context, key string, owner string, ttl time.Duration) (bool, error) { + if r == nil || r.client == nil { + return true, nil + } + if strings.TrimSpace(owner) == "" || ttl <= 0 { + return false, errors.New("lock owner and positive ttl are required") + } + const script = ` +if redis.call("GET", KEYS[1]) == ARGV[1] then + return redis.call("PEXPIRE", KEYS[1], ARGV[2]) +end +return 0` + result, err := r.client.Eval(ctx, script, []string{r.key(key)}, owner, ttl.Milliseconds()).Int64() + return result == 1, err +} + func (r *Redis) key(key string) string { if r.prefix == "" { return key diff --git a/server/admin/internal/integration/activityclient/client.go b/server/admin/internal/integration/activityclient/client.go index a36cc2f6..632cad45 100644 --- a/server/admin/internal/integration/activityclient/client.go +++ b/server/admin/internal/integration/activityclient/client.go @@ -324,6 +324,16 @@ func (c *GRPCClient) SetUserLevel(ctx context.Context, req *activityv1.SetUserLe return c.levelClient.SetUserLevel(ctx, req) } +// BatchGetUserLevelAdminProfiles 读取真实成长账户与有效 overlay,避免 admin-server 复制等级计算规则。 +func (c *GRPCClient) BatchGetUserLevelAdminProfiles(ctx context.Context, req *activityv1.BatchGetUserLevelAdminProfilesRequest) (*activityv1.BatchGetUserLevelAdminProfilesResponse, error) { + return c.growthClient.BatchGetUserLevelAdminProfiles(ctx, req) +} + +// AdjustTemporaryUserLevels 把财富和魅力两条轨道一次交给 activity-service 原子提交。 +func (c *GRPCClient) AdjustTemporaryUserLevels(ctx context.Context, req *activityv1.AdjustTemporaryUserLevelsRequest) (*activityv1.AdjustTemporaryUserLevelsResponse, error) { + return c.growthClient.AdjustTemporaryUserLevels(ctx, req) +} + func (c *GRPCClient) CreateInboxMessage(ctx context.Context, req *activityv1.CreateInboxMessageRequest) (*activityv1.CreateInboxMessageResponse, error) { return c.messageClient.CreateInboxMessage(ctx, req) } diff --git a/server/admin/internal/integration/userclient/client.go b/server/admin/internal/integration/userclient/client.go index d49c4b9d..9f651484 100644 --- a/server/admin/internal/integration/userclient/client.go +++ b/server/admin/internal/integration/userclient/client.go @@ -379,6 +379,19 @@ func (c *GRPCClient) SetUserStatus(ctx context.Context, req SetUserStatusRequest }, nil } +// BatchGetUserAdminProfiles 汇总 user-service owner 的生日、注册设备、成功登录、身份和有效封禁事实。 +func (c *GRPCClient) BatchGetUserAdminProfiles(ctx context.Context, req *userv1.BatchGetUserAdminProfilesRequest) (*userv1.BatchGetUserAdminProfilesResponse, error) { + return c.client.BatchGetUserAdminProfiles(ctx, req) +} + +func (c *GRPCClient) AdminBanUser(ctx context.Context, req *userv1.AdminBanUserRequest) (*userv1.AdminBanUserResponse, error) { + return c.client.AdminBanUser(ctx, req) +} + +func (c *GRPCClient) AdminUnbanUser(ctx context.Context, req *userv1.AdminUnbanUserRequest) (*userv1.AdminUnbanUserResponse, error) { + return c.client.AdminUnbanUser(ctx, req) +} + func userStatusToProto(status string) userv1.UserStatus { switch status { case "active": diff --git a/server/admin/internal/integration/walletclient/client.go b/server/admin/internal/integration/walletclient/client.go index b78ff76e..bbb5bb10 100644 --- a/server/admin/internal/integration/walletclient/client.go +++ b/server/admin/internal/integration/walletclient/client.go @@ -45,6 +45,7 @@ type Client interface { ReleaseSalaryWithdrawal(ctx context.Context, req *walletv1.ReleaseSalaryWithdrawalRequest) (*walletv1.ReleaseSalaryWithdrawalResponse, error) ListRechargeBills(ctx context.Context, req *walletv1.ListRechargeBillsRequest) (*walletv1.ListRechargeBillsResponse, error) GetRechargeBillSummary(ctx context.Context, req *walletv1.GetRechargeBillSummaryRequest) (*walletv1.GetRechargeBillSummaryResponse, error) + BatchGetUserRechargeStats(ctx context.Context, req *walletv1.BatchGetUserRechargeStatsRequest) (*walletv1.BatchGetUserRechargeStatsResponse, error) GetRechargeBillOverview(ctx context.Context, req *walletv1.GetRechargeBillOverviewRequest) (*walletv1.GetRechargeBillOverviewResponse, error) RefreshGooglePaymentPrices(ctx context.Context, req *walletv1.RefreshGooglePaymentPricesRequest) (*walletv1.RefreshGooglePaymentPricesResponse, error) ListThirdPartyPaymentChannels(ctx context.Context, req *walletv1.ListThirdPartyPaymentChannelsRequest) (*walletv1.ListThirdPartyPaymentChannelsResponse, error) @@ -59,9 +60,12 @@ type Client interface { CreateRechargeProduct(ctx context.Context, req *walletv1.CreateRechargeProductRequest) (*walletv1.RechargeProductResponse, error) UpdateRechargeProduct(ctx context.Context, req *walletv1.UpdateRechargeProductRequest) (*walletv1.RechargeProductResponse, error) DeleteRechargeProduct(ctx context.Context, req *walletv1.DeleteRechargeProductRequest) (*walletv1.DeleteRechargeProductResponse, error) + GetVipProgramConfig(ctx context.Context, req *walletv1.GetVipProgramConfigRequest) (*walletv1.GetVipProgramConfigResponse, error) + UpdateAdminVipProgramConfig(ctx context.Context, req *walletv1.UpdateAdminVipProgramConfigRequest) (*walletv1.UpdateAdminVipProgramConfigResponse, error) ListAdminVipLevels(ctx context.Context, req *walletv1.ListAdminVipLevelsRequest) (*walletv1.ListAdminVipLevelsResponse, error) UpdateAdminVipLevels(ctx context.Context, req *walletv1.UpdateAdminVipLevelsRequest) (*walletv1.UpdateAdminVipLevelsResponse, error) GrantVip(ctx context.Context, req *walletv1.GrantVipRequest) (*walletv1.GrantVipResponse, error) + GrantVipTrialCard(ctx context.Context, req *walletv1.GrantVipTrialCardRequest) (*walletv1.GrantVipTrialCardResponse, error) GetRedPacketConfig(ctx context.Context, req *walletv1.GetRedPacketConfigRequest) (*walletv1.GetRedPacketConfigResponse, error) UpdateRedPacketConfig(ctx context.Context, req *walletv1.UpdateRedPacketConfigRequest) (*walletv1.UpdateRedPacketConfigResponse, error) ListRedPackets(ctx context.Context, req *walletv1.ListRedPacketsRequest) (*walletv1.ListRedPacketsResponse, error) @@ -225,6 +229,10 @@ func (c *GRPCClient) GetRechargeBillSummary(ctx context.Context, req *walletv1.G return c.client.GetRechargeBillSummary(ctx, req) } +func (c *GRPCClient) BatchGetUserRechargeStats(ctx context.Context, req *walletv1.BatchGetUserRechargeStatsRequest) (*walletv1.BatchGetUserRechargeStatsResponse, error) { + return c.client.BatchGetUserRechargeStats(ctx, req) +} + func (c *GRPCClient) GetRechargeBillOverview(ctx context.Context, req *walletv1.GetRechargeBillOverviewRequest) (*walletv1.GetRechargeBillOverviewResponse, error) { return c.client.GetRechargeBillOverview(ctx, req) } @@ -281,6 +289,14 @@ func (c *GRPCClient) DeleteRechargeProduct(ctx context.Context, req *walletv1.De return c.client.DeleteRechargeProduct(ctx, req) } +func (c *GRPCClient) GetVipProgramConfig(ctx context.Context, req *walletv1.GetVipProgramConfigRequest) (*walletv1.GetVipProgramConfigResponse, error) { + return c.client.GetVipProgramConfig(ctx, req) +} + +func (c *GRPCClient) UpdateAdminVipProgramConfig(ctx context.Context, req *walletv1.UpdateAdminVipProgramConfigRequest) (*walletv1.UpdateAdminVipProgramConfigResponse, error) { + return c.client.UpdateAdminVipProgramConfig(ctx, req) +} + func (c *GRPCClient) ListAdminVipLevels(ctx context.Context, req *walletv1.ListAdminVipLevelsRequest) (*walletv1.ListAdminVipLevelsResponse, error) { return c.client.ListAdminVipLevels(ctx, req) } @@ -293,6 +309,10 @@ func (c *GRPCClient) GrantVip(ctx context.Context, req *walletv1.GrantVipRequest return c.client.GrantVip(ctx, req) } +func (c *GRPCClient) GrantVipTrialCard(ctx context.Context, req *walletv1.GrantVipTrialCardRequest) (*walletv1.GrantVipTrialCardResponse, error) { + return c.client.GrantVipTrialCard(ctx, req) +} + func (c *GRPCClient) GetRedPacketConfig(ctx context.Context, req *walletv1.GetRedPacketConfigRequest) (*walletv1.GetRedPacketConfigResponse, error) { return c.client.GetRedPacketConfig(ctx, req) } diff --git a/server/admin/internal/job/runner.go b/server/admin/internal/job/runner.go index 52dde471..fe60e205 100644 --- a/server/admin/internal/job/runner.go +++ b/server/admin/internal/job/runner.go @@ -26,29 +26,35 @@ const userExportJobType = "user-export" type HandlerFunc func(ctx context.Context, job *model.AdminJob) (string, error) +// ArtifactHandlerFunc 供需要生成可下载文件的业务任务使用;artifactPath 必须位于 runner 配置的导出目录内。 +type ArtifactHandlerFunc func(ctx context.Context, job *model.AdminJob) (resultJSON string, artifactPath string, err error) + type Option func(*Runner) type Store interface { LeaseNextJob(workerID string, lease time.Duration, maxAttempts int) (*model.AdminJob, error) - CompleteJobWithArtifact(id uint, resultJSON string, artifactPath string) error - FailJobAttempt(id uint, message string) error - ReleaseJobLease(id uint) error + RenewJobLease(id uint, workerID string, lease time.Duration) error + CompleteJobWithArtifact(id uint, workerID string, resultJSON string, artifactPath string) error + FailJobAttempt(id uint, workerID string, message string) error + ReleaseJobLease(id uint, workerID string) error ExportUsers(options repository.ListOptions) ([]model.User, error) } type Locker interface { TryLock(ctx context.Context, key string, owner string, ttl time.Duration) (bool, cache.UnlockFunc, error) + RefreshLock(ctx context.Context, key string, owner string, ttl time.Duration) (bool, error) } type Runner struct { - artifactDir string - interval time.Duration - leaseTTL time.Duration - locker Locker - handlers map[string]HandlerFunc - maxAttempts int - store Store - workerID string + artifactDir string + interval time.Duration + leaseTTL time.Duration + locker Locker + handlers map[string]HandlerFunc + artifactHandlers map[string]ArtifactHandlerFunc + maxAttempts int + store Store + workerID string closeOnce sync.Once done chan struct{} @@ -65,6 +71,17 @@ func WithHandler(jobType string, handler HandlerFunc) Option { } } +// WithArtifactHandler 注册带文件产物的任务,避免业务模块绕过统一 job lease、重试和下载校验。 +func WithArtifactHandler(jobType string, handler ArtifactHandlerFunc) Option { + return func(r *Runner) { + jobType = strings.TrimSpace(jobType) + if jobType == "" || handler == nil { + return + } + r.artifactHandlers[jobType] = handler + } +} + func NewRunner(store Store, locker Locker, cfg config.Config, opts ...Option) *Runner { interval := cfg.Jobs.WorkerInterval if interval <= 0 { @@ -87,16 +104,17 @@ func NewRunner(store Store, locker Locker, cfg config.Config, opts ...Option) *R workerID = "admin-job-worker" } runner := &Runner{ - artifactDir: artifactDir, - interval: interval, - leaseTTL: leaseTTL, - locker: locker, - handlers: make(map[string]HandlerFunc), - maxAttempts: maxAttempts, - store: store, - workerID: workerID, - done: make(chan struct{}), - stop: make(chan struct{}), + artifactDir: artifactDir, + interval: interval, + leaseTTL: leaseTTL, + locker: locker, + handlers: make(map[string]HandlerFunc), + artifactHandlers: make(map[string]ArtifactHandlerFunc), + maxAttempts: maxAttempts, + store: store, + workerID: workerID, + done: make(chan struct{}), + stop: make(chan struct{}), } for _, opt := range opts { if opt != nil { @@ -156,19 +174,69 @@ func (r *Runner) runOnce(ctx context.Context) { locked, unlock, err := r.lock(ctx, job) if err != nil { slog.Error("job_lock_failed", "worker_id", r.workerID, "job_id", job.ID, "error", err.Error()) - _ = r.store.ReleaseJobLease(job.ID) + _ = r.store.ReleaseJobLease(job.ID, r.workerID) return } if !locked { - _ = r.store.ReleaseJobLease(job.ID) + _ = r.store.ReleaseJobLease(job.ID, r.workerID) return } - err = r.handle(ctx, job) + err = r.handleWithHeartbeat(ctx, job) if unlock != nil { _ = unlock(ctx) } if err != nil { - _ = r.store.FailJobAttempt(job.ID, err.Error()) + _ = r.store.FailJobAttempt(job.ID, r.workerID, err.Error()) + } + } +} + +func (r *Runner) handleWithHeartbeat(ctx context.Context, job *model.AdminJob) error { + jobCtx, cancel := context.WithCancel(ctx) + defer cancel() + heartbeatResult := make(chan error, 1) + go r.heartbeat(jobCtx, cancel, job, heartbeatResult) + + handleErr := r.handle(jobCtx, job) + cancel() + heartbeatErr := <-heartbeatResult + if handleErr != nil { + return handleErr + } + return heartbeatErr +} + +func (r *Runner) heartbeat(ctx context.Context, cancel context.CancelFunc, job *model.AdminJob, result chan<- error) { + interval := r.leaseTTL / 3 + if interval < 100*time.Millisecond { + interval = 100 * time.Millisecond + } + ticker := time.NewTicker(interval) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + result <- nil + return + case <-ticker.C: + if err := r.store.RenewJobLease(job.ID, r.workerID, r.leaseTTL); err != nil { + cancel() + result <- fmt.Errorf("renew job lease: %w", err) + return + } + if r.locker != nil { + refreshed, err := r.locker.RefreshLock(ctx, fmt.Sprintf("jobs:%d", job.ID), r.workerID, r.leaseTTL) + if err != nil { + cancel() + result <- fmt.Errorf("refresh job lock: %w", err) + return + } + if !refreshed { + cancel() + result <- errors.New("job distributed lock is no longer owned by worker") + return + } + } } } } @@ -178,6 +246,13 @@ func (r *Runner) handle(ctx context.Context, job *model.AdminJob) error { case userExportJobType: return r.exportAdminUsers(ctx, job) default: + if handler := r.artifactHandlers[strings.TrimSpace(job.Type)]; handler != nil { + resultJSON, artifactPath, err := handler(ctx, job) + if err != nil { + return err + } + return r.store.CompleteJobWithArtifact(job.ID, r.workerID, resultJSON, artifactPath) + } handler := r.handlers[strings.TrimSpace(job.Type)] if handler == nil { return fmt.Errorf("unsupported job type: %s", job.Type) @@ -186,7 +261,7 @@ func (r *Runner) handle(ctx context.Context, job *model.AdminJob) error { if err != nil { return err } - return r.store.CompleteJobWithArtifact(job.ID, resultJSON, "") + return r.store.CompleteJobWithArtifact(job.ID, r.workerID, resultJSON, "") } } @@ -212,7 +287,7 @@ func (r *Runner) exportAdminUsers(_ context.Context, job *model.AdminJob) error if err != nil { return err } - return r.store.CompleteJobWithArtifact(job.ID, string(result), artifactPath) + return r.store.CompleteJobWithArtifact(job.ID, r.workerID, string(result), artifactPath) } func (r *Runner) lock(ctx context.Context, job *model.AdminJob) (bool, cache.UnlockFunc, error) { diff --git a/server/admin/internal/job/runner_test.go b/server/admin/internal/job/runner_test.go new file mode 100644 index 00000000..4c279f87 --- /dev/null +++ b/server/admin/internal/job/runner_test.go @@ -0,0 +1,115 @@ +package job + +import ( + "context" + "errors" + "sync" + "testing" + "time" + + "hyapp-admin-server/internal/cache" + "hyapp-admin-server/internal/config" + "hyapp-admin-server/internal/model" + "hyapp-admin-server/internal/repository" +) + +func TestArtifactJobRenewsDatabaseAndDistributedLeases(t *testing.T) { + store := &heartbeatStore{} + locker := &heartbeatLocker{} + runner := NewRunner(store, locker, config.Config{ + NodeID: "worker-heartbeat", + Jobs: config.JobsConfig{LeaseTTL: 150 * time.Millisecond}, + }, WithArtifactHandler("slow-export", func(ctx context.Context, _ *model.AdminJob) (string, string, error) { + select { + case <-ctx.Done(): + return "", "", ctx.Err() + case <-time.After(350 * time.Millisecond): + return `{"rows":1}`, "slow.csv", nil + } + })) + + if err := runner.handleWithHeartbeat(context.Background(), &model.AdminJob{ID: 91, Type: "slow-export"}); err != nil { + t.Fatalf("slow artifact handler failed: %v", err) + } + store.mu.Lock() + renews, completes, completedBy := store.renews, store.completes, store.completedBy + store.mu.Unlock() + locker.mu.Lock() + refreshes := locker.refreshes + locker.mu.Unlock() + if renews < 2 || refreshes < 2 || completes != 1 || completedBy != "worker-heartbeat" { + t.Fatalf("long job lease was not kept alive: renews=%d refreshes=%d completes=%d worker=%q", renews, refreshes, completes, completedBy) + } +} + +func TestArtifactJobCancelsWhenDistributedLeaseIsLost(t *testing.T) { + store := &heartbeatStore{} + locker := &heartbeatLocker{loseOnRefresh: true} + runner := NewRunner(store, locker, config.Config{ + NodeID: "worker-lost-lock", + Jobs: config.JobsConfig{LeaseTTL: 150 * time.Millisecond}, + }, WithArtifactHandler("blocked-export", func(ctx context.Context, _ *model.AdminJob) (string, string, error) { + <-ctx.Done() + return "", "", ctx.Err() + })) + + err := runner.handleWithHeartbeat(context.Background(), &model.AdminJob{ID: 92, Type: "blocked-export"}) + if !errors.Is(err, context.Canceled) { + t.Fatalf("lost distributed lock must cancel handler, err=%v", err) + } + store.mu.Lock() + completes := store.completes + store.mu.Unlock() + if completes != 0 { + t.Fatalf("worker that lost its lease must not complete the job: completes=%d", completes) + } +} + +type heartbeatStore struct { + mu sync.Mutex + renews int + completes int + completedBy string +} + +func (s *heartbeatStore) LeaseNextJob(string, time.Duration, int) (*model.AdminJob, error) { + return nil, errors.New("not used") +} + +func (s *heartbeatStore) RenewJobLease(_ uint, _ string, _ time.Duration) error { + s.mu.Lock() + s.renews++ + s.mu.Unlock() + return nil +} + +func (s *heartbeatStore) CompleteJobWithArtifact(_ uint, workerID string, _, _ string) error { + s.mu.Lock() + s.completes++ + s.completedBy = workerID + s.mu.Unlock() + return nil +} + +func (s *heartbeatStore) FailJobAttempt(uint, string, string) error { return nil } +func (s *heartbeatStore) ReleaseJobLease(uint, string) error { return nil } +func (s *heartbeatStore) ExportUsers(repository.ListOptions) ([]model.User, error) { + return nil, nil +} + +type heartbeatLocker struct { + mu sync.Mutex + refreshes int + loseOnRefresh bool +} + +func (l *heartbeatLocker) TryLock(context.Context, string, string, time.Duration) (bool, cache.UnlockFunc, error) { + return true, func(context.Context) error { return nil }, nil +} + +func (l *heartbeatLocker) RefreshLock(context.Context, string, string, time.Duration) (bool, error) { + l.mu.Lock() + defer l.mu.Unlock() + l.refreshes++ + return !l.loseOnRefresh, nil +} diff --git a/server/admin/internal/modules/appuser/export.go b/server/admin/internal/modules/appuser/export.go new file mode 100644 index 00000000..24def26a --- /dev/null +++ b/server/admin/internal/modules/appuser/export.go @@ -0,0 +1,271 @@ +package appuser + +import ( + "context" + "encoding/csv" + "encoding/json" + "errors" + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + + "hyapp-admin-server/internal/appctx" + "hyapp-admin-server/internal/model" + "hyapp-admin-server/internal/modules/shared" + "hyapp-admin-server/internal/response" + + "github.com/gin-gonic/gin" +) + +const AppUserExportJobType = "app-user-export" + +type appUserExportJobStore interface { + CreateJob(job *model.AdminJob) error +} + +type appUserExportPayload struct { + AppCode string `json:"appCode"` + Query listQuery `json:"query"` +} + +type appUserExportJobResponse struct { + JobID uint `json:"jobId"` + Status string `json:"status"` + SnapshotAtMs int64 `json:"snapshotAtMs"` +} + +type appUserExportResult struct { + JobID uint `json:"jobId"` + Rows int64 `json:"rows"` + Artifact string `json:"artifact"` + DownloadPath string `json:"downloadPath"` + SnapshotAtMs int64 `json:"snapshotAtMs"` +} + +func (s *Service) CreateExportJob(ctx context.Context, actor shared.Actor, query listQuery) (*appUserExportJobResponse, error) { + if s.jobStore == nil || !s.jobsConfig.Enabled { + return nil, errors.New("admin jobs are not enabled") + } + query = normalizeListQuery(query) + query = stableAppUserExportQuery(query) + query.Page = 1 + query.PageSize = 100 + query.SnapshotAtMs = nowMillis() + payload := appUserExportPayload{ + AppCode: appctx.FromContext(ctx), + Query: query, + } + body, err := json.Marshal(payload) + if err != nil { + return nil, err + } + job := model.AdminJob{ + Type: AppUserExportJobType, + Status: model.JobStatusPending, + PayloadJSON: string(body), + MaxAttempts: s.jobsConfig.MaxAttempts, + CreatedBy: actor.UserID, + CreatedByName: strings.TrimSpace(actor.Username), + } + if job.MaxAttempts <= 0 { + job.MaxAttempts = 3 + } + if err := s.jobStore.CreateJob(&job); err != nil { + return nil, err + } + return &appUserExportJobResponse{JobID: job.ID, Status: job.Status, SnapshotAtMs: query.SnapshotAtMs}, nil +} + +// HandleExportJob 使用创建任务时固化的 App 与筛选条件逐页读取;任务执行期间不会重新解释前端 query。 +func (s *Service) HandleExportJob(ctx context.Context, job *model.AdminJob) (string, string, error) { + if job == nil || job.ID == 0 { + return "", "", errors.New("job is required") + } + var payload appUserExportPayload + if err := json.Unmarshal([]byte(job.PayloadJSON), &payload); err != nil { + return "", "", err + } + payload.AppCode = strings.TrimSpace(payload.AppCode) + payload.Query = normalizeListQuery(payload.Query) + payload.Query = stableAppUserExportQuery(payload.Query) + if payload.AppCode == "" || payload.Query.SnapshotAtMs <= 0 { + return "", "", ErrInvalidArgument + } + + artifactDir := strings.TrimSpace(s.jobsConfig.ArtifactDir) + if artifactDir == "" { + artifactDir = "storage/exports" + } + if err := os.MkdirAll(artifactDir, 0o750); err != nil { + return "", "", err + } + file, err := os.CreateTemp(artifactDir, fmt.Sprintf("app-user-export-%d-*.csv", job.ID)) + if err != nil { + return "", "", err + } + artifactName := filepath.Base(file.Name()) + succeeded := false + defer func() { + _ = file.Close() + if !succeeded { + _ = os.Remove(file.Name()) + } + }() + + // UTF-8 BOM 让运营直接使用 Excel 打开中文昵称、国家和身份时不出现乱码。 + if _, err := file.WriteString("\xEF\xBB\xBF"); err != nil { + return "", "", err + } + writer := csv.NewWriter(file) + if err := writer.Write(appUserExportHeaders()); err != nil { + return "", "", err + } + + exportCtx := appctx.WithContext(ctx, payload.AppCode) + query := payload.Query + query.Page = 1 + query.PageSize = 100 + var exported int64 + for { + items, _, err := s.ListUsers(exportCtx, query) + if err != nil { + return "", "", err + } + for i := range items { + if err := writer.Write(appUserExportRow(items[i])); err != nil { + return "", "", err + } + } + exported += int64(len(items)) + if len(items) < query.PageSize { + break + } + last := items[len(items)-1] + cursorUserID, err := strconv.ParseInt(last.UserID, 10, 64) + if err != nil || cursorUserID <= 0 || last.CreatedAtMs <= 0 { + return "", "", errors.New("app user export cursor is invalid") + } + // 使用 (created_at_ms,user_id) keyset 而不是 OFFSET;任务运行期间新增用户或已读用户变更筛选字段时, + // 后续批次仍不会位移、重复或跳过尚未读取的稳定主键区间。 + query.ExportCursorCreatedAtMs = last.CreatedAtMs + query.ExportCursorUserID = cursorUserID + } + writer.Flush() + if err := writer.Error(); err != nil { + return "", "", err + } + if err := file.Sync(); err != nil { + return "", "", err + } + if err := file.Close(); err != nil { + return "", "", err + } + succeeded = true + + result := appUserExportResult{ + JobID: job.ID, + Rows: exported, + Artifact: artifactName, + DownloadPath: fmt.Sprintf("/api/v1/jobs/%d/artifact", job.ID), + SnapshotAtMs: payload.Query.SnapshotAtMs, + } + resultJSON, err := json.Marshal(result) + if err != nil { + return "", "", err + } + return string(resultJSON), artifactName, nil +} + +func stableAppUserExportQuery(query listQuery) listQuery { + // 导出顺序不属于筛选语义,统一 created_at/user_id 倒序才能和固定 keyset 游标一致。 + // 这也绕开 coin 投影的全量内存排序,避免每一批重复读取形成 O(批次数×用户数)。 + query.SortBy = "created_at" + query.SortDirection = "desc" + return query +} + +func (h *Handler) CreateExport(c *gin.Context) { + job, err := h.service.CreateExportJob(c.Request.Context(), shared.ActorFromContext(c), parseListQuery(c)) + if err != nil { + response.ServerError(c, "创建 App 用户导出任务失败") + return + } + writeAppUserAuditLog(c, h.audit, "export-app-users", "app_user_exports", int64(job.JobID), "success", fmt.Sprintf("snapshot_at_ms=%d", job.SnapshotAtMs)) + response.OK(c, job) +} + +func (h *Handler) HandleExportJob(ctx context.Context, job *model.AdminJob) (string, string, error) { + return h.service.HandleExportJob(ctx, job) +} + +func appUserExportHeaders() []string { + return []string{ + "用户ID", "短ID", "靓号", "昵称", "头像", "性别", "生日", "年龄", "国家", "区域", + "VIP等级", "VIP到期时间(ms)", "富豪真实等级", "富豪展示等级", "富豪临时目标", "富豪到期时间(ms)", + "魅力真实等级", "魅力展示等级", "魅力临时目标", "魅力到期时间(ms)", "游戏等级", "身份", + "注册设备", "金币", "钻石", "累计充值(USD分)", "状态", "封禁类型", "封禁到期时间(ms)", "封禁原因", + "注册时间(ms)", "最近活跃时间(ms)", "最近成功登录时间(ms)", "最新操作人", "最新操作", "最新操作时间(ms)", + } +} + +func appUserExportRow(item AppUser) []string { + age := "" + if item.Age != nil { + age = strconv.FormatInt(int64(*item.Age), 10) + } + banType := "" + if item.Ban.Active { + if item.Ban.Permanent { + banType = "永久" + } else { + banType = "限时" + } + } + operatorName := "" + operatorAction := "" + if item.LastOperator != nil { + operatorName = item.LastOperator.Name + operatorAction = item.LastOperator.Action + } + row := []string{ + item.UserID, item.DefaultDisplayUserID, firstNonEmptyString(item.PrettyDisplayUserID, item.PrettyID), item.Username, item.Avatar, + item.Gender, item.Birth, age, firstNonEmptyString(item.CountryDisplayName, item.CountryName, item.Country), item.RegionName, + strconv.FormatInt(int64(item.VIP.Level), 10), strconv.FormatInt(item.VIP.ExpiresAtMs, 10), + strconv.FormatInt(int64(item.Levels.Wealth.RealLevel), 10), strconv.FormatInt(int64(item.Levels.Wealth.DisplayLevel), 10), strconv.FormatInt(int64(item.Levels.Wealth.TemporaryTargetLevel), 10), strconv.FormatInt(item.Levels.Wealth.ExpiresAtMs, 10), + strconv.FormatInt(int64(item.Levels.Charm.RealLevel), 10), strconv.FormatInt(int64(item.Levels.Charm.DisplayLevel), 10), strconv.FormatInt(int64(item.Levels.Charm.TemporaryTargetLevel), 10), strconv.FormatInt(item.Levels.Charm.ExpiresAtMs, 10), + strconv.FormatInt(int64(item.Levels.Game.DisplayLevel), 10), strings.Join(item.Roles, "|"), item.RegisterDevice, + strconv.FormatInt(item.Coin, 10), strconv.FormatInt(item.Diamond, 10), strconv.FormatInt(item.CumulativeRechargeUSDMinor, 10), + item.Status, banType, strconv.FormatInt(item.Ban.ExpiresAtMs, 10), item.Ban.Reason, + strconv.FormatInt(item.CreatedAtMs, 10), strconv.FormatInt(item.LastActiveAtMs, 10), strconv.FormatInt(item.LastLoginAtMs, 10), + operatorName, operatorAction, strconv.FormatInt(item.LastOperatedAtMs, 10), + } + for index := range row { + row[index] = spreadsheetSafeCSVCell(row[index]) + } + return row +} + +func spreadsheetSafeCSVCell(value string) string { + trimmed := strings.TrimLeft(value, " \t\r\n") + if trimmed == "" { + return value + } + switch trimmed[0] { + case '=', '+', '-', '@': + // Excel/Sheets 会把这些前缀解释为公式;前置单引号只影响表格解释,不丢失原始文本内容。 + return "'" + value + default: + return value + } +} + +func firstNonEmptyString(values ...string) string { + for _, value := range values { + if value = strings.TrimSpace(value); value != "" { + return value + } + } + return "" +} diff --git a/server/admin/internal/modules/appuser/export_test.go b/server/admin/internal/modules/appuser/export_test.go new file mode 100644 index 00000000..f2a2250e --- /dev/null +++ b/server/admin/internal/modules/appuser/export_test.go @@ -0,0 +1,106 @@ +package appuser + +import ( + "context" + "encoding/json" + "strings" + "testing" + + "hyapp-admin-server/internal/appctx" + "hyapp-admin-server/internal/config" + "hyapp-admin-server/internal/model" + "hyapp-admin-server/internal/modules/shared" +) + +type recordingAppUserExportStore struct { + job *model.AdminJob +} + +func (s *recordingAppUserExportStore) CreateJob(job *model.AdminJob) error { + copy := *job + copy.ID = 81 + job.ID = copy.ID + s.job = © + return nil +} + +func TestCreateExportJobPersistsFilterSnapshot(t *testing.T) { + store := &recordingAppUserExportStore{} + service := &Service{ + jobStore: store, + jobsConfig: config.JobsConfig{ + Enabled: true, + MaxAttempts: 5, + }, + } + ctx := appctx.WithContext(context.Background(), "lalu") + response, err := service.CreateExportJob(ctx, shared.Actor{UserID: 7, Username: "operator"}, listQuery{ + Country: " ph ", + Status: "active", + Keyword: "1299324", + SortBy: "coin", + SortDirection: "asc", + Page: 9, + PageSize: 10, + }) + if err != nil { + t.Fatalf("create export job: %v", err) + } + if response.JobID != 81 || response.SnapshotAtMs <= 0 || store.job == nil { + t.Fatalf("response/job mismatch: response=%+v job=%+v", response, store.job) + } + if store.job.Type != AppUserExportJobType || store.job.MaxAttempts != 5 || store.job.CreatedBy != 7 { + t.Fatalf("job metadata mismatch: %+v", store.job) + } + var payload appUserExportPayload + if err := json.Unmarshal([]byte(store.job.PayloadJSON), &payload); err != nil { + t.Fatalf("decode payload: %v", err) + } + if payload.AppCode != "lalu" || payload.Query.Country != "PH" || payload.Query.Status != "active" || payload.Query.Keyword != "1299324" { + t.Fatalf("filter snapshot mismatch: %+v", payload) + } + if payload.Query.Page != 1 || payload.Query.PageSize != 100 || payload.Query.SnapshotAtMs != response.SnapshotAtMs { + t.Fatalf("pagination snapshot mismatch: %+v", payload.Query) + } + if payload.Query.SortBy != "created_at" || payload.Query.SortDirection != "desc" { + t.Fatalf("export must use stable database pagination instead of coin projection sort: %+v", payload.Query) + } +} + +func TestStableAppUserExportQueryForcesDescendingKeysetOrder(t *testing.T) { + for _, query := range []listQuery{ + {SortBy: "created_at", SortDirection: "asc"}, + {SortBy: "coin", SortDirection: "asc"}, + } { + stable := stableAppUserExportQuery(normalizeListQuery(query)) + if stable.SortBy != "created_at" || stable.SortDirection != "desc" { + t.Fatalf("export order must match descending keyset: input=%+v stable=%+v", query, stable) + } + } +} + +func TestAppUserExportWhereUsesSnapshotAndKeysetCursor(t *testing.T) { + query := normalizeListQuery(listQuery{ + SnapshotAtMs: 1_000, + ExportCursorCreatedAtMs: 900, + ExportCursorUserID: 88, + }) + whereSQL, args := appUserListWhereSQLAt("lalu", query, query.SnapshotAtMs) + for _, fragment := range []string{ + "u.created_at_ms <= ?", + "u.created_at_ms < ? OR (u.created_at_ms = ? AND u.user_id < ?)", + } { + if !strings.Contains(whereSQL, fragment) { + t.Fatalf("export where SQL missing %q: %s", fragment, whereSQL) + } + } + wantTail := []any{int64(1_000), int64(900), int64(900), int64(88)} + if len(args) < len(wantTail) { + t.Fatalf("export args too short: %+v", args) + } + for index, want := range wantTail { + if got := args[len(args)-len(wantTail)+index]; got != want { + t.Fatalf("export cursor arg[%d]=%v want=%v all=%+v", index, got, want, args) + } + } +} diff --git a/server/admin/internal/modules/appuser/handler.go b/server/admin/internal/modules/appuser/handler.go index ec25a596..c9f823cd 100644 --- a/server/admin/internal/modules/appuser/handler.go +++ b/server/admin/internal/modules/appuser/handler.go @@ -4,6 +4,7 @@ import ( "database/sql" "errors" "fmt" + "io" "strconv" "strings" @@ -15,6 +16,8 @@ import ( "hyapp-admin-server/internal/response" "github.com/gin-gonic/gin" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) type Handler struct { @@ -23,9 +26,9 @@ type Handler struct { audit shared.OperationLogger } -func New(userClient userclient.Client, activityClient activityclient.Client, adminDB *sql.DB, userDB *sql.DB, walletDB *sql.DB, cfg config.Config, audit shared.OperationLogger) *Handler { +func New(userClient userclient.Client, activityClient activityclient.Client, adminDB *sql.DB, userDB *sql.DB, walletDB *sql.DB, cfg config.Config, audit shared.OperationLogger, opts ...ServiceOption) *Handler { return &Handler{ - service: NewService(userClient, activityClient, adminDB, userDB, walletDB), + service: NewService(userClient, activityClient, adminDB, userDB, walletDB, opts...), cfg: cfg, audit: audit, } @@ -113,11 +116,64 @@ func (h *Handler) UpdateUser(c *gin.Context) { } func (h *Handler) BanUser(c *gin.Context) { - h.setUserStatus(c, "banned", "ban-app-user", "用户已封禁") + userID, ok := parseInt64ID(c, "id") + if !ok { + return + } + var req banUserRequest + if err := c.ShouldBindJSON(&req); err != nil && !errors.Is(err, io.EOF) { + response.BadRequest(c, "封禁参数不正确") + return + } + result, err := h.service.AdminBanUser(c.Request.Context(), userID, int64(middleware.CurrentUserID(c)), middleware.CurrentRequestID(c), req) + if err != nil { + writeMutationError(c, err, "封禁 App 用户失败") + return + } + detail := "permanent" + if req.ExpiresAtMs > 0 { + detail = fmt.Sprintf("expires_at_ms=%d", req.ExpiresAtMs) + } + writeAppUserAuditLog(c, h.audit, "ban-app-user", "app_users", userID, "success", detail) + response.OK(c, result) } func (h *Handler) UnbanUser(c *gin.Context) { - h.setUserStatus(c, "active", "unban-app-user", "用户已解封") + userID, ok := parseInt64ID(c, "id") + if !ok { + return + } + var req unbanUserRequest + if err := c.ShouldBindJSON(&req); err != nil && !errors.Is(err, io.EOF) { + response.BadRequest(c, "解封参数不正确") + return + } + result, err := h.service.AdminUnbanUser(c.Request.Context(), userID, int64(middleware.CurrentUserID(c)), middleware.CurrentRequestID(c), req) + if err != nil { + writeMutationError(c, err, "解封 App 用户失败") + return + } + writeAppUserAuditLog(c, h.audit, "unban-app-user", "app_users", userID, "success", strings.TrimSpace(req.Reason)) + response.OK(c, result) +} + +func (h *Handler) AdjustTemporaryLevels(c *gin.Context) { + userID, ok := parseInt64ID(c, "id") + if !ok { + return + } + var req adjustTemporaryLevelsRequest + if err := c.ShouldBindJSON(&req); err != nil { + response.BadRequest(c, "等级调整参数不正确") + return + } + user, err := h.service.AdjustTemporaryLevels(c.Request.Context(), userID, int64(middleware.CurrentUserID(c)), middleware.CurrentRequestID(c), req) + if err != nil { + writeMutationError(c, err, "调整用户等级失败") + return + } + writeAppUserAuditLog(c, h.audit, "adjust-app-user-level", "app_users", userID, "success", fmt.Sprintf("tracks=%d", len(req.Adjustments))) + response.OK(c, user) } func (h *Handler) SetPassword(c *gin.Context) { @@ -269,6 +325,22 @@ func writeMutationError(c *gin.Context, err error, fallback string) { response.BadRequest(c, err.Error()) return } + if grpcStatus, ok := status.FromError(err); ok { + message := strings.TrimSpace(grpcStatus.Message()) + if message == "" { + message = fallback + } + switch grpcStatus.Code() { + case codes.InvalidArgument, codes.AlreadyExists, codes.FailedPrecondition, codes.Aborted: + // 等级目标不高于真实等级、规则缺失或仍有其他封禁都属于可修正的业务拒绝,不能伪装成 500。 + response.BadRequest(c, message) + case codes.NotFound: + response.NotFound(c, message) + default: + response.ServerError(c, fallback) + } + return + } response.ServerError(c, fallback) } diff --git a/server/admin/internal/modules/appuser/handler_test.go b/server/admin/internal/modules/appuser/handler_test.go new file mode 100644 index 00000000..283ba996 --- /dev/null +++ b/server/admin/internal/modules/appuser/handler_test.go @@ -0,0 +1,34 @@ +package appuser + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/gin-gonic/gin" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func TestWriteMutationErrorMapsGRPCBusinessFailures(t *testing.T) { + gin.SetMode(gin.TestMode) + tests := []struct { + name string + err error + wantStatus int + }{ + {name: "invalid level", err: status.Error(codes.FailedPrecondition, "target must exceed real level"), wantStatus: http.StatusBadRequest}, + {name: "missing user", err: status.Error(codes.NotFound, "user not found"), wantStatus: http.StatusNotFound}, + {name: "owner unavailable", err: status.Error(codes.Unavailable, "activity unavailable"), wantStatus: http.StatusInternalServerError}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + recorder := httptest.NewRecorder() + context, _ := gin.CreateTestContext(recorder) + writeMutationError(context, test.err, "mutation failed") + if recorder.Code != test.wantStatus { + t.Fatalf("HTTP status=%d want=%d body=%s", recorder.Code, test.wantStatus, recorder.Body.String()) + } + }) + } +} diff --git a/server/admin/internal/modules/appuser/projection_test.go b/server/admin/internal/modules/appuser/projection_test.go new file mode 100644 index 00000000..6c8f1ee8 --- /dev/null +++ b/server/admin/internal/modules/appuser/projection_test.go @@ -0,0 +1,85 @@ +package appuser + +import ( + "context" + "testing" + + "hyapp-admin-server/internal/appctx" + activityv1 "hyapp.local/api/proto/activity/v1" + userv1 "hyapp.local/api/proto/user/v1" +) + +type fakeUserAdminProjectionClient struct { + profiles map[int64]*userv1.UserAdminProfile +} + +func (f *fakeUserAdminProjectionClient) BatchGetUserAdminProfiles(context.Context, *userv1.BatchGetUserAdminProfilesRequest) (*userv1.BatchGetUserAdminProfilesResponse, error) { + return &userv1.BatchGetUserAdminProfilesResponse{Profiles: f.profiles}, nil +} + +func (f *fakeUserAdminProjectionClient) AdminBanUser(context.Context, *userv1.AdminBanUserRequest) (*userv1.AdminBanUserResponse, error) { + return &userv1.AdminBanUserResponse{}, nil +} + +func (f *fakeUserAdminProjectionClient) AdminUnbanUser(context.Context, *userv1.AdminUnbanUserRequest) (*userv1.AdminUnbanUserResponse, error) { + return &userv1.AdminUnbanUserResponse{}, nil +} + +type fakeLevelAdminProjectionClient struct { + profiles []*activityv1.AdminUserLevelProfile +} + +func (f *fakeLevelAdminProjectionClient) BatchGetUserLevelAdminProfiles(context.Context, *activityv1.BatchGetUserLevelAdminProfilesRequest) (*activityv1.BatchGetUserLevelAdminProfilesResponse, error) { + return &activityv1.BatchGetUserLevelAdminProfilesResponse{Profiles: f.profiles}, nil +} + +func (f *fakeLevelAdminProjectionClient) AdjustTemporaryUserLevels(context.Context, *activityv1.AdjustTemporaryUserLevelsRequest) (*activityv1.AdjustTemporaryUserLevelsResponse, error) { + return &activityv1.AdjustTemporaryUserLevelsResponse{}, nil +} + +func TestAdminProjectionEnrichmentMapsOwnerFacts(t *testing.T) { + service := &Service{ + userAdminClient: &fakeUserAdminProjectionClient{profiles: map[int64]*userv1.UserAdminProfile{ + 10001: { + Birth: "2000-02-03", + RegisterDevice: "Pixel 9", + LastSuccessLoginAtMs: 7000, + Roles: []string{"host", "bd_leader", "manager"}, + Ban: &userv1.ActiveUserBanSummary{ + Active: true, Source: "admin", BanId: "ban-1", Permanent: false, ExpiresAtMs: 9000, Reason: "risk", + }, + }, + }}, + levelAdminClient: &fakeLevelAdminProjectionClient{profiles: []*activityv1.AdminUserLevelProfile{ + {UserId: 10001, Tracks: []*activityv1.AdminLevelTrackProfile{ + {Track: "wealth", RealLevel: 8, RealTotalValue: 800, DisplayLevel: 14, DisplayValue: 1400, TemporaryLevelId: "temp-1", TemporaryTargetLevel: 14, StartedAtMs: 1000, ExpiresAtMs: 9000}, + {Track: "charm", RealLevel: 9, RealTotalValue: 900, DisplayLevel: 9, DisplayValue: 900}, + {Track: "game", RealLevel: 6, RealTotalValue: 600, DisplayLevel: 6, DisplayValue: 600}, + }}, + }}, + } + items := []AppUser{{UserID: "10001"}} + ctx := appctx.WithContext(context.Background(), "lalu") + if err := service.fillUserAdminProfiles(ctx, items, []int64{10001}); err != nil { + t.Fatalf("fill user profiles: %v", err) + } + if err := service.fillLevelAdminProfiles(ctx, items, []int64{10001}); err != nil { + t.Fatalf("fill level profiles: %v", err) + } + item := items[0] + if item.Birth != "2000-02-03" || item.RegisterDevice != "Pixel 9" || item.LastLoginAtMs != 7000 { + t.Fatalf("user owner facts mismatch: %+v", item) + } + if len(item.Roles) != 3 || item.Roles[0] != "主播" || item.Roles[1] != "BD Leader" || item.Roles[2] != "经理" { + t.Fatalf("roles mismatch: %#v", item.Roles) + } + if !item.Ban.Active || item.Ban.ID != "ban-1" || item.Ban.ExpiresAtMs != 9000 { + t.Fatalf("ban mismatch: %+v", item.Ban) + } + if item.Levels.Wealth.RealLevel != 8 || item.Levels.Wealth.DisplayLevel != 14 || item.Levels.Wealth.TemporaryTargetLevel != 14 { + t.Fatalf("wealth overlay mismatch: %+v", item.Levels.Wealth) + } + if item.Levels.Game.DisplayLevel != 6 || item.Levels.Charm.DisplayLevel != 9 { + t.Fatalf("read-only levels mismatch: %+v", item.Levels) + } +} diff --git a/server/admin/internal/modules/appuser/request.go b/server/admin/internal/modules/appuser/request.go index be687d8d..c463d3e7 100644 --- a/server/admin/internal/modules/appuser/request.go +++ b/server/admin/internal/modules/appuser/request.go @@ -15,6 +15,11 @@ type listQuery struct { SortDirection string StartMs int64 EndMs int64 + // SnapshotAtMs 只由异步导出设置,使短号租约和筛选时间基线在所有分页中保持一致。 + SnapshotAtMs int64 + // ExportCursor* 仅在 job worker 内存中推进 keyset;不进入任务 payload,也不暴露为 HTTP 查询参数。 + ExportCursorCreatedAtMs int64 `json:"-"` + ExportCursorUserID int64 `json:"-"` } type loginLogQuery struct { @@ -58,3 +63,23 @@ type updateUserRequest struct { type setPasswordRequest struct { Password string `json:"password" binding:"required"` } + +type temporaryLevelAdjustmentRequest struct { + Track string `json:"track" binding:"required"` + Level int32 `json:"level" binding:"required"` + DurationDays int32 `json:"duration_days" binding:"required"` +} + +type adjustTemporaryLevelsRequest struct { + Adjustments []temporaryLevelAdjustmentRequest `json:"adjustments" binding:"required,min=1,max=2,dive"` + Reason string `json:"reason"` +} + +type banUserRequest struct { + ExpiresAtMs int64 `json:"expires_at_ms"` + Reason string `json:"reason"` +} + +type unbanUserRequest struct { + Reason string `json:"reason"` +} diff --git a/server/admin/internal/modules/appuser/routes.go b/server/admin/internal/modules/appuser/routes.go index da18e152..046aec44 100644 --- a/server/admin/internal/modules/appuser/routes.go +++ b/server/admin/internal/modules/appuser/routes.go @@ -12,11 +12,13 @@ func RegisterRoutes(protected *gin.RouterGroup, h *Handler) { } protected.GET("/app/users", middleware.RequirePermission("app-user:view"), h.ListUsers) + protected.POST("/exports/app-users", middleware.RequirePermission("app-user:export"), h.CreateExport) protected.GET("/app/users/bans", middleware.RequirePermission("app-user:view"), h.ListBannedUsers) protected.GET("/app/users/login-logs", middleware.RequirePermission("app-user:view"), h.ListLoginLogs) protected.GET("/app/users/:id/login-logs", middleware.RequirePermission("app-user:view"), h.ListUserLoginLogs) protected.GET("/app/users/:id", middleware.RequirePermission("app-user:view"), h.GetUser) protected.PATCH("/app/users/:id", middleware.RequirePermission("app-user:update"), h.UpdateUser) + protected.PUT("/app/users/:id/levels", middleware.RequirePermission("app-user:level"), h.AdjustTemporaryLevels) protected.POST("/app/users/:id/ban", middleware.RequirePermission("app-user:status"), h.BanUser) protected.POST("/app/users/:id/unban", middleware.RequirePermission("app-user:status"), h.UnbanUser) protected.POST("/app/users/:id/password", middleware.RequirePermission("app-user:password"), h.SetPassword) diff --git a/server/admin/internal/modules/appuser/service.go b/server/admin/internal/modules/appuser/service.go index ad82defb..da36bf92 100644 --- a/server/admin/internal/modules/appuser/service.go +++ b/server/admin/internal/modules/appuser/service.go @@ -12,11 +12,15 @@ import ( "time" "hyapp-admin-server/internal/appctx" + "hyapp-admin-server/internal/config" "hyapp-admin-server/internal/integration/activityclient" "hyapp-admin-server/internal/integration/userclient" + "hyapp-admin-server/internal/integration/walletclient" "hyapp-admin-server/internal/modules/shared" "hyapp-admin-server/internal/security" activityv1 "hyapp.local/api/proto/activity/v1" + userv1 "hyapp.local/api/proto/user/v1" + walletv1 "hyapp.local/api/proto/wallet/v1" ) var ( @@ -25,37 +29,122 @@ var ( ) type Service struct { - userClient userclient.Client - activityClient activityclient.Client - adminDB *sql.DB - userDB *sql.DB - walletDB *sql.DB + userClient userclient.Client + userAdminClient userAdminProjectionClient + activityClient activityclient.Client + levelAdminClient levelAdminProjectionClient + walletClient rechargeStatsClient + jobStore appUserExportJobStore + jobsConfig config.JobsConfig + adminDB *sql.DB + userDB *sql.DB + walletDB *sql.DB +} + +// rechargeStatsClient 只暴露用户后台需要的累计充值聚合;列表不能为展示字段回扫钱包流水。 +type rechargeStatsClient interface { + BatchGetUserRechargeStats(context.Context, *walletv1.BatchGetUserRechargeStatsRequest) (*walletv1.BatchGetUserRechargeStatsResponse, error) +} + +// userAdminProjectionClient 保证生日、成功登录和封禁语义继续由 user-service 统一解释。 +type userAdminProjectionClient interface { + BatchGetUserAdminProfiles(context.Context, *userv1.BatchGetUserAdminProfilesRequest) (*userv1.BatchGetUserAdminProfilesResponse, error) + AdminBanUser(context.Context, *userv1.AdminBanUserRequest) (*userv1.AdminBanUserResponse, error) + AdminUnbanUser(context.Context, *userv1.AdminUnbanUserRequest) (*userv1.AdminUnbanUserResponse, error) +} + +// levelAdminProjectionClient 只允许后台读 overlay 和一次原子调整,游戏等级没有写入口。 +type levelAdminProjectionClient interface { + BatchGetUserLevelAdminProfiles(context.Context, *activityv1.BatchGetUserLevelAdminProfilesRequest) (*activityv1.BatchGetUserLevelAdminProfilesResponse, error) + AdjustTemporaryUserLevels(context.Context, *activityv1.AdjustTemporaryUserLevelsRequest) (*activityv1.AdjustTemporaryUserLevelsResponse, error) +} + +type ServiceOption func(*Service) + +// WithWalletClient 通过 wallet-service 读取它拥有的充值聚合,保留 walletDB 仅用于现有余额与 VIP 展示。 +func WithWalletClient(client walletclient.Client) ServiceOption { + return func(service *Service) { + service.walletClient = client + } +} + +// WithExportJobs 把任务创建留在 admin 数据库,把分批导出交给统一 job runner 执行。 +func WithExportJobs(store appUserExportJobStore, cfg config.Config) ServiceOption { + return func(service *Service) { + service.jobStore = store + service.jobsConfig = cfg.Jobs + } } type AppUser struct { - Avatar string `json:"avatar"` - Balances []AppUserAssetBalance `json:"balances,omitempty"` - Coin int64 `json:"coin"` - Country string `json:"country"` - CountryDisplayName string `json:"countryDisplayName"` - CountryName string `json:"countryName"` - CreatedAtMs int64 `json:"createdAtMs"` - DefaultDisplayUserID string `json:"defaultDisplayUserId"` - Diamond int64 `json:"diamond"` - DisplayUserID string `json:"displayUserId"` - EquippedResources []AppUserResource `json:"equippedResources,omitempty"` - Gender string `json:"gender"` - LastActiveAtMs int64 `json:"lastActiveAtMs"` - PrettyDisplayUserID string `json:"prettyDisplayUserId"` - PrettyID string `json:"prettyId"` - RegionID int64 `json:"regionId"` - RegionName string `json:"regionName"` - Resources []AppUserResource `json:"resources,omitempty"` - Status string `json:"status"` - UpdatedAtMs int64 `json:"updatedAtMs"` - UserID string `json:"userId"` - Username string `json:"username"` - VIP AppUserVIP `json:"vip"` + Age *int32 `json:"age,omitempty"` + Avatar string `json:"avatar"` + Balances []AppUserAssetBalance `json:"balances,omitempty"` + Ban AppUserBan `json:"ban"` + Birth string `json:"birth"` + Coin int64 `json:"coin"` + Country string `json:"country"` + CountryDisplayName string `json:"countryDisplayName"` + CountryName string `json:"countryName"` + CreatedAtMs int64 `json:"createdAtMs"` + CumulativeRechargeUSDMinor int64 `json:"cumulativeRechargeUsdMinor"` + DefaultDisplayUserID string `json:"defaultDisplayUserId"` + Diamond int64 `json:"diamond"` + DisplayUserID string `json:"displayUserId"` + EquippedResources []AppUserResource `json:"equippedResources,omitempty"` + Gender string `json:"gender"` + LastActiveAtMs int64 `json:"lastActiveAtMs"` + LastLoginAtMs int64 `json:"lastLoginAtMs"` + LastOperatedAtMs int64 `json:"lastOperatedAtMs"` + LastOperator *AppUserOperator `json:"lastOperator,omitempty"` + Levels AppUserLevels `json:"levels"` + PrettyDisplayUserID string `json:"prettyDisplayUserId"` + PrettyID string `json:"prettyId"` + RegisterDevice string `json:"registerDevice"` + RegionID int64 `json:"regionId"` + RegionName string `json:"regionName"` + Resources []AppUserResource `json:"resources,omitempty"` + Roles []string `json:"roles"` + Status string `json:"status"` + UpdatedAtMs int64 `json:"updatedAtMs"` + UserID string `json:"userId"` + Username string `json:"username"` + VIP AppUserVIP `json:"vip"` +} + +// AppUserLevels 固定三个成长轨道,前端无需按数组位置猜测富豪、游戏和魅力列。 +type AppUserLevels struct { + Wealth AppUserLevel `json:"wealth"` + Game AppUserLevel `json:"game"` + Charm AppUserLevel `json:"charm"` +} + +// AppUserLevel 同时暴露真实成长事实和当前临时展示事实,详情页可明确标出到期时间。 +type AppUserLevel struct { + Track string `json:"track"` + RealLevel int32 `json:"realLevel"` + RealTotalValue int64 `json:"realTotalValue"` + DisplayLevel int32 `json:"displayLevel"` + DisplayValue int64 `json:"displayValue"` + TemporaryLevelID string `json:"temporaryLevelId,omitempty"` + TemporaryTargetLevel int32 `json:"temporaryTargetLevel,omitempty"` + StartedAtMs int64 `json:"startedAtMs,omitempty"` + ExpiresAtMs int64 `json:"expiresAtMs,omitempty"` +} + +type AppUserBan struct { + ID string `json:"id,omitempty"` + Active bool `json:"active"` + Permanent bool `json:"permanent"` + ExpiresAtMs int64 `json:"expiresAtMs"` + Source string `json:"source,omitempty"` + Reason string `json:"reason,omitempty"` +} + +type AppUserOperator struct { + AdminID string `json:"adminId"` + Name string `json:"name"` + Action string `json:"action"` } type AppUserAssetBalance struct { @@ -110,8 +199,20 @@ type SetUserStatusResult struct { RoomEvictError string `json:"roomEvictError,omitempty"` } -func NewService(userClient userclient.Client, activityClient activityclient.Client, adminDB *sql.DB, userDB *sql.DB, walletDB *sql.DB) *Service { - return &Service{userClient: userClient, activityClient: activityClient, adminDB: adminDB, userDB: userDB, walletDB: walletDB} +func NewService(userClient userclient.Client, activityClient activityclient.Client, adminDB *sql.DB, userDB *sql.DB, walletDB *sql.DB, opts ...ServiceOption) *Service { + service := &Service{userClient: userClient, activityClient: activityClient, adminDB: adminDB, userDB: userDB, walletDB: walletDB} + if adminClient, ok := any(userClient).(userAdminProjectionClient); ok { + service.userAdminClient = adminClient + } + if adminClient, ok := any(activityClient).(levelAdminProjectionClient); ok { + service.levelAdminClient = adminClient + } + for _, opt := range opts { + if opt != nil { + opt(service) + } + } + return service } func (s *Service) ListUsers(ctx context.Context, query listQuery) ([]AppUser, int64, error) { @@ -120,7 +221,10 @@ func (s *Service) ListUsers(ctx context.Context, query listQuery) ([]AppUser, in } query = normalizeListQuery(query) appCode := appctx.FromContext(ctx) - nowMs := nowMillis() + nowMs := query.SnapshotAtMs + if nowMs <= 0 { + nowMs = nowMillis() + } whereSQL, args := appUserListWhereSQLAt(appCode, query, nowMs) total, err := countRows(ctx, s.userDB, whereSQL, args...) @@ -192,6 +296,18 @@ func (s *Service) ListUsers(ctx context.Context, query listQuery) ([]AppUser, in if err := s.fillVIPLevels(ctx, items, userIDs); err != nil { return nil, 0, err } + if err := s.fillUserAdminProfiles(ctx, items, userIDs); err != nil { + return nil, 0, err + } + if err := s.fillLevelAdminProfiles(ctx, items, userIDs); err != nil { + return nil, 0, err + } + if err := s.fillRechargeStats(ctx, items, userIDs); err != nil { + return nil, 0, err + } + if err := s.fillLatestOperators(ctx, items, userIDs); err != nil { + return nil, 0, err + } return items, total, nil } @@ -256,6 +372,19 @@ func (s *Service) listUsersSortedByCoin(ctx context.Context, query listQuery, wh if err := s.fillVIPLevels(ctx, pagedItems, appUserNumericIDs(pagedItems)); err != nil { return nil, err } + pagedUserIDs := appUserNumericIDs(pagedItems) + if err := s.fillUserAdminProfiles(ctx, pagedItems, pagedUserIDs); err != nil { + return nil, err + } + if err := s.fillLevelAdminProfiles(ctx, pagedItems, pagedUserIDs); err != nil { + return nil, err + } + if err := s.fillRechargeStats(ctx, pagedItems, pagedUserIDs); err != nil { + return nil, err + } + if err := s.fillLatestOperators(ctx, pagedItems, pagedUserIDs); err != nil { + return nil, err + } return pagedItems, nil } @@ -380,12 +509,297 @@ func (s *Service) GetUser(ctx context.Context, userID int64) (AppUser, error) { if err := s.fillVIPLevels(ctx, items, []int64{userID}); err != nil { return AppUser{}, err } + if err := s.fillUserAdminProfiles(ctx, items, []int64{userID}); err != nil { + return AppUser{}, err + } + if err := s.fillLevelAdminProfiles(ctx, items, []int64{userID}); err != nil { + return AppUser{}, err + } + if err := s.fillRechargeStats(ctx, items, []int64{userID}); err != nil { + return AppUser{}, err + } + if err := s.fillLatestOperators(ctx, items, []int64{userID}); err != nil { + return AppUser{}, err + } if err := s.fillUserResources(ctx, items, userID); err != nil { return AppUser{}, err } return items[0], nil } +func (s *Service) fillUserAdminProfiles(ctx context.Context, items []AppUser, userIDs []int64) error { + initializeAdminProjectionDefaults(items) + if s.userAdminClient == nil || len(items) == 0 || len(userIDs) == 0 { + return nil + } + nowMs := nowMillis() + response, err := s.userAdminClient.BatchGetUserAdminProfiles(ctx, &userv1.BatchGetUserAdminProfilesRequest{ + Meta: &userv1.RequestMeta{ + RequestId: fmt.Sprintf("admin-app-user-profile-%d", nowMs), + Caller: "hyapp-admin-server", + SentAtMs: nowMs, + AppCode: appctx.FromContext(ctx), + }, + UserIds: userIDs, + }) + if err != nil { + return err + } + index := appUserIndex(items) + for userID, profile := range response.GetProfiles() { + if profile == nil { + continue + } + i, ok := index[userID] + if !ok { + continue + } + items[i].Birth = strings.TrimSpace(profile.GetBirth()) + items[i].Age = ageAtUTC(items[i].Birth, time.UnixMilli(nowMs).UTC()) + items[i].RegisterDevice = strings.TrimSpace(profile.GetRegisterDevice()) + items[i].LastLoginAtMs = profile.GetLastSuccessLoginAtMs() + items[i].Roles = displayUserRoles(profile.GetRoles()) + if ban := profile.GetBan(); ban != nil { + items[i].Ban = AppUserBan{ + ID: strings.TrimSpace(ban.GetBanId()), + Active: ban.GetActive(), + Permanent: ban.GetPermanent(), + ExpiresAtMs: ban.GetExpiresAtMs(), + Source: strings.TrimSpace(ban.GetSource()), + Reason: strings.TrimSpace(ban.GetReason()), + } + } + if profile.GetLastOperationAtMs() > items[i].LastOperatedAtMs { + items[i].LastOperatedAtMs = profile.GetLastOperationAtMs() + items[i].LastOperator = &AppUserOperator{ + AdminID: strconv.FormatInt(profile.GetLastOperatorUserId(), 10), + Name: displayOperatorType(profile.GetLastOperatorType()), + Action: strings.TrimSpace(profile.GetLastOperationReason()), + } + } + } + return nil +} + +func (s *Service) fillLevelAdminProfiles(ctx context.Context, items []AppUser, userIDs []int64) error { + initializeAdminProjectionDefaults(items) + if s.levelAdminClient == nil || len(items) == 0 || len(userIDs) == 0 { + return nil + } + nowMs := nowMillis() + response, err := s.levelAdminClient.BatchGetUserLevelAdminProfiles(ctx, &activityv1.BatchGetUserLevelAdminProfilesRequest{ + Meta: &activityv1.RequestMeta{ + RequestId: fmt.Sprintf("admin-app-user-level-%d", nowMs), + Caller: "hyapp-admin-server", + SentAtMs: nowMs, + AppCode: appctx.FromContext(ctx), + }, + UserIds: userIDs, + }) + if err != nil { + return err + } + index := appUserIndex(items) + for _, profile := range response.GetProfiles() { + if profile == nil { + continue + } + i, ok := index[profile.GetUserId()] + if !ok { + continue + } + for _, track := range profile.GetTracks() { + if track == nil { + continue + } + level := AppUserLevel{ + Track: strings.ToLower(strings.TrimSpace(track.GetTrack())), + RealLevel: track.GetRealLevel(), + RealTotalValue: track.GetRealTotalValue(), + DisplayLevel: track.GetDisplayLevel(), + DisplayValue: track.GetDisplayValue(), + TemporaryLevelID: strings.TrimSpace(track.GetTemporaryLevelId()), + TemporaryTargetLevel: track.GetTemporaryTargetLevel(), + StartedAtMs: track.GetStartedAtMs(), + ExpiresAtMs: track.GetExpiresAtMs(), + } + switch level.Track { + case "wealth": + items[i].Levels.Wealth = level + case "charm": + items[i].Levels.Charm = level + case "game": + items[i].Levels.Game = level + } + } + } + return nil +} + +func initializeAdminProjectionDefaults(items []AppUser) { + for i := range items { + if len(items[i].Roles) == 0 { + items[i].Roles = []string{"普通用户"} + } + if items[i].Levels.Wealth.Track == "" { + items[i].Levels.Wealth.Track = "wealth" + } + if items[i].Levels.Charm.Track == "" { + items[i].Levels.Charm.Track = "charm" + } + if items[i].Levels.Game.Track == "" { + items[i].Levels.Game.Track = "game" + } + } +} + +func displayUserRoles(roles []string) []string { + displayByRole := map[string]string{ + "host": "主播", + "agency": "公会长", + "bd": "BD", + "bd_leader": "BD Leader", + "coin_seller": "币商", + "manager": "经理", + } + seen := make(map[string]struct{}, len(roles)) + for _, role := range roles { + role = strings.ToLower(strings.TrimSpace(role)) + if _, ok := displayByRole[role]; ok { + seen[role] = struct{}{} + } + } + order := []string{"host", "agency", "bd", "bd_leader", "coin_seller", "manager"} + result := make([]string, 0, len(seen)) + for _, role := range order { + if _, ok := seen[role]; ok { + result = append(result, displayByRole[role]) + } + } + if len(result) == 0 { + return []string{"普通用户"} + } + return result +} + +func displayOperatorType(operatorType string) string { + switch strings.ToLower(strings.TrimSpace(operatorType)) { + case "admin": + return "管理员" + case "manager": + return "经理" + default: + return strings.TrimSpace(operatorType) + } +} + +func ageAtUTC(birth string, now time.Time) *int32 { + birthDate, err := time.Parse("2006-01-02", strings.TrimSpace(birth)) + if err != nil || birthDate.After(now) { + return nil + } + age := now.Year() - birthDate.Year() + if now.Month() < birthDate.Month() || (now.Month() == birthDate.Month() && now.Day() < birthDate.Day()) { + age-- + } + if age < 0 { + return nil + } + value := int32(age) + return &value +} + +func (s *Service) fillRechargeStats(ctx context.Context, items []AppUser, userIDs []int64) error { + if s.walletClient == nil || len(items) == 0 || len(userIDs) == 0 { + return nil + } + response, err := s.walletClient.BatchGetUserRechargeStats(ctx, &walletv1.BatchGetUserRechargeStatsRequest{ + RequestId: fmt.Sprintf("admin-app-user-recharge-%d", nowMillis()), + AppCode: appctx.FromContext(ctx), + UserIds: userIDs, + }) + if err != nil { + return err + } + index := appUserIndex(items) + for _, stat := range response.GetItems() { + if stat == nil { + continue + } + if i, ok := index[stat.GetUserId()]; ok { + items[i].CumulativeRechargeUSDMinor = stat.GetTotalUsdMinorAmount() + } + } + return nil +} + +func (s *Service) fillLatestOperators(ctx context.Context, items []AppUser, userIDs []int64) error { + if s.adminDB == nil || len(items) == 0 || len(userIDs) == 0 { + return nil + } + args := make([]any, 0, len(userIDs)+1) + args = append(args, "app_users") + for _, userID := range userIDs { + args = append(args, strconv.FormatInt(userID, 10)) + } + rows, err := s.adminDB.QueryContext(ctx, fmt.Sprintf(` + SELECT resource_id, user_id, username, action, created_at_ms + FROM admin_operation_logs + WHERE resource = ? AND resource_id IN (%s) AND status = 'success' + ORDER BY resource_id ASC, created_at_ms DESC, id DESC + `, placeholders(len(userIDs))), args...) + if err != nil { + return err + } + defer rows.Close() + + index := appUserIndex(items) + seen := make(map[int64]struct{}, len(userIDs)) + for rows.Next() { + var resourceID string + var adminID uint64 + var name string + var action string + var operatedAtMs int64 + if err := rows.Scan(&resourceID, &adminID, &name, &action, &operatedAtMs); err != nil { + return err + } + userID, err := strconv.ParseInt(strings.TrimSpace(resourceID), 10, 64) + if err != nil { + continue + } + if _, ok := seen[userID]; ok { + continue + } + i, ok := index[userID] + if !ok { + continue + } + seen[userID] = struct{}{} + if operatedAtMs <= items[i].LastOperatedAtMs { + continue + } + items[i].LastOperatedAtMs = operatedAtMs + items[i].LastOperator = &AppUserOperator{ + AdminID: strconv.FormatUint(adminID, 10), + Name: strings.TrimSpace(name), + Action: strings.TrimSpace(action), + } + } + return rows.Err() +} + +func appUserIndex(items []AppUser) map[int64]int { + index := make(map[int64]int, len(items)) + for i := range items { + userID, err := strconv.ParseInt(strings.TrimSpace(items[i].UserID), 10, 64) + if err == nil && userID > 0 { + index[userID] = i + } + } + return index +} + func (s *Service) UpdateUser(ctx context.Context, userID int64, adminUserID int64, requestID string, req updateUserRequest) (AppUser, error) { if s.userDB == nil { return AppUser{}, fmt.Errorf("user mysql is not configured") @@ -527,6 +941,163 @@ func (s *Service) SetUserStatus(ctx context.Context, userID int64, status string return output, nil } +func (s *Service) AdjustTemporaryLevels(ctx context.Context, userID int64, operatorAdminID int64, requestID string, req adjustTemporaryLevelsRequest) (AppUser, error) { + if s.levelAdminClient == nil { + return AppUser{}, fmt.Errorf("activity service level admin client is not configured") + } + if userID <= 0 || operatorAdminID <= 0 || len(req.Adjustments) == 0 || len(req.Adjustments) > 2 { + return AppUser{}, fmt.Errorf("%w: 等级调整参数不正确", ErrInvalidArgument) + } + seen := make(map[string]struct{}, len(req.Adjustments)) + adjustments := make([]*activityv1.TemporaryLevelAdjustment, 0, len(req.Adjustments)) + for _, adjustment := range req.Adjustments { + track := strings.ToLower(strings.TrimSpace(adjustment.Track)) + if track != "wealth" && track != "charm" { + return AppUser{}, fmt.Errorf("%w: 只允许调整富豪或魅力等级", ErrInvalidArgument) + } + if _, duplicated := seen[track]; duplicated { + return AppUser{}, fmt.Errorf("%w: 同一等级轨道不能重复提交", ErrInvalidArgument) + } + if adjustment.Level < 1 || adjustment.Level > 50 || adjustment.DurationDays <= 0 { + return AppUser{}, fmt.Errorf("%w: 等级必须为 1-50 且有效期必须大于 0 天", ErrInvalidArgument) + } + seen[track] = struct{}{} + adjustments = append(adjustments, &activityv1.TemporaryLevelAdjustment{ + Track: track, + Level: adjustment.Level, + DurationDays: adjustment.DurationDays, + }) + } + requestID = strings.TrimSpace(requestID) + if requestID == "" { + return AppUser{}, fmt.Errorf("%w: request_id 不能为空", ErrInvalidArgument) + } + nowMs := nowMillis() + reason := strings.TrimSpace(req.Reason) + if reason == "" { + reason = "admin_temporary_user_level" + } + _, err := s.levelAdminClient.AdjustTemporaryUserLevels(ctx, &activityv1.AdjustTemporaryUserLevelsRequest{ + Meta: &activityv1.RequestMeta{ + RequestId: requestID, + Caller: "hyapp-admin-server", + SentAtMs: nowMs, + AppCode: appctx.FromContext(ctx), + }, + CommandId: fmt.Sprintf("app-user-level:%s:%d", requestID, userID), + UserId: userID, + Adjustments: adjustments, + OperatorAdminId: operatorAdminID, + Reason: reason, + }) + if err != nil { + return AppUser{}, err + } + return s.GetUser(ctx, userID) +} + +func (s *Service) AdminBanUser(ctx context.Context, userID int64, operatorAdminID int64, requestID string, req banUserRequest) (SetUserStatusResult, error) { + if s.userAdminClient == nil { + return SetUserStatusResult{}, fmt.Errorf("user service admin ban client is not configured") + } + nowMs := nowMillis() + if userID <= 0 || operatorAdminID <= 0 || req.ExpiresAtMs < 0 || (req.ExpiresAtMs > 0 && req.ExpiresAtMs <= nowMs) { + return SetUserStatusResult{}, fmt.Errorf("%w: 封禁截止时间必须为 0 或晚于当前 UTC 时间", ErrInvalidArgument) + } + requestID = strings.TrimSpace(requestID) + if requestID == "" { + return SetUserStatusResult{}, fmt.Errorf("%w: request_id 不能为空", ErrInvalidArgument) + } + reason := strings.TrimSpace(req.Reason) + if reason == "" { + reason = "admin_app_user_ban" + } + response, err := s.userAdminClient.AdminBanUser(ctx, &userv1.AdminBanUserRequest{ + Meta: &userv1.RequestMeta{ + RequestId: requestID, + Caller: "hyapp-admin-server", + SentAtMs: nowMs, + AppCode: appctx.FromContext(ctx), + }, + CommandId: fmt.Sprintf("app-user-ban:%s:%d", requestID, userID), + TargetUserId: userID, + ExpiresAtMs: req.ExpiresAtMs, + OperatorAdminId: operatorAdminID, + Reason: reason, + }) + if err != nil { + return SetUserStatusResult{}, err + } + return s.userStatusResultFromAdminResponse(ctx, userID, response.GetStatus()) +} + +func (s *Service) AdminUnbanUser(ctx context.Context, userID int64, operatorAdminID int64, requestID string, req unbanUserRequest) (SetUserStatusResult, error) { + if s.userAdminClient == nil { + return SetUserStatusResult{}, fmt.Errorf("user service admin ban client is not configured") + } + if userID <= 0 || operatorAdminID <= 0 { + return SetUserStatusResult{}, fmt.Errorf("%w: 解封参数不正确", ErrInvalidArgument) + } + requestID = strings.TrimSpace(requestID) + if requestID == "" { + return SetUserStatusResult{}, fmt.Errorf("%w: request_id 不能为空", ErrInvalidArgument) + } + current, err := s.GetUser(ctx, userID) + if err != nil { + return SetUserStatusResult{}, err + } + // 历史 banned/disabled 用户没有独立 ban_id;这类永久兼容记录只能沿用旧状态接口手动恢复。 + if strings.TrimSpace(current.Ban.ID) == "" { + if current.Ban.Active && current.Ban.Source == "legacy" { + return s.SetUserStatus(ctx, userID, "active", operatorAdminID, requestID) + } + } + reason := strings.TrimSpace(req.Reason) + if reason == "" { + reason = "admin_app_user_unban" + } + nowMs := nowMillis() + response, err := s.userAdminClient.AdminUnbanUser(ctx, &userv1.AdminUnbanUserRequest{ + Meta: &userv1.RequestMeta{ + RequestId: requestID, + Caller: "hyapp-admin-server", + SentAtMs: nowMs, + AppCode: appctx.FromContext(ctx), + }, + // 摘要可能选中一条更晚到期的 manager 封禁;留空由 user-service 选择最新 admin 事实。 + BanId: "", + TargetUserId: userID, + OperatorAdminId: operatorAdminID, + Reason: reason, + }) + if err != nil { + return SetUserStatusResult{}, err + } + return s.userStatusResultFromAdminResponse(ctx, userID, response.GetStatus()) +} + +func (s *Service) userStatusResultFromAdminResponse(ctx context.Context, userID int64, status *userv1.SetUserStatusResponse) (SetUserStatusResult, error) { + user, err := s.GetUser(ctx, userID) + if err != nil { + return SetUserStatusResult{}, err + } + result := SetUserStatusResult{User: user} + if status == nil { + return result, nil + } + result.RevokedSessionCount = status.GetRevokedSessionCount() + result.AccessTokenRevoked = status.GetAccessTokenRevoked() + result.AccessTokenError = status.GetAccessTokenRevokeError() + result.IMKicked = status.GetImKicked() + result.IMKickError = status.GetImKickError() + result.RoomEvicted = status.GetRoomEvicted() + result.RoomID = status.GetRoomId() + result.RTCKicked = status.GetRtcKicked() + result.RTCKickError = status.GetRtcKickError() + result.RoomEvictError = status.GetRoomEvictError() + return result, nil +} + func (s *Service) SetPassword(ctx context.Context, userID int64, password string) error { if s.userDB == nil { return fmt.Errorf("user mysql is not configured") @@ -784,6 +1355,9 @@ func normalizeListQuery(query listQuery) listQuery { if query.EndMs < 0 { query.EndMs = 0 } + if query.SnapshotAtMs < 0 { + query.SnapshotAtMs = 0 + } query.Status = strings.ToLower(strings.TrimSpace(query.Status)) query.SortBy = normalizeAppUserSortBy(query.SortBy) query.SortDirection = normalizeSortDirection(query.SortDirection) @@ -833,6 +1407,16 @@ func appUserListWhereSQLAt(appCode string, query listQuery, nowMs int64) (string whereSQL += " AND u.created_at_ms < ?" args = append(args, query.EndMs) } + if query.SnapshotAtMs > 0 { + // 导出只读取任务创建时已经存在的用户,避免长任务执行期间的新注册插入到头部并改变分页集合。 + whereSQL += " AND u.created_at_ms <= ?" + args = append(args, query.SnapshotAtMs) + } + if query.ExportCursorCreatedAtMs > 0 && query.ExportCursorUserID > 0 { + // 导出固定 created_at DESC/user_id DESC,组合游标处理同毫秒注册且不依赖 OFFSET。 + whereSQL += " AND (u.created_at_ms < ? OR (u.created_at_ms = ? AND u.user_id < ?))" + args = append(args, query.ExportCursorCreatedAtMs, query.ExportCursorCreatedAtMs, query.ExportCursorUserID) + } return whereSQL, args } diff --git a/server/admin/internal/modules/appuser/service_test.go b/server/admin/internal/modules/appuser/service_test.go index d7ec538f..6882f7f7 100644 --- a/server/admin/internal/modules/appuser/service_test.go +++ b/server/admin/internal/modules/appuser/service_test.go @@ -3,6 +3,7 @@ package appuser import ( "strings" "testing" + "time" "hyapp-admin-server/internal/modules/shared" ) @@ -24,6 +25,68 @@ func TestNormalizeListQuerySort(t *testing.T) { } } +func TestAgeAtUTCBirthdayBoundary(t *testing.T) { + beforeBirthday := ageAtUTC("2000-07-11", time.Date(2026, time.July, 10, 23, 59, 59, 0, time.UTC)) + if beforeBirthday == nil || *beforeBirthday != 25 { + t.Fatalf("age before UTC birthday = %v, want 25", beforeBirthday) + } + onBirthday := ageAtUTC("2000-07-11", time.Date(2026, time.July, 11, 0, 0, 0, 0, time.UTC)) + if onBirthday == nil || *onBirthday != 26 { + t.Fatalf("age on UTC birthday = %v, want 26", onBirthday) + } + if got := ageAtUTC("", time.Now().UTC()); got != nil { + t.Fatalf("empty birth age = %v, want nil", got) + } +} + +func TestDisplayUserRolesSupportsMultipleIdentities(t *testing.T) { + roles := displayUserRoles([]string{"manager", "host", "bd_leader", "host", "unknown"}) + want := []string{"主播", "BD Leader", "经理"} + if strings.Join(roles, ",") != strings.Join(want, ",") { + t.Fatalf("roles = %#v, want %#v", roles, want) + } + ordinary := displayUserRoles(nil) + if len(ordinary) != 1 || ordinary[0] != "普通用户" { + t.Fatalf("ordinary roles = %#v", ordinary) + } +} + +func TestAppUserExportRowKeepsCompositeIdentityFieldsAndAddsColumns(t *testing.T) { + age := int32(26) + item := AppUser{ + UserID: "10001", + DefaultDisplayUserID: "1299324", + PrettyDisplayUserID: "11222", + Username: "sumon Ahammad", + Avatar: "https://example.test/avatar.png", + Age: &age, + Roles: []string{"主播", "经理"}, + Levels: AppUserLevels{ + Wealth: AppUserLevel{RealLevel: 8, DisplayLevel: 14, TemporaryTargetLevel: 14, ExpiresAtMs: 1234}, + Charm: AppUserLevel{RealLevel: 9, DisplayLevel: 15, TemporaryTargetLevel: 15, ExpiresAtMs: 5678}, + Game: AppUserLevel{DisplayLevel: 6}, + }, + } + row := appUserExportRow(item) + if len(row) != len(appUserExportHeaders()) { + t.Fatalf("export row columns = %d, headers = %d", len(row), len(appUserExportHeaders())) + } + if row[0] != "10001" || row[1] != "1299324" || row[2] != "11222" || row[3] != "sumon Ahammad" || row[4] != "https://example.test/avatar.png" { + t.Fatalf("identity columns changed: %#v", row[:5]) + } +} + +func TestSpreadsheetSafeCSVCellEscapesFormulaPrefixes(t *testing.T) { + for _, value := range []string{"=HYPERLINK(\"https://example.test\")", "+cmd", " -1+1", "@SUM(A1:A2)"} { + if got := spreadsheetSafeCSVCell(value); !strings.HasPrefix(got, "'") { + t.Fatalf("dangerous CSV cell %q was not escaped: %q", value, got) + } + } + if got := spreadsheetSafeCSVCell("normal user"); got != "normal user" { + t.Fatalf("normal CSV cell changed: %q", got) + } +} + func TestAppUserListWhereSQLFilters(t *testing.T) { whereSQL, args := appUserListWhereSQL("lalu", normalizeListQuery(listQuery{ Country: "ph", diff --git a/server/admin/internal/modules/dashboard/service.go b/server/admin/internal/modules/dashboard/service.go index 1274a45a..070c1364 100644 --- a/server/admin/internal/modules/dashboard/service.go +++ b/server/admin/internal/modules/dashboard/service.go @@ -57,16 +57,17 @@ type AppTrackingFunnelQuery struct { } type SocialRequirementsQuery struct { - AppCode string - StatTZ string - StartMS int64 - EndMS int64 - RegionID int64 - RegionIDs []int64 - CountryID int64 - Section string - UserRole string - PayerType string + AppCode string + StatTZ string + StartMS int64 + EndMS int64 + RegionID int64 + RegionIDs []int64 + CountryID int64 + Section string + UserRole string + PayerType string + NewUserType string } type PlatformGrantStatisticsQuery struct { @@ -260,6 +261,9 @@ func (s *DashboardService) SocialRequirements(ctx context.Context, query SocialR if payerType := strings.TrimSpace(query.PayerType); payerType != "" { values.Set("payer_type", payerType) } + if newUserType := strings.TrimSpace(query.NewUserType); newUserType != "" { + values.Set("new_user_type", newUserType) + } // Social BI 数据需求只读 statistics-service 聚合投影;admin 不直接拼 owner service 明细或跨库查询。 return s.statisticsGET(ctx, "/internal/v1/statistics/social/requirements", values) } diff --git a/server/admin/internal/modules/databi/handler.go b/server/admin/internal/modules/databi/handler.go index ed517d0d..918f3889 100644 --- a/server/admin/internal/modules/databi/handler.go +++ b/server/admin/internal/modules/databi/handler.go @@ -78,15 +78,16 @@ func (h *Handler) Requirements(c *gin.Context) { return } result, err := h.service.Requirements(c.Request.Context(), access, RequirementsQuery{ - StatTZ: c.Query("stat_tz"), - StartMS: queryInt64(c, "start_ms"), - EndMS: queryInt64(c, "end_ms"), - AppCodes: splitCSV(c.Query("app_codes")), - RegionID: queryInt64(c, "region_id"), - RegionIDs: queryInt64CSV(c.Query("region_ids")), - Section: c.Query("section"), - UserRole: c.Query("user_role"), - PayerType: c.Query("payer_type"), + StatTZ: c.Query("stat_tz"), + StartMS: queryInt64(c, "start_ms"), + EndMS: queryInt64(c, "end_ms"), + AppCodes: splitCSV(c.Query("app_codes")), + RegionID: queryInt64(c, "region_id"), + RegionIDs: queryInt64CSV(c.Query("region_ids")), + Section: c.Query("section"), + UserRole: c.Query("user_role"), + PayerType: c.Query("payer_type"), + NewUserType: c.Query("new_user_type"), }) if err != nil { response.ServerError(c, "获取数据需求指标失败") diff --git a/server/admin/internal/modules/databi/service.go b/server/admin/internal/modules/databi/service.go index d8d310e7..9f8409ce 100644 --- a/server/admin/internal/modules/databi/service.go +++ b/server/admin/internal/modules/databi/service.go @@ -298,15 +298,16 @@ type FunnelResult struct { } type RequirementsQuery struct { - StatTZ string - StartMS int64 - EndMS int64 - AppCodes []string - RegionID int64 - RegionIDs []int64 - Section string - UserRole string - PayerType string + StatTZ string + StartMS int64 + EndMS int64 + AppCodes []string + RegionID int64 + RegionIDs []int64 + Section string + UserRole string + PayerType string + NewUserType string } type AppRequirements struct { @@ -466,15 +467,16 @@ func (s *Service) appRequirements(ctx context.Context, app AppInfo, regions []Re regionIDs = requestRegionIDs } requirements, err := s.dashboards.SocialRequirements(ctx, dashboard.SocialRequirementsQuery{ - AppCode: app.AppCode, - StatTZ: query.StatTZ, - StartMS: query.StartMS, - EndMS: query.EndMS, - RegionID: query.RegionID, - RegionIDs: regionIDs, - Section: query.Section, - UserRole: query.UserRole, - PayerType: query.PayerType, + AppCode: app.AppCode, + StatTZ: query.StatTZ, + StartMS: query.StartMS, + EndMS: query.EndMS, + RegionID: query.RegionID, + RegionIDs: regionIDs, + Section: query.Section, + UserRole: query.UserRole, + PayerType: query.PayerType, + NewUserType: query.NewUserType, }) if err != nil { out.Error = fmt.Sprintf("获取数据需求指标失败: %v", err) diff --git a/server/admin/internal/modules/job/handler.go b/server/admin/internal/modules/job/handler.go index b4b82e48..356e7877 100644 --- a/server/admin/internal/modules/job/handler.go +++ b/server/admin/internal/modules/job/handler.go @@ -5,6 +5,8 @@ import ( "path/filepath" "hyapp-admin-server/internal/config" + "hyapp-admin-server/internal/middleware" + "hyapp-admin-server/internal/model" "hyapp-admin-server/internal/modules/shared" "hyapp-admin-server/internal/repository" "hyapp-admin-server/internal/response" @@ -41,6 +43,10 @@ func (h *Handler) GetJob(c *gin.Context) { response.BadRequest(c, "任务不存在") return } + if !canReadJob(c, job) { + response.Forbidden(c, "没有查看该任务的权限") + return + } response.OK(c, job) } @@ -72,6 +78,15 @@ func (h *Handler) DownloadJobArtifact(c *gin.Context) { if !ok { return } + job, err := h.service.GetJob(id) + if err != nil { + response.BadRequest(c, "任务不存在") + return + } + if !canReadJob(c, job) { + response.Forbidden(c, "没有下载该任务的权限") + return + } _, artifactPath, err := h.service.JobArtifact(id) if err != nil { response.BadRequest(c, err.Error()) @@ -81,3 +96,16 @@ func (h *Handler) DownloadJobArtifact(c *gin.Context) { c.Header("Content-Disposition", "attachment; filename="+filepath.Base(artifactPath)) c.File(artifactPath) } + +func canReadJob(c *gin.Context, job *model.AdminJob) bool { + if job == nil { + return false + } + if middleware.HasAnyPermission(c, "job:view", "country:update") { + return true + } + // app-user:export 只允许读取本人创建的用户导出,不能借任务 ID 查看其他后台任务或他人的 CSV。 + return middleware.HasPermission(c, "app-user:export") && + job.Type == "app-user-export" && + job.CreatedBy == middleware.CurrentUserID(c) +} diff --git a/server/admin/internal/modules/job/handler_test.go b/server/admin/internal/modules/job/handler_test.go new file mode 100644 index 00000000..260a3b41 --- /dev/null +++ b/server/admin/internal/modules/job/handler_test.go @@ -0,0 +1,34 @@ +package job + +import ( + "net/http/httptest" + "testing" + + "hyapp-admin-server/internal/middleware" + "hyapp-admin-server/internal/model" + + "github.com/gin-gonic/gin" +) + +func TestCanReadJobScopesAppUserExportToCreator(t *testing.T) { + gin.SetMode(gin.TestMode) + context, _ := gin.CreateTestContext(httptest.NewRecorder()) + context.Set(middleware.ContextUserID, uint(7)) + context.Set(middleware.ContextPermissions, []string{"app-user:export"}) + + owned := &model.AdminJob{ID: 1, Type: "app-user-export", CreatedBy: 7} + if !canReadJob(context, owned) { + t.Fatal("app-user exporter must read own export job") + } + if canReadJob(context, &model.AdminJob{ID: 2, Type: "app-user-export", CreatedBy: 8}) { + t.Fatal("app-user exporter must not read another operator's export") + } + if canReadJob(context, &model.AdminJob{ID: 3, Type: "country-code-rename", CreatedBy: 7}) { + t.Fatal("app-user exporter must not read unrelated job types") + } + + context.Set(middleware.ContextPermissions, []string{"job:view"}) + if !canReadJob(context, &model.AdminJob{ID: 4, Type: "country-code-rename", CreatedBy: 8}) { + t.Fatal("job viewer must retain broad read access") + } +} diff --git a/server/admin/internal/modules/job/routes.go b/server/admin/internal/modules/job/routes.go index e7c8ea16..9e2f0d05 100644 --- a/server/admin/internal/modules/job/routes.go +++ b/server/admin/internal/modules/job/routes.go @@ -8,8 +8,8 @@ import ( func RegisterRoutes(protected *gin.RouterGroup, h *Handler) { protected.GET("/jobs", middleware.RequirePermission("job:view"), h.ListJobs) - protected.GET("/jobs/:id", middleware.RequireAnyPermission("job:view", "country:update"), h.GetJob) + protected.GET("/jobs/:id", middleware.RequireAnyPermission("job:view", "country:update", "app-user:export"), h.GetJob) protected.POST("/jobs/:id/cancel", middleware.RequirePermission("job:cancel"), h.CancelJob) - protected.GET("/jobs/:id/artifact", middleware.RequirePermission("job:view"), h.DownloadJobArtifact) + protected.GET("/jobs/:id/artifact", middleware.RequireAnyPermission("job:view", "app-user:export"), h.DownloadJobArtifact) protected.POST("/exports/users", middleware.RequirePermission("export:create"), h.CreateUserExportJob) } diff --git a/server/admin/internal/modules/resource/handler.go b/server/admin/internal/modules/resource/handler.go index 4bc906ae..53ce8041 100644 --- a/server/admin/internal/modules/resource/handler.go +++ b/server/admin/internal/modules/resource/handler.go @@ -639,6 +639,10 @@ func (h *Handler) GrantResource(c *gin.Context) { response.BadRequest(c, err.Error()) return } + if err := h.validateGenericGrantResource(c, req.ResourceID); err != nil { + response.BadRequest(c, err.Error()) + return + } resp, err := h.wallet.GrantResource(c.Request.Context(), &walletv1.GrantResourceRequest{ CommandId: strings.TrimSpace(req.CommandID), AppCode: appctx.FromContext(c.Request.Context()), @@ -670,6 +674,10 @@ func (h *Handler) GrantResourceGroup(c *gin.Context) { response.BadRequest(c, err.Error()) return } + if err := h.validateGenericGrantGroup(c, req.GroupID); err != nil { + response.BadRequest(c, err.Error()) + return + } resp, err := h.wallet.GrantResourceGroup(c.Request.Context(), &walletv1.GrantResourceGroupRequest{ CommandId: strings.TrimSpace(req.CommandID), AppCode: appctx.FromContext(c.Request.Context()), @@ -688,6 +696,53 @@ func (h *Handler) GrantResourceGroup(c *gin.Context) { response.Created(c, grant) } +func (h *Handler) validateGenericGrantResource(c *gin.Context, resourceID int64) error { + resp, err := h.wallet.GetResource(c.Request.Context(), &walletv1.GetResourceRequest{ + RequestId: middleware.CurrentRequestID(c), + AppCode: appctx.FromContext(c.Request.Context()), + ResourceId: resourceID, + }) + if err != nil { + return err + } + // VIP 体验卡除了资源权益,还必须同步写入卡片等级、独立失效时间和 VIP 状态投影; + // 通用资源赠送只会创建 entitlement,放行会产生“背包可见但无法生效”的半成品数据。 + if resp.GetResource().GetResourceType() == resourceTypeVIPTrialCard { + return fmt.Errorf("VIP 体验卡必须通过 VIP 配置页赠送") + } + return nil +} + +func (h *Handler) validateGenericGrantGroup(c *gin.Context, groupID int64) error { + resp, err := h.wallet.GetResourceGroup(c.Request.Context(), &walletv1.GetResourceGroupRequest{ + RequestId: middleware.CurrentRequestID(c), + AppCode: appctx.FromContext(c.Request.Context()), + GroupId: groupID, + }) + if err != nil { + return err + } + for _, item := range resp.GetGroup().GetItems() { + resourceType := item.GetResource().GetResourceType() + // 老资源组数据可能只返回 resource_id;逐项回查可防止因嵌套 Resource 缺失而绕过体验卡专用发放链路。 + if resourceType == "" && item.GetResourceId() > 0 { + resourceResp, err := h.wallet.GetResource(c.Request.Context(), &walletv1.GetResourceRequest{ + RequestId: middleware.CurrentRequestID(c), + AppCode: appctx.FromContext(c.Request.Context()), + ResourceId: item.GetResourceId(), + }) + if err != nil { + return err + } + resourceType = resourceResp.GetResource().GetResourceType() + } + if resourceType == resourceTypeVIPTrialCard { + return fmt.Errorf("包含 VIP 体验卡的资源组必须通过 VIP 配置页赠送") + } + } + return nil +} + func (h *Handler) RevokeResourceGrant(c *gin.Context) { grantID := strings.TrimSpace(c.Param("grant_id")) if grantID == "" { diff --git a/server/admin/internal/modules/resource/handler_test.go b/server/admin/internal/modules/resource/handler_test.go index 5ff4c77c..5924530e 100644 --- a/server/admin/internal/modules/resource/handler_test.go +++ b/server/admin/internal/modules/resource/handler_test.go @@ -220,6 +220,73 @@ func TestIdentityAutoGrantConfigRouteDoesNotHitResourceGroupID(t *testing.T) { } } +func TestGenericResourceGrantRejectsVIPTrialCard(t *testing.T) { + wallet := &mockResourceWallet{resources: map[int64]*walletv1.Resource{ + 99: {AppCode: "lalu", ResourceId: 99, ResourceCode: "vip_trial_5", ResourceType: resourceTypeVIPTrialCard, Name: "VIP5体验卡"}, + }} + router := newResourceHandlerTestRouter(New(wallet, nil, nil, time.Second, nil)) + recorder := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodPost, "/admin/resource-grants/resource", strings.NewReader(`{"commandId":"grant-1","targetUserId":"318705991371722752","resourceId":99,"quantity":1,"durationMs":86400000,"reason":"manual"}`)) + request.Header.Set("Content-Type", "application/json") + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusBadRequest || !strings.Contains(recorder.Body.String(), "VIP 体验卡必须通过 VIP 配置页赠送") { + t.Fatalf("generic grant must reject vip trial card: status=%d body=%s", recorder.Code, recorder.Body.String()) + } +} + +func TestGenericResourceGroupGrantRejectsVIPTrialCardItem(t *testing.T) { + wallet := &mockResourceWallet{resourceGroups: map[int64]*walletv1.ResourceGroup{ + 88: { + AppCode: "lalu", + GroupId: 88, + Items: []*walletv1.ResourceGroupItem{{ + ResourceId: 99, + Resource: &walletv1.Resource{ResourceId: 99, ResourceType: resourceTypeVIPTrialCard}, + }}, + }, + }} + router := newResourceHandlerTestRouter(New(wallet, nil, nil, time.Second, nil)) + recorder := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodPost, "/admin/resource-grants/group", strings.NewReader(`{"commandId":"grant-group-1","targetUserId":"318705991371722752","groupId":88,"reason":"manual"}`)) + request.Header.Set("Content-Type", "application/json") + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusBadRequest || !strings.Contains(recorder.Body.String(), "包含 VIP 体验卡的资源组必须通过 VIP 配置页赠送") { + t.Fatalf("generic group grant must reject vip trial card: status=%d body=%s", recorder.Code, recorder.Body.String()) + } +} + +func TestVIPGrantPermissionCanLookupResourceGrantTarget(t *testing.T) { + db, sqlMock, err := sqlmock.New() + if err != nil { + t.Fatalf("create sql mock failed: %v", err) + } + defer db.Close() + sqlMock.ExpectQuery(`(?s)SELECT u\.user_id.*FROM users u.*LIMIT 1`). + WillReturnRows(sqlmock.NewRows([]string{"user_id", "current_display_user_id", "username", "avatar"}).AddRow(int64(318705991371722752), "111", "target", "avatar.png")) + + gin.SetMode(gin.TestMode) + router := gin.New() + router.Use(func(c *gin.Context) { + c.Request = c.Request.WithContext(appctx.WithContext(c.Request.Context(), "lalu")) + c.Set(middleware.ContextRequestID, "vip-target-test") + c.Set(middleware.ContextPermissions, []string{"vip-config:grant"}) + c.Next() + }) + RegisterRoutes(router.Group(""), New(&mockResourceWallet{}, nil, db, time.Second, nil)) + recorder := httptest.NewRecorder() + request := httptest.NewRequest(http.MethodGet, "/admin/resource-grants/target?keyword=111", nil) + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK || !strings.Contains(recorder.Body.String(), `"userId":"318705991371722752"`) { + t.Fatalf("vip grant permission should resolve target: status=%d body=%s", recorder.Code, recorder.Body.String()) + } + if err := sqlMock.ExpectationsWereMet(); err != nil { + t.Fatalf("lookup sql mismatch: %v", err) + } +} + func TestListResourceGrantsResolvesDisplayIDBeforeWalletFilter(t *testing.T) { db, sqlMock, err := sqlmock.New() if err != nil { @@ -304,6 +371,7 @@ 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 @@ -320,6 +388,14 @@ func (m *mockResourceWallet) GetResource(ctx context.Context, req *walletv1.GetR return &walletv1.GetResourceResponse{Resource: resource}, nil } +func (m *mockResourceWallet) GetResourceGroup(_ context.Context, req *walletv1.GetResourceGroupRequest) (*walletv1.GetResourceGroupResponse, error) { + group := m.resourceGroups[req.GetGroupId()] + if group == nil { + return nil, fmt.Errorf("resource group not found") + } + return &walletv1.GetResourceGroupResponse{Group: group}, nil +} + func (m *mockResourceWallet) UpdateResource(ctx context.Context, req *walletv1.UpdateResourceRequest) (*walletv1.ResourceResponse, error) { m.updates = append(m.updates, req) return &walletv1.ResourceResponse{Resource: &walletv1.Resource{ diff --git a/server/admin/internal/modules/resource/request.go b/server/admin/internal/modules/resource/request.go index 4680e45a..c10ae0be 100644 --- a/server/admin/internal/modules/resource/request.go +++ b/server/admin/internal/modules/resource/request.go @@ -18,11 +18,12 @@ import ( const dayMillis int64 = 24 * 60 * 60 * 1000 const ( - resourceTypeCoin = "coin" - resourceTypeAvatarFrame = "avatar_frame" - resourceTypeBadge = "badge" - resourceTypeEmojiPack = "emoji_pack" - resourceTypeProfileCard = "profile_card" + resourceTypeCoin = "coin" + resourceTypeAvatarFrame = "avatar_frame" + resourceTypeBadge = "badge" + resourceTypeEmojiPack = "emoji_pack" + resourceTypeProfileCard = "profile_card" + resourceTypeVIPTrialCard = "vip_trial_card" ) const ( diff --git a/server/admin/internal/modules/resource/routes.go b/server/admin/internal/modules/resource/routes.go index ce6aeaf3..0c4b6e76 100644 --- a/server/admin/internal/modules/resource/routes.go +++ b/server/admin/internal/modules/resource/routes.go @@ -49,7 +49,8 @@ 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.GET("/admin/resource-grants/target", middleware.RequirePermission("resource-grant:create"), h.LookupResourceGrantTarget) + // 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) protected.GET("/admin/resource-shop/purchase-orders", middleware.RequirePermission("resource-shop:view"), h.ListResourceShopPurchaseOrders) diff --git a/server/admin/internal/modules/vipconfig/handler.go b/server/admin/internal/modules/vipconfig/handler.go index e8e30488..d0bf5a66 100644 --- a/server/admin/internal/modules/vipconfig/handler.go +++ b/server/admin/internal/modules/vipconfig/handler.go @@ -27,6 +27,10 @@ type configRequest struct { Levels []vipLevelDTO `json:"levels"` } +type programRequest struct { + Config *vipProgramConfigDTO `json:"config"` +} + type grantVipRequest struct { CommandID string `json:"commandId"` TargetUserID any `json:"targetUserId"` @@ -34,9 +38,25 @@ type grantVipRequest struct { Reason string `json:"reason"` } +type grantVipTrialCardRequest struct { + CommandID string `json:"commandId"` + TargetUserID any `json:"targetUserId"` + Level int32 `json:"level"` + DurationMS int64 `json:"durationMs"` + ResourceID *int64 `json:"resourceId"` + Reason string `json:"reason"` +} + type configDTO struct { - Levels []vipLevelDTO `json:"levels"` - ServerTimeMS int64 `json:"serverTimeMs"` + Levels []vipLevelDTO `json:"levels"` + ProgramConfig vipProgramConfigDTO `json:"programConfig"` + ServerTimeMS int64 `json:"serverTimeMs"` +} + +type programDTO struct { + Config vipProgramConfigDTO `json:"config"` + Benefits []vipBenefitDTO `json:"benefits"` + ServerTimeMS int64 `json:"serverTimeMs"` } type grantVipDTO struct { @@ -46,30 +66,103 @@ type grantVipDTO struct { ServerTimeMS int64 `json:"serverTimeMs"` } +type grantVipTrialCardDTO struct { + TrialCard vipTrialCardDTO `json:"trialCard"` + State vipStateDTO `json:"state"` + ServerTimeMS int64 `json:"serverTimeMs"` +} + type userVipDTO struct { - UserID string `json:"userId"` - Level int32 `json:"level"` - Name string `json:"name"` - Active bool `json:"active"` - StartedAtMS int64 `json:"startedAtMs"` - ExpiresAtMS int64 `json:"expiresAtMs"` - UpdatedAtMS int64 `json:"updatedAtMs"` + UserID string `json:"userId"` + Level int32 `json:"level"` + Name string `json:"name"` + Active bool `json:"active"` + StartedAtMS int64 `json:"startedAtMs"` + ExpiresAtMS int64 `json:"expiresAtMs"` + UpdatedAtMS int64 `json:"updatedAtMs"` + ProgramType string `json:"programType"` + ConfigVersion int64 `json:"configVersion"` } type vipLevelDTO struct { - Level int32 `json:"level"` - Name string `json:"name"` - Status string `json:"status"` - PriceCoin int64 `json:"priceCoin"` - DurationMS int64 `json:"durationMs"` - RewardResourceGroupID int64 `json:"rewardResourceGroupId"` - SortOrder int32 `json:"sortOrder"` - RechargeGateRequired bool `json:"rechargeGateRequired"` - RequiredRechargeCoinAmount int64 `json:"requiredRechargeCoinAmount"` - UserRechargeCoinAmount int64 `json:"userRechargeCoinAmount"` - PurchaseLockedReason string `json:"purchaseLockedReason"` - CreatedAtMS int64 `json:"createdAtMs"` - UpdatedAtMS int64 `json:"updatedAtMs"` + Level int32 `json:"level"` + Name string `json:"name"` + Status string `json:"status"` + PriceCoin int64 `json:"priceCoin"` + DurationMS int64 `json:"durationMs"` + RewardResourceGroupID int64 `json:"rewardResourceGroupId"` + SortOrder int32 `json:"sortOrder"` + RechargeGateRequired bool `json:"rechargeGateRequired"` + RequiredRechargeCoinAmount int64 `json:"requiredRechargeCoinAmount"` + UserRechargeCoinAmount int64 `json:"userRechargeCoinAmount"` + PurchaseLockedReason string `json:"purchaseLockedReason"` + CreatedAtMS int64 `json:"createdAtMs"` + UpdatedAtMS int64 `json:"updatedAtMs"` + Benefits []vipBenefitDTO `json:"benefits"` + ConfigVersion int64 `json:"configVersion"` +} + +type vipProgramConfigDTO struct { + AppCode string `json:"appCode"` + ProgramType string `json:"programType"` + LevelCount int32 `json:"levelCount"` + SameLevelExpiryPolicy string `json:"sameLevelExpiryPolicy"` + UpgradeExpiryPolicy string `json:"upgradeExpiryPolicy"` + DowngradePurchasePolicy string `json:"downgradePurchasePolicy"` + BenefitInheritancePolicy string `json:"benefitInheritancePolicy"` + GrantMode string `json:"grantMode"` + TrialCardEnabled bool `json:"trialCardEnabled"` + Status string `json:"status"` + ConfigVersion int64 `json:"configVersion"` + UpdatedByAdminID int64 `json:"updatedByAdminId"` + CreatedAtMS int64 `json:"createdAtMs"` + UpdatedAtMS int64 `json:"updatedAtMs"` +} + +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"` +} + +type vipTrialCardDTO struct { + TrialCardID string `json:"trialCardId"` + EntitlementID string `json:"entitlementId"` + ResourceID int64 `json:"resourceId"` + UserID string `json:"userId"` + Level int32 `json:"level"` + Name string `json:"name"` + Status string `json:"status"` + Equipped bool `json:"equipped"` + DurationMS int64 `json:"durationMs"` + EffectiveAtMS int64 `json:"effectiveAtMs"` + ExpiresAtMS int64 `json:"expiresAtMs"` + RemainingDurationMS int64 `json:"remainingDurationMs"` + GrantSource string `json:"grantSource"` + SourceGrantID string `json:"sourceGrantId"` + CreatedAtMS int64 `json:"createdAtMs"` + UpdatedAtMS int64 `json:"updatedAtMs"` +} + +type vipStateDTO struct { + PaidVIP userVipDTO `json:"paidVip"` + EquippedTrialCard vipTrialCardDTO `json:"equippedTrialCard"` + EffectiveVIP userVipDTO `json:"effectiveVip"` + EffectiveSource string `json:"effectiveSource"` + EffectiveBenefits []vipBenefitDTO `json:"effectiveBenefits"` + EvaluatedAtMS int64 `json:"evaluatedAtMs"` + ProgramConfig vipProgramConfigDTO `json:"programConfig"` } type vipRewardItemDTO struct { @@ -81,6 +174,59 @@ type vipRewardItemDTO struct { ExpiresAtMS int64 `json:"expiresAtMs"` } +func (h *Handler) GetProgram(c *gin.Context) { + resp, err := h.wallet.GetVipProgramConfig(c.Request.Context(), &walletv1.GetVipProgramConfigRequest{ + RequestId: middleware.CurrentRequestID(c), + AppCode: appctx.FromContext(c.Request.Context()), + }) + if err != nil { + response.ServerError(c, "获取 VIP 体系失败") + return + } + // 体系规则与权益目录同次返回,保证后台切换 App 后不会把上一 App 的权益矩阵误带入当前表单。 + response.OK(c, programDTO{ + Config: vipProgramConfigFromProto(resp.GetConfig()), + Benefits: vipBenefitsFromProto(resp.GetBenefits()), + ServerTimeMS: resp.GetServerTimeMs(), + }) +} + +func (h *Handler) UpdateProgram(c *gin.Context) { + var req programRequest + if err := c.ShouldBindJSON(&req); err != nil || req.Config == nil { + response.BadRequest(c, "VIP 体系参数不正确") + return + } + config := req.Config.toProto() + if config.GetLevelCount() <= 0 || strings.TrimSpace(config.GetProgramType()) == "" || strings.TrimSpace(config.GetStatus()) == "" { + response.BadRequest(c, "VIP 体系参数不正确") + return + } + appCode := appctx.FromContext(c.Request.Context()) + // AppCode、版本和审计操作者只取服务端上下文;即使客户端提交同名字段也不能跨 App 或伪造审计信息。 + config.AppCode = appCode + config.ConfigVersion = 0 + config.UpdatedByAdminId = 0 + config.CreatedAtMs = 0 + config.UpdatedAtMs = 0 + resp, err := h.wallet.UpdateAdminVipProgramConfig(c.Request.Context(), &walletv1.UpdateAdminVipProgramConfigRequest{ + RequestId: middleware.CurrentRequestID(c), + AppCode: appCode, + Config: config, + OperatorUserId: int64(middleware.CurrentUserID(c)), + }) + if err != nil { + response.BadRequest(c, err.Error()) + return + } + shared.OperationLogWithResourceID(c, h.audit, "update-vip-program", "vip_program_configs", appCode, "success", resp.GetConfig().GetProgramType()) + response.OK(c, programDTO{ + Config: vipProgramConfigFromProto(resp.GetConfig()), + Benefits: []vipBenefitDTO{}, + ServerTimeMS: resp.GetServerTimeMs(), + }) +} + func (h *Handler) ListLevels(c *gin.Context) { resp, err := h.wallet.ListAdminVipLevels(c.Request.Context(), &walletv1.ListAdminVipLevelsRequest{ RequestId: middleware.CurrentRequestID(c), @@ -90,7 +236,11 @@ func (h *Handler) ListLevels(c *gin.Context) { response.ServerError(c, "获取 VIP 配置失败") return } - response.OK(c, configDTO{Levels: vipLevelsFromProto(resp.GetLevels()), ServerTimeMS: resp.GetServerTimeMs()}) + response.OK(c, configDTO{ + Levels: vipLevelsFromProto(resp.GetLevels()), + ProgramConfig: vipProgramConfigFromProto(resp.GetProgramConfig()), + ServerTimeMS: resp.GetServerTimeMs(), + }) } func (h *Handler) GrantVIP(c *gin.Context) { @@ -130,6 +280,46 @@ func (h *Handler) GrantVIP(c *gin.Context) { response.Created(c, grantVipFromProto(resp)) } +func (h *Handler) GrantVIPTrialCard(c *gin.Context) { + var req grantVipTrialCardRequest + if err := c.ShouldBindJSON(&req); err != nil { + response.BadRequest(c, "VIP 体验卡赠送参数不正确") + return + } + targetUserID, ok := parseFlexibleUserID(req.TargetUserID) + if !ok || req.Level <= 0 || req.DurationMS <= 0 || (req.ResourceID != nil && *req.ResourceID <= 0) { + response.BadRequest(c, "VIP 体验卡赠送参数不正确") + return + } + reason := strings.TrimSpace(req.Reason) + if reason == "" { + response.BadRequest(c, "赠送原因不能为空") + return + } + commandID := strings.TrimSpace(req.CommandID) + if commandID == "" { + commandID = "admin_vip_trial_card_grant:" + middleware.CurrentRequestID(c) + } + resp, err := h.wallet.GrantVipTrialCard(c.Request.Context(), &walletv1.GrantVipTrialCardRequest{ + CommandId: commandID, + AppCode: appctx.FromContext(c.Request.Context()), + TargetUserId: targetUserID, + Level: req.Level, + DurationMs: req.DurationMS, + ResourceId: req.ResourceID, + GrantSource: "admin_grant", + OperatorUserId: int64(middleware.CurrentUserID(c)), + Reason: reason, + }) + if err != nil { + response.BadRequest(c, err.Error()) + return + } + // 体验卡是独立背包实例,审计目标使用 trial_card_id,后续切换佩戴不会覆盖本次赠送记录。 + shared.OperationLogWithResourceID(c, h.audit, "grant-vip-trial-card", "user_vip_trial_cards", resp.GetTrialCard().GetTrialCardId(), "success", "target_user_id="+strconv.FormatInt(targetUserID, 10)) + response.Created(c, grantVipTrialCardFromProto(resp)) +} + func (h *Handler) UpdateLevels(c *gin.Context) { var req configRequest if err := c.ShouldBindJSON(&req); err != nil { @@ -138,6 +328,10 @@ func (h *Handler) UpdateLevels(c *gin.Context) { } input := make([]*walletv1.AdminVipLevelInput, 0, len(req.Levels)) for _, level := range req.Levels { + benefits := make([]*walletv1.VipBenefit, 0, len(level.Benefits)) + for _, benefit := range level.Benefits { + benefits = append(benefits, benefit.toProto()) + } input = append(input, &walletv1.AdminVipLevelInput{ Level: level.Level, Name: strings.TrimSpace(level.Name), @@ -148,6 +342,7 @@ func (h *Handler) UpdateLevels(c *gin.Context) { // VIP 累充门槛已下线;后台旧请求即使携带旧字段,也统一写 0,避免旧页面或缓存把门槛重新保存回来。 RequiredRechargeCoinAmount: 0, SortOrder: level.SortOrder, + Benefits: benefits, }) } resp, err := h.wallet.UpdateAdminVipLevels(c.Request.Context(), &walletv1.UpdateAdminVipLevelsRequest{ @@ -161,7 +356,11 @@ func (h *Handler) UpdateLevels(c *gin.Context) { return } shared.OperationLogWithResourceID(c, h.audit, "update-vip-config", "vip_levels", appctx.FromContext(c.Request.Context()), "success", strconv.Itoa(len(resp.GetLevels()))) - response.OK(c, configDTO{Levels: vipLevelsFromProto(resp.GetLevels()), ServerTimeMS: resp.GetServerTimeMs()}) + response.OK(c, configDTO{ + Levels: vipLevelsFromProto(resp.GetLevels()), + ProgramConfig: vipProgramConfigFromProto(resp.GetProgramConfig()), + ServerTimeMS: resp.GetServerTimeMs(), + }) } func vipLevelsFromProto(items []*walletv1.VipLevel) []vipLevelDTO { @@ -185,11 +384,92 @@ func vipLevelsFromProto(items []*walletv1.VipLevel) []vipLevelDTO { PurchaseLockedReason: item.GetPurchaseLockedReason(), CreatedAtMS: item.GetCreatedAtMs(), UpdatedAtMS: item.GetUpdatedAtMs(), + Benefits: vipBenefitsFromProto(item.GetBenefits()), + ConfigVersion: item.GetConfigVersion(), }) } return levels } +func vipProgramConfigFromProto(item *walletv1.VipProgramConfig) vipProgramConfigDTO { + if item == nil { + return vipProgramConfigDTO{} + } + return vipProgramConfigDTO{ + AppCode: item.GetAppCode(), + ProgramType: item.GetProgramType(), + LevelCount: item.GetLevelCount(), + SameLevelExpiryPolicy: item.GetSameLevelExpiryPolicy(), + UpgradeExpiryPolicy: item.GetUpgradeExpiryPolicy(), + DowngradePurchasePolicy: item.GetDowngradePurchasePolicy(), + BenefitInheritancePolicy: item.GetBenefitInheritancePolicy(), + GrantMode: item.GetGrantMode(), + TrialCardEnabled: item.GetTrialCardEnabled(), + Status: item.GetStatus(), + ConfigVersion: item.GetConfigVersion(), + UpdatedByAdminID: item.GetUpdatedByAdminId(), + CreatedAtMS: item.GetCreatedAtMs(), + UpdatedAtMS: item.GetUpdatedAtMs(), + } +} + +func (item vipProgramConfigDTO) toProto() *walletv1.VipProgramConfig { + return &walletv1.VipProgramConfig{ + ProgramType: strings.TrimSpace(item.ProgramType), + LevelCount: item.LevelCount, + SameLevelExpiryPolicy: strings.TrimSpace(item.SameLevelExpiryPolicy), + UpgradeExpiryPolicy: strings.TrimSpace(item.UpgradeExpiryPolicy), + DowngradePurchasePolicy: strings.TrimSpace(item.DowngradePurchasePolicy), + BenefitInheritancePolicy: strings.TrimSpace(item.BenefitInheritancePolicy), + GrantMode: strings.TrimSpace(item.GrantMode), + TrialCardEnabled: item.TrialCardEnabled, + Status: strings.TrimSpace(item.Status), + } +} + +func vipBenefitsFromProto(items []*walletv1.VipBenefit) []vipBenefitDTO { + benefits := make([]vipBenefitDTO, 0, len(items)) + for _, item := range items { + if item == nil { + continue + } + benefits = append(benefits, vipBenefitDTO{ + BenefitCode: item.GetBenefitCode(), + Name: item.GetName(), + BenefitType: item.GetBenefitType(), + UnlockLevel: item.GetUnlockLevel(), + Status: item.GetStatus(), + TrialEnabled: item.GetTrialEnabled(), + ResourceID: item.GetResourceId(), + ResourceType: item.GetResourceType(), + ExecutionScope: item.GetExecutionScope(), + AutoEquip: item.GetAutoEquip(), + SortOrder: item.GetSortOrder(), + MetadataJSON: item.GetMetadataJson(), + CreatedAtMS: item.GetCreatedAtMs(), + UpdatedAtMS: item.GetUpdatedAtMs(), + }) + } + return benefits +} + +func (item vipBenefitDTO) toProto() *walletv1.VipBenefit { + return &walletv1.VipBenefit{ + BenefitCode: strings.TrimSpace(item.BenefitCode), + Name: strings.TrimSpace(item.Name), + BenefitType: strings.TrimSpace(item.BenefitType), + UnlockLevel: item.UnlockLevel, + Status: strings.TrimSpace(item.Status), + TrialEnabled: item.TrialEnabled, + ResourceId: item.ResourceID, + ResourceType: strings.TrimSpace(item.ResourceType), + ExecutionScope: strings.TrimSpace(item.ExecutionScope), + AutoEquip: item.AutoEquip, + SortOrder: item.SortOrder, + MetadataJson: strings.TrimSpace(item.MetadataJSON), + } +} + func grantVipFromProto(resp *walletv1.GrantVipResponse) grantVipDTO { if resp == nil { return grantVipDTO{} @@ -207,13 +487,65 @@ func userVipFromProto(item *walletv1.UserVip) userVipDTO { return userVipDTO{} } return userVipDTO{ - UserID: strconv.FormatInt(item.GetUserId(), 10), - Level: item.GetLevel(), - Name: item.GetName(), - Active: item.GetActive(), - StartedAtMS: item.GetStartedAtMs(), - ExpiresAtMS: item.GetExpiresAtMs(), - UpdatedAtMS: item.GetUpdatedAtMs(), + UserID: strconv.FormatInt(item.GetUserId(), 10), + Level: item.GetLevel(), + Name: item.GetName(), + Active: item.GetActive(), + StartedAtMS: item.GetStartedAtMs(), + ExpiresAtMS: item.GetExpiresAtMs(), + UpdatedAtMS: item.GetUpdatedAtMs(), + ProgramType: item.GetProgramType(), + ConfigVersion: item.GetConfigVersion(), + } +} + +func grantVipTrialCardFromProto(resp *walletv1.GrantVipTrialCardResponse) grantVipTrialCardDTO { + if resp == nil { + return grantVipTrialCardDTO{} + } + return grantVipTrialCardDTO{ + TrialCard: vipTrialCardFromProto(resp.GetTrialCard()), + State: vipStateFromProto(resp.GetState()), + ServerTimeMS: resp.GetServerTimeMs(), + } +} + +func vipTrialCardFromProto(item *walletv1.VipTrialCard) vipTrialCardDTO { + if item == nil { + return vipTrialCardDTO{} + } + return vipTrialCardDTO{ + TrialCardID: item.GetTrialCardId(), + EntitlementID: item.GetEntitlementId(), + ResourceID: item.GetResourceId(), + UserID: strconv.FormatInt(item.GetUserId(), 10), + Level: item.GetLevel(), + Name: item.GetName(), + Status: item.GetStatus(), + Equipped: item.GetEquipped(), + DurationMS: item.GetDurationMs(), + EffectiveAtMS: item.GetEffectiveAtMs(), + ExpiresAtMS: item.GetExpiresAtMs(), + RemainingDurationMS: item.GetRemainingDurationMs(), + GrantSource: item.GetGrantSource(), + SourceGrantID: item.GetSourceGrantId(), + CreatedAtMS: item.GetCreatedAtMs(), + UpdatedAtMS: item.GetUpdatedAtMs(), + } +} + +func vipStateFromProto(item *walletv1.VipState) vipStateDTO { + if item == nil { + return vipStateDTO{EffectiveBenefits: []vipBenefitDTO{}} + } + return vipStateDTO{ + PaidVIP: userVipFromProto(item.GetPaidVip()), + EquippedTrialCard: vipTrialCardFromProto(item.GetEquippedTrialCard()), + EffectiveVIP: userVipFromProto(item.GetEffectiveVip()), + EffectiveSource: item.GetEffectiveSource(), + EffectiveBenefits: vipBenefitsFromProto(item.GetEffectiveBenefits()), + EvaluatedAtMS: item.GetEvaluatedAtMs(), + ProgramConfig: vipProgramConfigFromProto(item.GetProgramConfig()), } } diff --git a/server/admin/internal/modules/vipconfig/handler_test.go b/server/admin/internal/modules/vipconfig/handler_test.go new file mode 100644 index 00000000..514c2746 --- /dev/null +++ b/server/admin/internal/modules/vipconfig/handler_test.go @@ -0,0 +1,201 @@ +package vipconfig + +import ( + "context" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "hyapp-admin-server/internal/appctx" + "hyapp-admin-server/internal/integration/walletclient" + "hyapp-admin-server/internal/middleware" + walletv1 "hyapp.local/api/proto/wallet/v1" + + "github.com/gin-gonic/gin" +) + +func TestGetProgramReturnsCamelCaseCompleteConfigAndBenefits(t *testing.T) { + wallet := &fakeVIPConfigWallet{ + programResponse: &walletv1.GetVipProgramConfigResponse{ + Config: &walletv1.VipProgramConfig{ + AppCode: "fami", + ProgramType: "tiered_privilege_v1", + LevelCount: 9, + SameLevelExpiryPolicy: "extend_remaining", + UpgradeExpiryPolicy: "replace_from_now", + DowngradePurchasePolicy: "reject", + BenefitInheritancePolicy: "target_only", + GrantMode: "trial_card", + TrialCardEnabled: true, + Status: "active", + ConfigVersion: 3, + UpdatedByAdminId: 77, + CreatedAtMs: 100, + UpdatedAtMs: 200, + }, + Benefits: []*walletv1.VipBenefit{{ + BenefitCode: "anti_kick", + Name: "防踢", + BenefitType: "function", + UnlockLevel: 9, + Status: "active", + TrialEnabled: true, + ExecutionScope: "room", + MetadataJson: "{}", + CreatedAtMs: 101, + UpdatedAtMs: 201, + }}, + ServerTimeMs: 300, + }, + } + recorder := serveVIPConfigRequest(t, wallet, http.MethodGet, "/admin/activity/vip-program", "") + if recorder.Code != http.StatusOK { + t.Fatalf("get program status = %d, body=%s", recorder.Code, recorder.Body.String()) + } + body := recorder.Body.String() + for _, fragment := range []string{ + `"programType":"tiered_privilege_v1"`, + `"upgradeExpiryPolicy":"replace_from_now"`, + `"updatedByAdminId":77`, + `"benefitCode":"anti_kick"`, + `"executionScope":"room"`, + `"serverTimeMs":300`, + } { + if !strings.Contains(body, fragment) { + t.Fatalf("get program response missing %s: %s", fragment, body) + } + } + if strings.Contains(body, "program_type") || strings.Contains(body, "benefit_code") { + t.Fatalf("admin contract must stay camelCase: %s", body) + } + if wallet.getProgramRequest.GetAppCode() != "fami" || wallet.getProgramRequest.GetRequestId() != "vip-config-test" { + t.Fatalf("get program request mismatch: %+v", wallet.getProgramRequest) + } +} + +func TestUpdateProgramUsesContextAppAndAuthenticatedOperator(t *testing.T) { + wallet := &fakeVIPConfigWallet{updateProgramResponse: &walletv1.UpdateAdminVipProgramConfigResponse{ + Config: &walletv1.VipProgramConfig{AppCode: "fami", ProgramType: "tiered_privilege_v1", LevelCount: 9, Status: "active", ConfigVersion: 4}, + ServerTimeMs: 400, + }} + body := `{"config":{"appCode":"lalu","programType":"tiered_privilege_v1","levelCount":9,"sameLevelExpiryPolicy":"extend_remaining","upgradeExpiryPolicy":"replace_from_now","downgradePurchasePolicy":"reject","benefitInheritancePolicy":"target_only","grantMode":"trial_card","trialCardEnabled":true,"status":"active","configVersion":999,"updatedByAdminId":999}}` + recorder := serveVIPConfigRequest(t, wallet, http.MethodPut, "/admin/activity/vip-program", body) + if recorder.Code != http.StatusOK { + t.Fatalf("update program status = %d, body=%s", recorder.Code, recorder.Body.String()) + } + req := wallet.updateProgramRequest + if req.GetAppCode() != "fami" || req.GetOperatorUserId() != 77 { + t.Fatalf("program scope/operator mismatch: %+v", req) + } + if req.GetConfig().GetAppCode() != "fami" || req.GetConfig().GetConfigVersion() != 0 || req.GetConfig().GetUpdatedByAdminId() != 0 { + t.Fatalf("client-controlled program audit fields leaked through: %+v", req.GetConfig()) + } + if !strings.Contains(recorder.Body.String(), `"configVersion":4`) || !strings.Contains(recorder.Body.String(), `"benefits":[]`) { + t.Fatalf("update program response mismatch: %s", recorder.Body.String()) + } +} + +func TestUpdateLevelsForwardsExplicitBenefitsAndReturnsProgram(t *testing.T) { + wallet := &fakeVIPConfigWallet{updateLevelsResponse: &walletv1.UpdateAdminVipLevelsResponse{ + Levels: []*walletv1.VipLevel{{ + Level: 2, Name: "VIP2", Status: "active", DurationMs: 2_592_000_000, + Benefits: []*walletv1.VipBenefit{{BenefitCode: "room_entry_notice", Name: "进房通知", Status: "active", ExecutionScope: "room", MetadataJson: "{}"}}, + }}, + 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":"{}"}]}]}` + 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()) + } + req := wallet.updateLevelsRequest + if req.GetAppCode() != "fami" || req.GetOperatorUserId() != 77 || len(req.GetLevels()) != 1 { + t.Fatalf("update levels request mismatch: %+v", req) + } + level := req.GetLevels()[0] + if level.GetRequiredRechargeCoinAmount() != 0 || len(level.GetBenefits()) != 1 || level.GetBenefits()[0].GetBenefitCode() != "room_entry_notice" { + t.Fatalf("explicit level benefits mismatch: %+v", level) + } + 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()) + } +} + +func TestGrantTrialCardLeavesOptionalResourceUnsetAndUsesAuthenticatedOperator(t *testing.T) { + wallet := &fakeVIPConfigWallet{grantTrialResponse: &walletv1.GrantVipTrialCardResponse{ + TrialCard: &walletv1.VipTrialCard{TrialCardId: "trial-1", EntitlementId: "ent-1", UserId: 318705991371722752, Level: 5, DurationMs: 1_728_000_000, ExpiresAtMs: 2_000}, + State: &walletv1.VipState{EffectiveSource: "none", EffectiveBenefits: []*walletv1.VipBenefit{}}, + ServerTimeMs: 1_000, + }} + body := `{"targetUserId":"318705991371722752","level":5,"durationMs":1728000000,"reason":"manual"}` + recorder := serveVIPConfigRequest(t, wallet, http.MethodPost, "/admin/activity/vip-trial-card-grants", body) + if recorder.Code != http.StatusCreated { + 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 { + t.Fatalf("trial grant command context mismatch: %+v", req) + } + if req.ResourceId != nil || req.GetTargetUserId() != 318705991371722752 || req.GetDurationMs() != 1_728_000_000 { + t.Fatalf("trial grant payload mismatch: %+v", req) + } + if !strings.Contains(recorder.Body.String(), `"trialCardId":"trial-1"`) || !strings.Contains(recorder.Body.String(), `"userId":"318705991371722752"`) { + t.Fatalf("trial grant response mismatch: %s", 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) + router := gin.New() + router.Use(func(c *gin.Context) { + c.Request = c.Request.WithContext(appctx.WithContext(c.Request.Context(), "fami")) + c.Set(middleware.ContextRequestID, "vip-config-test") + c.Set(middleware.ContextUserID, uint(77)) + c.Set(middleware.ContextUsername, "vip-operator") + c.Set(middleware.ContextPermissions, []string{"vip-config:view", "vip-config:update", "vip-config:grant"}) + c.Next() + }) + RegisterRoutes(router.Group(""), New(wallet, nil)) + recorder := httptest.NewRecorder() + request := httptest.NewRequest(method, path, strings.NewReader(body)) + if body != "" { + request.Header.Set("Content-Type", "application/json") + } + router.ServeHTTP(recorder, request) + return recorder +} + +type fakeVIPConfigWallet struct { + walletclient.Client + programResponse *walletv1.GetVipProgramConfigResponse + updateProgramResponse *walletv1.UpdateAdminVipProgramConfigResponse + updateLevelsResponse *walletv1.UpdateAdminVipLevelsResponse + grantTrialResponse *walletv1.GrantVipTrialCardResponse + getProgramRequest *walletv1.GetVipProgramConfigRequest + updateProgramRequest *walletv1.UpdateAdminVipProgramConfigRequest + updateLevelsRequest *walletv1.UpdateAdminVipLevelsRequest + grantTrialRequest *walletv1.GrantVipTrialCardRequest +} + +func (f *fakeVIPConfigWallet) GetVipProgramConfig(_ context.Context, req *walletv1.GetVipProgramConfigRequest) (*walletv1.GetVipProgramConfigResponse, error) { + f.getProgramRequest = req + return f.programResponse, nil +} + +func (f *fakeVIPConfigWallet) UpdateAdminVipProgramConfig(_ context.Context, req *walletv1.UpdateAdminVipProgramConfigRequest) (*walletv1.UpdateAdminVipProgramConfigResponse, error) { + f.updateProgramRequest = req + return f.updateProgramResponse, nil +} + +func (f *fakeVIPConfigWallet) UpdateAdminVipLevels(_ context.Context, req *walletv1.UpdateAdminVipLevelsRequest) (*walletv1.UpdateAdminVipLevelsResponse, error) { + f.updateLevelsRequest = req + return f.updateLevelsResponse, nil +} + +func (f *fakeVIPConfigWallet) GrantVipTrialCard(_ context.Context, req *walletv1.GrantVipTrialCardRequest) (*walletv1.GrantVipTrialCardResponse, error) { + f.grantTrialRequest = req + return f.grantTrialResponse, nil +} diff --git a/server/admin/internal/modules/vipconfig/routes.go b/server/admin/internal/modules/vipconfig/routes.go index e9b331a0..3919557b 100644 --- a/server/admin/internal/modules/vipconfig/routes.go +++ b/server/admin/internal/modules/vipconfig/routes.go @@ -11,7 +11,11 @@ func RegisterRoutes(protected *gin.RouterGroup, h *Handler) { return } + protected.GET("/admin/activity/vip-program", middleware.RequirePermission("vip-config:view"), h.GetProgram) + protected.PUT("/admin/activity/vip-program", middleware.RequirePermission("vip-config:update"), h.UpdateProgram) protected.GET("/admin/activity/vip-levels", middleware.RequirePermission("vip-config:view"), h.ListLevels) protected.PUT("/admin/activity/vip-levels", middleware.RequirePermission("vip-config:update"), h.UpdateLevels) + protected.POST("/admin/activity/vip-trial-card-grants", middleware.RequirePermission("vip-config:grant"), h.GrantVIPTrialCard) + // 旧 App 仍使用直接会员赠送,保留原路由直到其 program.grant_mode 切换为 trial_card。 protected.POST("/admin/activity/vip-grants", middleware.RequirePermission("vip-config:grant"), h.GrantVIP) } diff --git a/server/admin/internal/repository/admin_ops.go b/server/admin/internal/repository/admin_ops.go index c8949ce9..9e66fbaa 100644 --- a/server/admin/internal/repository/admin_ops.go +++ b/server/admin/internal/repository/admin_ops.go @@ -191,16 +191,51 @@ func (s *Store) LeaseNextJob(workerID string, lease time.Duration, maxAttempts i return &leased, nil } -func (s *Store) CompleteJobWithArtifact(id uint, resultJSON string, artifactPath string) error { +func (s *Store) CompleteJobWithArtifact(id uint, workerID string, resultJSON string, artifactPath string) error { nowMS := time.Now().UTC().UnixMilli() - return s.db.Model(&model.AdminJob{}).Where("id = ?", id).Updates(map[string]any{ - "status": model.JobStatusSucceeded, - "result_json": resultJSON, - "artifact_path": artifactPath, - "locked_by": "", - "locked_until_ms": nil, - "finished_at_ms": &nowMS, - }).Error + result := s.db.Model(&model.AdminJob{}). + Where("id = ? AND status = ? AND locked_by = ?", id, model.JobStatusRunning, strings.TrimSpace(workerID)). + Updates(map[string]any{ + "status": model.JobStatusSucceeded, + "result_json": resultJSON, + "artifact_path": artifactPath, + "locked_by": "", + "locked_until_ms": nil, + "finished_at_ms": &nowMS, + }) + if result.Error != nil { + return result.Error + } + if result.RowsAffected == 0 { + return errors.New("job lease is no longer owned by worker") + } + return nil +} + +// RenewJobLease 延长仍属于 worker 的 running 任务;RowsAffected=0 说明任务已完成或租约已经被其他实例接管。 +func (s *Store) RenewJobLease(id uint, workerID string, lease time.Duration) error { + if strings.TrimSpace(workerID) == "" || lease <= 0 { + return errors.New("worker id and positive lease are required") + } + nowMS := time.Now().UTC().UnixMilli() + result := s.db.Model(&model.AdminJob{}). + Where("id = ? AND status = ? AND locked_by = ?", id, model.JobStatusRunning, strings.TrimSpace(workerID)). + Update("locked_until_ms", nowMS+lease.Milliseconds()) + if result.Error != nil { + return result.Error + } + if result.RowsAffected == 0 { + var job model.AdminJob + if err := s.db.Select("status", "locked_by").First(&job, id).Error; err != nil { + return err + } + // handler 完成提交与 heartbeat tick 可能恰好相邻;终态无需续租,不能把成功任务误报为失败。 + if job.Status != model.JobStatusRunning { + return nil + } + return errors.New("job lease is no longer owned by worker") + } + return nil } type CountryCodeAdminReferenceCounts struct { @@ -234,9 +269,9 @@ func (s *Store) RenameCountryCodeAdminReferences(appCode string, oldCountryCode return counts, nil } -func (s *Store) FailJobAttempt(id uint, message string) error { +func (s *Store) FailJobAttempt(id uint, workerID string, message string) error { var job model.AdminJob - if err := s.db.First(&job, id).Error; err != nil { + if err := s.db.Where("id = ? AND status = ? AND locked_by = ?", id, model.JobStatusRunning, strings.TrimSpace(workerID)).First(&job).Error; err != nil { return err } nowMS := time.Now().UTC().UnixMilli() @@ -246,23 +281,39 @@ func (s *Store) FailJobAttempt(id uint, message string) error { status = model.JobStatusFailed finishedAt = &nowMS } - return s.db.Model(&model.AdminJob{}).Where("id = ?", id).Updates(map[string]any{ - "status": status, - "error": message, - "locked_by": "", - "locked_until_ms": nil, - "finished_at_ms": finishedAt, - }).Error + result := s.db.Model(&model.AdminJob{}). + Where("id = ? AND status = ? AND locked_by = ?", id, model.JobStatusRunning, strings.TrimSpace(workerID)). + Updates(map[string]any{ + "status": status, + "error": message, + "locked_by": "", + "locked_until_ms": nil, + "finished_at_ms": finishedAt, + }) + if result.Error != nil { + return result.Error + } + if result.RowsAffected == 0 { + return errors.New("job lease is no longer owned by worker") + } + return nil } -func (s *Store) ReleaseJobLease(id uint) error { - return s.db.Model(&model.AdminJob{}). - Where("id = ? AND status = ?", id, model.JobStatusRunning). +func (s *Store) ReleaseJobLease(id uint, workerID string) error { + result := s.db.Model(&model.AdminJob{}). + Where("id = ? AND status = ? AND locked_by = ?", id, model.JobStatusRunning, strings.TrimSpace(workerID)). Updates(map[string]any{ "status": model.JobStatusPending, "locked_by": "", "locked_until_ms": nil, - }).Error + }) + if result.Error != nil { + return result.Error + } + if result.RowsAffected == 0 { + return errors.New("job lease is no longer owned by worker") + } + return nil } func (s *Store) CancelJob(id uint) error { diff --git a/server/admin/internal/repository/app_config_repository_test.go b/server/admin/internal/repository/app_config_repository_test.go new file mode 100644 index 00000000..ce63a2eb --- /dev/null +++ b/server/admin/internal/repository/app_config_repository_test.go @@ -0,0 +1,81 @@ +package repository + +import ( + "testing" + + "hyapp-admin-server/internal/model" + + "github.com/DATA-DOG/go-sqlmock" +) + +func TestMergeScopedAppConfigsDoesNotLeakOverridesOrTombstonesAcrossApps(t *testing.T) { + rows := []model.AppConfig{ + {AppCode: "", Group: "h5-links", Key: "admin", Description: "Legacy Admin", Value: "https://legacy.example.com/admin"}, + {AppCode: "", Group: "h5-links", Key: "host", Description: "Legacy Host", Value: "https://legacy.example.com/host"}, + {AppCode: "yumi", Group: "h5-links", Key: "admin", Description: "Yumi Admin", Value: "https://yumi.example.com/admin"}, + {AppCode: "yumi", Group: "h5-links", Key: "host", IsDeleted: true}, + {AppCode: "fami", Group: "h5-links", Key: "admin", Description: "Fami Admin", Value: "https://fami.example.com/admin"}, + } + + yumi := mergeScopedAppConfigs(rows, "yumi") + if len(yumi) != 1 || yumi[0].AppCode != "yumi" || yumi[0].Description != "Yumi Admin" { + t.Fatalf("yumi effective config mismatch: %+v", yumi) + } + fami := mergeScopedAppConfigs(rows, "fami") + if len(fami) != 2 || fami[0].AppCode != "fami" || fami[0].Description != "Fami Admin" || fami[1].Value != "https://legacy.example.com/host" { + t.Fatalf("fami must not inherit yumi override/tombstone: %+v", fami) + } + future := mergeScopedAppConfigs(rows, "future-app") + if len(future) != 2 || future[0].Description != "Legacy Admin" || future[1].Description != "Legacy Host" { + t.Fatalf("future app must inherit only legacy baseline: %+v", future) + } +} + +func TestTombstoneScopedAppConfigWritesOnlyCurrentApp(t *testing.T) { + store, mock, closeStore := newRepositorySQLMock(t) + defer closeStore() + + mock.ExpectBegin() + mock.ExpectExec("INSERT INTO `admin_app_configs`"). + WithArgs("yumi", "h5-links", "host", "", "", true, sqlmock.AnyArg(), sqlmock.AnyArg(), true, sqlmock.AnyArg()). + WillReturnResult(sqlmock.NewResult(9, 1)) + mock.ExpectCommit() + + if err := store.TombstoneScopedAppConfig(" YUMI ", "h5-links", "host"); err != nil { + t.Fatalf("write scoped tombstone failed: %v", err) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} + +func TestListScopedAppConfigsOverlaysBaselineAndHonorsTombstone(t *testing.T) { + store, mock, closeStore := newRepositorySQLMock(t) + defer closeStore() + + mock.ExpectQuery("SELECT \\* FROM `admin_app_configs` WHERE `group` = \\? AND app_code IN \\(\\?,\\?\\) ORDER BY `key` ASC, app_code ASC"). + WithArgs("h5-links", "", "yumi"). + WillReturnRows(sqlmock.NewRows([]string{"id", "app_code", "group", "key", "value", "description", "is_deleted", "created_at_ms", "updated_at_ms"}). + AddRow(1, "", "h5-links", "admin", "https://legacy.example.com/admin", "Admin", false, int64(100), int64(100)). + AddRow(2, "yumi", "h5-links", "admin", "https://yumi.example.com/admin", "Yumi Admin", false, int64(200), int64(200)). + AddRow(3, "", "h5-links", "host", "https://legacy.example.com/host", "Host", false, int64(100), int64(100)). + AddRow(4, "yumi", "h5-links", "host", "", "", true, int64(300), int64(300)). + AddRow(5, "", "h5-links", "public", "https://legacy.example.com/public", "Public", false, int64(100), int64(100))) + + items, err := store.ListScopedAppConfigs(" YUMI ", "h5-links") + if err != nil { + t.Fatalf("list scoped app configs failed: %v", err) + } + if len(items) != 2 { + t.Fatalf("unexpected effective configs: %+v", items) + } + if items[0].AppCode != "yumi" || items[0].Key != "admin" || items[0].Description != "Yumi Admin" { + t.Fatalf("override mismatch: %+v", items[0]) + } + if items[1].AppCode != "yumi" || items[1].Key != "public" || items[1].Value != "https://legacy.example.com/public" { + t.Fatalf("baseline projection mismatch: %+v", items[1]) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("sql expectations mismatch: %v", err) + } +} diff --git a/server/admin/internal/repository/seed.go b/server/admin/internal/repository/seed.go index 19cbaa61..a5bcd1f0 100644 --- a/server/admin/internal/repository/seed.go +++ b/server/admin/internal/repository/seed.go @@ -21,6 +21,8 @@ var defaultPermissions = []model.Permission{ {Name: "团队更新", Code: "team:update", Kind: "button"}, {Name: "App 用户查看", Code: "app-user:view", Kind: "menu"}, {Name: "App 用户更新", Code: "app-user:update", Kind: "button"}, + {Name: "App 用户等级调整", Code: "app-user:level", Kind: "button"}, + {Name: "App 用户导出", Code: "app-user:export", Kind: "button"}, {Name: "App 用户状态", Code: "app-user:status", Kind: "button"}, {Name: "App 用户设置密码", Code: "app-user:password", Kind: "button"}, {Name: "等级配置查看", Code: "level-config:view", Kind: "menu"}, @@ -639,7 +641,7 @@ func defaultRolePermissionCodes(code string) []string { "overview:view", "user:view", "user:status", "team:view", "team:create", "team:update", - "app-user:view", "app-user:update", "app-user:status", "app-user:password", + "app-user:view", "app-user:update", "app-user:level", "app-user:export", "app-user:status", "app-user:password", "level-config:view", "level-config:update", "pretty-id:view", "pretty-id:update", "pretty-id:generate", "pretty-id:grant", "risk-config:view", "risk-config:update", @@ -752,7 +754,7 @@ func defaultRolePermissionMigrationCodes(code string) []string { case "ops-admin": return []string{ "team:view", "team:create", "team:update", - "app-user:update", "app-user:status", "app-user:password", + "app-user:update", "app-user:level", "app-user:export", "app-user:status", "app-user:password", "room:view", "room:update", "room:delete", "room-pin:view", "room-pin:create", "room-pin:cancel", "room-config:view", "room-config:update", "room-whitelist:view", "room-whitelist:update", "room-robot:view", "room-robot:create", "room-robot:update", "app-config:view", "app-config:update", "app-version:view", "app-version:create", "app-version:update", "app-version:delete", diff --git a/server/admin/migrations/085_app_user_level_export_permissions.sql b/server/admin/migrations/085_app_user_level_export_permissions.sql new file mode 100644 index 00000000..ac5b6945 --- /dev/null +++ b/server/admin/migrations/085_app_user_level_export_permissions.sql @@ -0,0 +1,21 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- 等级调整会跨 activity/wallet 执行奖励副作用,用户导出会读取筛选快照和生成文件; +-- 两者都必须与普通资料更新解耦,便于运营角色按职责最小授权。 +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 + ('App 用户等级调整', 'app-user:level', 'button', '允许临时调整 App 用户富豪或魅力等级', @now_ms, @now_ms), + ('App 用户导出', 'app-user:export', 'button', '允许按当前筛选快照异步导出 App 用户 CSV', @now_ms, @now_ms) +ON DUPLICATE KEY UPDATE + name = VALUES(name), + kind = VALUES(kind), + description = VALUES(description), + updated_at_ms = @now_ms; + +INSERT IGNORE INTO admin_role_permissions (role_id, permission_id) +SELECT admin_role.id, admin_permission.id +FROM admin_roles admin_role +JOIN admin_permissions admin_permission +WHERE admin_role.code IN ('platform-admin', 'ops-admin') + AND admin_permission.code IN ('app-user:level', 'app-user:export'); diff --git a/services/activity-service/configs/config.docker.yaml b/services/activity-service/configs/config.docker.yaml index d7d648f9..a08f3a6c 100644 --- a/services/activity-service/configs/config.docker.yaml +++ b/services/activity-service/configs/config.docker.yaml @@ -78,6 +78,7 @@ rocketmq: cumulative_recharge_consumer_group: "hyapp-activity-cumulative-recharge-wallet-outbox" invite_activity_consumer_group: "hyapp-activity-invite-wallet-outbox" red_packet_broadcast_consumer_group: "hyapp-activity-red-packet-wallet-outbox" + vip_rebate_notice_consumer_group: "hyapp-activity-vip-rebate-notice-wallet-outbox" task_consumer_group: "hyapp-activity-task-wallet-outbox" user_leaderboard_consumer_group: "hyapp-activity-user-leaderboard-wallet-outbox" consumer_max_reconsume_times: 16 diff --git a/services/activity-service/configs/config.tencent.example.yaml b/services/activity-service/configs/config.tencent.example.yaml index f9a811ee..fd932d69 100644 --- a/services/activity-service/configs/config.tencent.example.yaml +++ b/services/activity-service/configs/config.tencent.example.yaml @@ -78,6 +78,7 @@ rocketmq: cumulative_recharge_consumer_group: "hyapp-activity-cumulative-recharge-wallet-outbox" invite_activity_consumer_group: "hyapp-activity-invite-wallet-outbox" red_packet_broadcast_consumer_group: "hyapp-activity-red-packet-wallet-outbox" + vip_rebate_notice_consumer_group: "hyapp-activity-vip-rebate-notice-wallet-outbox" task_consumer_group: "hyapp-activity-task-wallet-outbox" user_leaderboard_consumer_group: "hyapp-activity-user-leaderboard-wallet-outbox" consumer_max_reconsume_times: 16 diff --git a/services/activity-service/configs/config.yaml b/services/activity-service/configs/config.yaml index 908f1060..01c742ff 100644 --- a/services/activity-service/configs/config.yaml +++ b/services/activity-service/configs/config.yaml @@ -78,6 +78,7 @@ rocketmq: cumulative_recharge_consumer_group: "hyapp-activity-cumulative-recharge-wallet-outbox" invite_activity_consumer_group: "hyapp-activity-invite-wallet-outbox" red_packet_broadcast_consumer_group: "hyapp-activity-red-packet-wallet-outbox" + vip_rebate_notice_consumer_group: "hyapp-activity-vip-rebate-notice-wallet-outbox" task_consumer_group: "hyapp-activity-task-wallet-outbox" user_leaderboard_consumer_group: "hyapp-activity-user-leaderboard-wallet-outbox" consumer_max_reconsume_times: 16 diff --git a/services/activity-service/deploy/mysql/initdb/001_activity_service.sql b/services/activity-service/deploy/mysql/initdb/001_activity_service.sql index 1a046bd5..6ef1df87 100644 --- a/services/activity-service/deploy/mysql/initdb/001_activity_service.sql +++ b/services/activity-service/deploy/mysql/initdb/001_activity_service.sql @@ -695,6 +695,13 @@ CREATE TABLE IF NOT EXISTS growth_level_reward_jobs ( resource_group_id BIGINT NOT NULL COMMENT '资源分组 ID', wallet_command_id VARCHAR(128) NOT NULL COMMENT '钱包命令 ID', wallet_grant_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包资源发放 ID', + reward_origin VARCHAR(32) NOT NULL DEFAULT 'organic' COMMENT '奖励来源:organic/temporary', + temporary_level_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '临时等级记录 ID', + grant_generation INT NOT NULL DEFAULT 0 COMMENT '同一奖励来源的发放代次', + reward_level INT NOT NULL DEFAULT 0 COMMENT '取得该奖励所需等级', + is_permanent TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否已提升为永久奖励', + temporary_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '临时奖励到期时间,UTC epoch ms', + revoke_status VARCHAR(32) NOT NULL DEFAULT 'none' COMMENT 'none/pending/running/revoked/failed/skipped', status VARCHAR(32) NOT NULL COMMENT '业务状态', attempt_count INT NOT NULL DEFAULT 0 COMMENT '尝试次数', next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '下一次重试时间,UTC epoch ms', @@ -704,11 +711,70 @@ CREATE TABLE IF NOT EXISTS growth_level_reward_jobs ( created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', PRIMARY KEY (app_code, reward_job_id), - UNIQUE KEY uk_growth_level_reward_once (app_code, user_id, track, reward_source_type, reward_source_id), + UNIQUE KEY uk_growth_level_reward_generation (app_code, user_id, track, reward_source_type, reward_source_id, reward_origin, grant_generation), KEY idx_growth_level_reward_pending (app_code, status, next_retry_at_ms, created_at_ms), KEY idx_growth_level_reward_user (app_code, user_id, track, created_at_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='成长等级奖励任务表'; +CREATE TABLE IF NOT EXISTS growth_level_reward_wallet_grants ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + reward_job_id VARCHAR(96) NOT NULL COMMENT '奖励任务 ID', + grant_kind VARCHAR(32) NOT NULL COMMENT 'resource_group/avatar_frame/short_badge', + wallet_grant_id VARCHAR(96) NOT NULL COMMENT '钱包发放 ID', + revoke_status VARCHAR(32) NOT NULL DEFAULT 'none' COMMENT 'none/pending/running/revoked/failed/skipped', + revoke_attempt_count INT NOT NULL DEFAULT 0 COMMENT '撤回尝试次数', + revoke_next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '撤回重试时间', + revoke_locked_by VARCHAR(128) NOT NULL DEFAULT '' COMMENT '撤回 worker', + revoke_locked_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT '撤回锁截止', + revoke_failure_reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '撤回失败原因', + revoked_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '撤回完成时间', + created_at_ms BIGINT NOT NULL COMMENT '创建时间', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间', + PRIMARY KEY (app_code, reward_job_id, wallet_grant_id), + KEY idx_growth_reward_grant_revoke (app_code, revoke_status, revoke_next_retry_at_ms, created_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='等级奖励钱包发放明细'; + +CREATE TABLE IF NOT EXISTS growth_temporary_level_commands ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + command_id VARCHAR(128) NOT NULL COMMENT '整批调整幂等键', + request_hash VARCHAR(64) NOT NULL COMMENT '规范化请求 SHA256', + user_id BIGINT NOT NULL COMMENT '目标用户', + operator_admin_id BIGINT NOT NULL COMMENT '操作管理员', + created_at_ms BIGINT NOT NULL COMMENT '创建时间', + PRIMARY KEY (app_code, command_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='临时等级批量命令幂等表'; + +CREATE TABLE IF NOT EXISTS growth_temporary_levels ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + temporary_level_id VARCHAR(96) NOT NULL COMMENT '临时等级 ID', + command_id VARCHAR(128) NOT NULL COMMENT '批量命令 ID', + user_id BIGINT NOT NULL COMMENT '用户 ID', + track VARCHAR(32) NOT NULL COMMENT 'wealth/charm', + target_level INT NOT NULL COMMENT '临时目标等级', + target_required_value BIGINT NOT NULL COMMENT '目标等级起始阈值快照', + baseline_total_value BIGINT NOT NULL COMMENT '调整时真实累计值快照', + started_at_ms BIGINT NOT NULL COMMENT '有效期开始,包含', + expires_at_ms BIGINT NOT NULL COMMENT '有效期结束,不包含', + status VARCHAR(32) NOT NULL COMMENT 'active/superseded/expired', + generation INT NOT NULL COMMENT '用户轨道临时发放代次', + operator_admin_id BIGINT NOT NULL COMMENT '操作管理员', + reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '操作原因', + final_level INT NOT NULL DEFAULT 0 COMMENT '按基线和有效期经验计算的恢复等级', + activation_notice_status VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT '下发通知状态', + expiry_notice_status VARCHAR(32) NOT NULL DEFAULT 'skipped' COMMENT '到期通知状态', + attempt_count INT NOT NULL DEFAULT 0 COMMENT '副作用尝试次数', + next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '副作用重试时间', + locked_by VARCHAR(128) NOT NULL DEFAULT '' COMMENT '当前 worker', + locked_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT '锁截止时间', + failure_reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '副作用失败原因', + created_at_ms BIGINT NOT NULL COMMENT '创建时间', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间', + PRIMARY KEY (app_code, temporary_level_id), + UNIQUE KEY uk_growth_temp_command_track (app_code, command_id, track), + KEY idx_growth_temp_user_track (app_code, user_id, track, status, expires_at_ms), + KEY idx_growth_temp_work (app_code, status, next_retry_at_ms, expires_at_ms, created_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户临时成长等级 overlay'; + CREATE TABLE IF NOT EXISTS user_level_display_profiles ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', user_id BIGINT NOT NULL COMMENT '用户 ID', diff --git a/services/activity-service/deploy/mysql/migrations/009_temporary_growth_levels.sql b/services/activity-service/deploy/mysql/migrations/009_temporary_growth_levels.sql new file mode 100644 index 00000000..befb7ed8 --- /dev/null +++ b/services/activity-service/deploy/mysql/migrations/009_temporary_growth_levels.sql @@ -0,0 +1,46 @@ +-- 临时财富/魅力等级只建立 overlay 和副作用事实,不修改 user_growth_level_accounts 的真实经验。 +ALTER TABLE growth_level_reward_jobs + DROP INDEX uk_growth_level_reward_once, + ADD COLUMN reward_origin VARCHAR(32) NOT NULL DEFAULT 'organic' COMMENT 'organic/temporary' AFTER wallet_grant_id, + ADD COLUMN temporary_level_id VARCHAR(96) NOT NULL DEFAULT '' AFTER reward_origin, + ADD COLUMN grant_generation INT NOT NULL DEFAULT 0 AFTER temporary_level_id, + ADD COLUMN reward_level INT NOT NULL DEFAULT 0 AFTER grant_generation, + ADD COLUMN is_permanent TINYINT(1) NOT NULL DEFAULT 1 AFTER reward_level, + ADD COLUMN temporary_expires_at_ms BIGINT NOT NULL DEFAULT 0 AFTER is_permanent, + ADD COLUMN revoke_status VARCHAR(32) NOT NULL DEFAULT 'none' AFTER temporary_expires_at_ms, + ADD UNIQUE KEY uk_growth_level_reward_generation + (app_code, user_id, track, reward_source_type, reward_source_id, reward_origin, grant_generation); + +CREATE TABLE IF NOT EXISTS growth_level_reward_wallet_grants ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu', reward_job_id VARCHAR(96) NOT NULL, + grant_kind VARCHAR(32) NOT NULL, wallet_grant_id VARCHAR(96) NOT NULL, + revoke_status VARCHAR(32) NOT NULL DEFAULT 'none', revoke_attempt_count INT NOT NULL DEFAULT 0, + revoke_next_retry_at_ms BIGINT NOT NULL DEFAULT 0, revoke_locked_by VARCHAR(128) NOT NULL DEFAULT '', + revoke_locked_until_ms BIGINT NOT NULL DEFAULT 0, revoke_failure_reason VARCHAR(255) NOT NULL DEFAULT '', + revoked_at_ms BIGINT NOT NULL DEFAULT 0, created_at_ms BIGINT NOT NULL, updated_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, reward_job_id, wallet_grant_id), + KEY idx_growth_reward_grant_revoke (app_code, revoke_status, revoke_next_retry_at_ms, created_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS growth_temporary_level_commands ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu', command_id VARCHAR(128) NOT NULL, + request_hash VARCHAR(64) NOT NULL, user_id BIGINT NOT NULL, operator_admin_id BIGINT NOT NULL, + created_at_ms BIGINT NOT NULL, PRIMARY KEY (app_code, command_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS growth_temporary_levels ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu', temporary_level_id VARCHAR(96) NOT NULL, + command_id VARCHAR(128) NOT NULL, user_id BIGINT NOT NULL, track VARCHAR(32) NOT NULL, + target_level INT NOT NULL, target_required_value BIGINT NOT NULL, baseline_total_value BIGINT NOT NULL, + started_at_ms BIGINT NOT NULL, expires_at_ms BIGINT NOT NULL, status VARCHAR(32) NOT NULL, + generation INT NOT NULL, operator_admin_id BIGINT NOT NULL, reason VARCHAR(255) NOT NULL DEFAULT '', + final_level INT NOT NULL DEFAULT 0, activation_notice_status VARCHAR(32) NOT NULL DEFAULT 'pending', + expiry_notice_status VARCHAR(32) NOT NULL DEFAULT 'skipped', attempt_count INT NOT NULL DEFAULT 0, + next_retry_at_ms BIGINT NOT NULL DEFAULT 0, locked_by VARCHAR(128) NOT NULL DEFAULT '', + locked_until_ms BIGINT NOT NULL DEFAULT 0, failure_reason VARCHAR(255) NOT NULL DEFAULT '', + created_at_ms BIGINT NOT NULL, updated_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, temporary_level_id), + UNIQUE KEY uk_growth_temp_command_track (app_code, command_id, track), + KEY idx_growth_temp_user_track (app_code, user_id, track, status, expires_at_ms), + KEY idx_growth_temp_work (app_code, status, next_retry_at_ms, expires_at_ms, created_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/services/activity-service/internal/app/mq.go b/services/activity-service/internal/app/mq.go index 818f2c54..f5ac8e09 100644 --- a/services/activity-service/internal/app/mq.go +++ b/services/activity-service/internal/app/mq.go @@ -97,6 +97,14 @@ func buildMQConsumers(cfg config.Config, services *serviceBundle) ([]*rocketmqx. } mqConsumers = append(mqConsumers, consumer) } + if cfg.RocketMQ.WalletOutbox.Enabled { + consumer, err := newVIPRebateNoticeWalletConsumer(cfg, services) + if err != nil { + shutdownConsumers(mqConsumers) + return nil, err + } + mqConsumers = append(mqConsumers, consumer) + } if cfg.UserLeaderboardWorker.Enabled && cfg.RocketMQ.WalletOutbox.Enabled { consumer, err := newUserLeaderboardWalletConsumer(cfg, services) if err != nil { @@ -273,6 +281,26 @@ func newRedPacketWalletConsumer(cfg config.Config, services *serviceBundle) (*ro return consumer, nil } +func newVIPRebateNoticeWalletConsumer(cfg config.Config, services *serviceBundle) (*rocketmqx.Consumer, error) { + // VIP 返现资格是 wallet 的逐用户事实,必须使用独立 consumer group 投影为系统通知; + // 不能复用首充/红包位点,也不能用全服 fanout,因为每个用户的 rebate_id、金额和到期时间都不同。 + consumer, err := rocketmqx.NewConsumer(walletOutboxVIPRebateNoticeConsumerConfig(cfg.RocketMQ)) + if err != nil { + return nil, err + } + if err := consumer.Subscribe(cfg.RocketMQ.WalletOutbox.Topic, walletmq.TagWalletOutboxEvent, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { + event, ok, err := vipRebateAvailableEventFromWalletMessage(message.Body) + if err != nil || !ok { + return err + } + return createVIPRebateSystemNotice(appcode.WithContext(ctx, event.AppCode), services.message, event) + }); err != nil { + _ = consumer.Shutdown() + return nil, err + } + return consumer, nil +} + func newUserLeaderboardWalletConsumer(cfg config.Config, services *serviceBundle) (*rocketmqx.Consumer, error) { if services == nil || services.userLeaderboard == nil { return nil, errors.New("user leaderboard worker requires redis store") @@ -380,6 +408,14 @@ func walletOutboxUserLeaderboardConsumerConfig(cfg config.RocketMQConfig) rocket return consumerConfig } +func walletOutboxVIPRebateNoticeConsumerConfig(cfg config.RocketMQConfig) rocketmqx.ConsumerConfig { + consumerConfig := walletOutboxConsumerConfig(cfg, cfg.WalletOutbox.VIPRebateNoticeConsumerGroup) + // 新 consumer group 上线时必须从 broker 仍保留的最早事实恢复;否则 wallet/cron 先发布的 + // 当日资格会永久没有系统通知。非目标钱包事实会被解析器安全跳过,不会写 inbox。 + consumerConfig.ConsumeFromFirst = true + return consumerConfig +} + func messageActionProducerConfig(cfg config.RocketMQConfig) rocketmqx.ProducerConfig { return rocketmqx.ProducerConfig{ EndpointConfig: rocketmqx.EndpointConfig{ diff --git a/services/activity-service/internal/app/services.go b/services/activity-service/internal/app/services.go index 61513ba7..070cdcb6 100644 --- a/services/activity-service/internal/app/services.go +++ b/services/activity-service/internal/app/services.go @@ -60,7 +60,7 @@ 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) + growthSvc := growthservice.New(repository, walletClient, growthservice.WithNoticeService(messageSvc)) 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/app/vip_rebate_notice.go b/services/activity-service/internal/app/vip_rebate_notice.go new file mode 100644 index 00000000..167f2d70 --- /dev/null +++ b/services/activity-service/internal/app/vip_rebate_notice.go @@ -0,0 +1,133 @@ +package app + +import ( + "context" + "encoding/json" + "fmt" + "strings" + "time" + + "hyapp/pkg/appcode" + "hyapp/pkg/walletmq" + "hyapp/pkg/xerr" + messageservice "hyapp/services/activity-service/internal/service/message" +) + +const vipDailyCoinRebateAvailableEventType = "VipDailyCoinRebateAvailable" + +// vipRebateAvailableEvent 是 wallet outbox 的逐用户返现资格快照。 +// activity-service 只把这个已提交事实投影为 inbox;资格、金额、过期和最终入账仍由 wallet owner 判定。 +type vipRebateAvailableEvent struct { + AppCode string + EventID string + RebateID string + UserID int64 + TaskDay string + VIPLevel int32 + VIPName string + CoinAmount int64 + AvailableAtMS int64 + ExpiresAtMS int64 + ConfigVersion int64 + CreatedAtMS int64 +} + +func vipRebateAvailableEventFromWalletMessage(body []byte) (vipRebateAvailableEvent, bool, error) { + message, err := walletmq.DecodeWalletOutboxMessage(body) + if err != nil { + return vipRebateAvailableEvent{}, false, err + } + if message.EventType != vipDailyCoinRebateAvailableEventType { + return vipRebateAvailableEvent{}, false, nil + } + var payload struct { + RebateID string `json:"rebate_id"` + UserID int64 `json:"user_id"` + TaskDay string `json:"task_day"` + VIPLevel int32 `json:"vip_level"` + VIPName string `json:"vip_name"` + CoinAmount int64 `json:"coin_amount"` + AvailableAtMS int64 `json:"available_at_ms"` + ExpiresAtMS int64 `json:"expires_at_ms"` + ConfigVersion int64 `json:"config_version"` + CreatedAtMS int64 `json:"created_at_ms"` + } + if err := json.Unmarshal([]byte(message.PayloadJSON), &payload); err != nil { + // 目标事件 payload 损坏必须让 MQ 重投并进入告警,不能确认后永久丢失用户领取入口。 + return vipRebateAvailableEvent{}, false, err + } + payload.RebateID = strings.TrimSpace(payload.RebateID) + payload.TaskDay = strings.TrimSpace(payload.TaskDay) + payload.VIPName = strings.TrimSpace(payload.VIPName) + if payload.CreatedAtMS <= 0 { + payload.CreatedAtMS = message.OccurredAtMS + } + if payload.RebateID == "" || payload.UserID <= 0 || payload.UserID != message.UserID || !validUTCTaskDay(payload.TaskDay) || payload.VIPLevel <= 0 || payload.CoinAmount <= 0 || payload.AvailableAtMS <= 0 || payload.ExpiresAtMS <= payload.AvailableAtMS || payload.ConfigVersion <= 0 { + return vipRebateAvailableEvent{}, false, xerr.New(xerr.InvalidArgument, "VIP rebate wallet event is invalid") + } + return vipRebateAvailableEvent{ + AppCode: appcode.Normalize(message.AppCode), + EventID: message.EventID, + RebateID: payload.RebateID, + UserID: payload.UserID, + TaskDay: payload.TaskDay, + VIPLevel: payload.VIPLevel, + VIPName: payload.VIPName, + CoinAmount: payload.CoinAmount, + AvailableAtMS: payload.AvailableAtMS, + ExpiresAtMS: payload.ExpiresAtMS, + ConfigVersion: payload.ConfigVersion, + CreatedAtMS: payload.CreatedAtMS, + }, true, nil +} + +func createVIPRebateSystemNotice(ctx context.Context, service *messageservice.Service, event vipRebateAvailableEvent) error { + if service == nil { + return xerr.New(xerr.Unavailable, "message service is not configured") + } + actionParam, err := json.Marshal(map[string]any{ + "rebate_id": event.RebateID, + "task_day": event.TaskDay, + "coin_amount": event.CoinAmount, + "expires_at_ms": event.ExpiresAtMS, + }) + if err != nil { + return err + } + summary := fmt.Sprintf("尊敬的VIP用户,平台今日返现%d金币,请及时领取。", event.CoinAmount) + _, err = service.CreateSystemNotice(ctx, messageservice.NoticeCommand{ + TargetUserID: event.UserID, + Producer: "wallet-service", + ProducerEventID: event.EventID, + ProducerEventType: vipDailyCoinRebateAvailableEventType, + AggregateType: "vip_daily_coin_rebate", + AggregateID: event.RebateID, + TemplateID: "vip_daily_coin_rebate_available", + TemplateVersion: "v1", + Title: "VIP金币返现", + Summary: summary, + Body: summary, + ActionType: "vip_coin_rebate_claim", + ActionParam: string(actionParam), + Priority: 50, + SentAtMS: event.AvailableAtMS, + ExpireAtMS: event.ExpiresAtMS, + Metadata: map[string]any{ + "rebate_id": event.RebateID, + "task_day": event.TaskDay, + "vip_level": event.VIPLevel, + "vip_name": event.VIPName, + "coin_amount": event.CoinAmount, + "available_at_ms": event.AvailableAtMS, + "expires_at_ms": event.ExpiresAtMS, + "config_version": event.ConfigVersion, + "claim_status": "claimable", + }, + }) + return err +} + +func validUTCTaskDay(value string) bool { + parsed, err := time.Parse("2006-01-02", value) + return err == nil && parsed.Location() == time.UTC && parsed.Format("2006-01-02") == value +} diff --git a/services/activity-service/internal/app/vip_rebate_notice_test.go b/services/activity-service/internal/app/vip_rebate_notice_test.go new file mode 100644 index 00000000..d2f2fad9 --- /dev/null +++ b/services/activity-service/internal/app/vip_rebate_notice_test.go @@ -0,0 +1,90 @@ +package app + +import ( + "context" + "testing" + "time" + + "hyapp/pkg/appcode" + "hyapp/pkg/walletmq" + messageservice "hyapp/services/activity-service/internal/service/message" + "hyapp/services/activity-service/internal/testutil/mysqltest" +) + +func TestVIPRebateAvailableEventFromWalletMessage(t *testing.T) { + body := vipRebateWalletMessage(t, "VipDailyCoinRebateAvailable", 42, `{ + "rebate_id":"viprebate_fami_2027-01-15_42", + "user_id":42, + "task_day":"2027-01-15", + "vip_level":9, + "vip_name":"VIP9", + "coin_amount":100000, + "available_at_ms":1800000000000, + "expires_at_ms":1800086400000, + "config_version":7, + "created_at_ms":1800000000100 + }`) + event, ok, err := vipRebateAvailableEventFromWalletMessage(body) + if err != nil || !ok { + t.Fatalf("parse VIP rebate event failed: ok=%v event=%+v err=%v", ok, event, err) + } + if event.AppCode != "fami" || event.EventID != "wev-vip-rebate" || event.RebateID != "viprebate_fami_2027-01-15_42" || event.UserID != 42 || event.TaskDay != "2027-01-15" || event.VIPLevel != 9 || event.CoinAmount != 100000 || event.ExpiresAtMS != 1800086400000 || event.ConfigVersion != 7 { + t.Fatalf("VIP rebate event mismatch: %+v", event) + } +} + +func TestVIPRebateWalletEventSkipsOtherFactsAndRejectsCorruptTarget(t *testing.T) { + other := vipRebateWalletMessage(t, "WalletRechargeRecorded", 42, `{}`) + if event, ok, err := vipRebateAvailableEventFromWalletMessage(other); err != nil || ok || event.EventID != "" { + t.Fatalf("non-target event should be acknowledged: ok=%v event=%+v err=%v", ok, event, err) + } + corrupt := vipRebateWalletMessage(t, "VipDailyCoinRebateAvailable", 42, `{"rebate_id":"r1","user_id":99}`) + if _, ok, err := vipRebateAvailableEventFromWalletMessage(corrupt); err == nil || ok { + t.Fatalf("corrupt target event must fail for MQ retry: ok=%v err=%v", ok, err) + } +} + +func TestVIPRebateWalletEventCreatesOneIdempotentSystemNotice(t *testing.T) { + ctx := appcode.WithContext(context.Background(), "fami") + repository := mysqltest.NewRepository(t) + service := messageservice.New(messageservice.Config{NodeID: "activity-test"}, repository) + service.SetClock(func() time.Time { return time.UnixMilli(1800000000200) }) + event := vipRebateAvailableEvent{ + AppCode: "fami", EventID: "wev-vip-rebate", RebateID: "viprebate_fami_2027-01-15_42", + UserID: 42, TaskDay: "2027-01-15", VIPLevel: 9, VIPName: "VIP9", CoinAmount: 100000, + AvailableAtMS: 1800000000000, ExpiresAtMS: 1800086400000, ConfigVersion: 7, CreatedAtMS: 1800000000100, + } + if err := createVIPRebateSystemNotice(ctx, service, event); err != nil { + t.Fatalf("create system notice failed: %v", err) + } + if err := createVIPRebateSystemNotice(ctx, service, event); err != nil { + t.Fatalf("duplicate system notice should be idempotent: %v", err) + } + items, _, err := service.ListInboxMessages(ctx, 42, "system", 20, "") + if err != nil || len(items) != 1 { + t.Fatalf("system inbox mismatch: items=%+v err=%v", items, err) + } + item := items[0] + if item.Title != "VIP金币返现" || item.ActionType != "vip_coin_rebate_claim" || item.AggregateID != event.RebateID || item.ExpireAtMS != event.ExpiresAtMS || item.ActionParam == "" { + t.Fatalf("VIP rebate notice mismatch: %+v", item) + } +} + +func vipRebateWalletMessage(t *testing.T, eventType string, userID int64, payload string) []byte { + t.Helper() + body, err := walletmq.EncodeWalletOutboxMessage(walletmq.WalletOutboxMessage{ + AppCode: "fami", + EventID: "wev-vip-rebate", + EventType: eventType, + TransactionID: "viprebate_fami_2027-01-15_42", + CommandID: "vip-rebate-generate:fami:2027-01-15:42", + UserID: userID, + AssetType: "COIN", + PayloadJSON: payload, + OccurredAtMS: 1800000000100, + }) + if err != nil { + t.Fatalf("encode wallet outbox message: %v", err) + } + return body +} diff --git a/services/activity-service/internal/config/config.go b/services/activity-service/internal/config/config.go index f2edd547..caccea3a 100644 --- a/services/activity-service/internal/config/config.go +++ b/services/activity-service/internal/config/config.go @@ -196,6 +196,7 @@ type WalletOutboxMQConfig struct { CumulativeRechargeConsumerGroup string `yaml:"cumulative_recharge_consumer_group"` InviteActivityConsumerGroup string `yaml:"invite_activity_consumer_group"` RedPacketBroadcastConsumerGroup string `yaml:"red_packet_broadcast_consumer_group"` + VIPRebateNoticeConsumerGroup string `yaml:"vip_rebate_notice_consumer_group"` TaskConsumerGroup string `yaml:"task_consumer_group"` UserLeaderboardConsumerGroup string `yaml:"user_leaderboard_consumer_group"` ConsumerMaxReconsumeTimes int32 `yaml:"consumer_max_reconsume_times"` @@ -311,6 +312,7 @@ func defaultRocketMQConfig() RocketMQConfig { CumulativeRechargeConsumerGroup: "hyapp-activity-cumulative-recharge-wallet-outbox", InviteActivityConsumerGroup: "hyapp-activity-invite-wallet-outbox", RedPacketBroadcastConsumerGroup: "hyapp-activity-red-packet-wallet-outbox", + VIPRebateNoticeConsumerGroup: "hyapp-activity-vip-rebate-notice-wallet-outbox", TaskConsumerGroup: "hyapp-activity-task-wallet-outbox", UserLeaderboardConsumerGroup: "hyapp-activity-user-leaderboard-wallet-outbox", ConsumerMaxReconsumeTimes: 16, @@ -473,6 +475,9 @@ func normalizeRocketMQConfig(cfg RocketMQConfig) (RocketMQConfig, error) { if cfg.WalletOutbox.RedPacketBroadcastConsumerGroup = strings.TrimSpace(cfg.WalletOutbox.RedPacketBroadcastConsumerGroup); cfg.WalletOutbox.RedPacketBroadcastConsumerGroup == "" { cfg.WalletOutbox.RedPacketBroadcastConsumerGroup = defaults.WalletOutbox.RedPacketBroadcastConsumerGroup } + if cfg.WalletOutbox.VIPRebateNoticeConsumerGroup = strings.TrimSpace(cfg.WalletOutbox.VIPRebateNoticeConsumerGroup); cfg.WalletOutbox.VIPRebateNoticeConsumerGroup == "" { + cfg.WalletOutbox.VIPRebateNoticeConsumerGroup = defaults.WalletOutbox.VIPRebateNoticeConsumerGroup + } if cfg.WalletOutbox.TaskConsumerGroup = strings.TrimSpace(cfg.WalletOutbox.TaskConsumerGroup); cfg.WalletOutbox.TaskConsumerGroup == "" { cfg.WalletOutbox.TaskConsumerGroup = defaults.WalletOutbox.TaskConsumerGroup } diff --git a/services/activity-service/internal/config/config_test.go b/services/activity-service/internal/config/config_test.go index 515ab57c..799dee3c 100644 --- a/services/activity-service/internal/config/config_test.go +++ b/services/activity-service/internal/config/config_test.go @@ -17,7 +17,7 @@ func TestLoadLocalEnablesOutboxMQConsumers(t *testing.T) { if cfg.UserLeaderboardWorker.RedisAddr != "127.0.0.1:13379" || cfg.UserLeaderboardWorker.KeyPrefix != "activity:user_leaderboard" { t.Fatalf("local user leaderboard worker redis config mismatch: %+v", cfg.UserLeaderboardWorker) } - if cfg.RocketMQ.WalletOutbox.InviteActivityConsumerGroup == "" || cfg.RocketMQ.WalletOutbox.UserLeaderboardConsumerGroup == "" || cfg.RocketMQ.UserOutbox.InviteActivityConsumerGroup == "" { + if cfg.RocketMQ.WalletOutbox.InviteActivityConsumerGroup == "" || cfg.RocketMQ.WalletOutbox.UserLeaderboardConsumerGroup == "" || cfg.RocketMQ.WalletOutbox.VIPRebateNoticeConsumerGroup == "" || cfg.RocketMQ.UserOutbox.InviteActivityConsumerGroup == "" { t.Fatalf("local config must configure invite activity consumer groups: wallet=%+v user=%+v", cfg.RocketMQ.WalletOutbox, cfg.RocketMQ.UserOutbox) } } diff --git a/services/activity-service/internal/domain/broadcast/broadcast.go b/services/activity-service/internal/domain/broadcast/broadcast.go index 502a043e..d5431eed 100644 --- a/services/activity-service/internal/domain/broadcast/broadcast.go +++ b/services/activity-service/internal/domain/broadcast/broadcast.go @@ -22,6 +22,9 @@ const ( TypeRoomPasswordChanged = "room_password_changed" // TypeLuckyGiftBigWin 是幸运礼物中奖区域飘屏;当前只让 10 倍及以上大奖进入播报 outbox。 TypeLuckyGiftBigWin = "lucky_gift_big_win" + // TypeVIPOnlineNotice 是 VIP 用户进入 App 时的全局飘屏。是否允许发送必须由 gateway + // 先向 wallet-service 校验 effective benefit,activity-service 只负责持久化和 IM 投递。 + TypeVIPOnlineNotice = "vip_online_notice" // StatusPending 表示消息已持久化,尚未被 worker claim。 StatusPending = "pending" diff --git a/services/activity-service/internal/domain/growth/growth.go b/services/activity-service/internal/domain/growth/growth.go index 891784ae..6e9b77b2 100644 --- a/services/activity-service/internal/domain/growth/growth.go +++ b/services/activity-service/internal/domain/growth/growth.go @@ -8,10 +8,30 @@ const ( StatusActive = "active" StatusDisabled = "disabled" - RewardStatusPending = "pending" - RewardStatusRunning = "running" - RewardStatusGranted = "granted" - RewardStatusFailed = "failed" + RewardStatusPending = "pending" + RewardStatusRunning = "running" + RewardStatusGranted = "granted" + RewardStatusFailed = "failed" + RewardStatusCanceled = "canceled" + + RewardOriginOrganic = "organic" + RewardOriginTemporary = "temporary" + + RevokeStatusNone = "none" + RevokeStatusPending = "pending" + RevokeStatusRunning = "running" + RevokeStatusRevoked = "revoked" + RevokeStatusFailed = "failed" + RevokeStatusSkipped = "skipped" + + TemporaryLevelStatusActive = "active" + TemporaryLevelStatusSuperseded = "superseded" + TemporaryLevelStatusExpired = "expired" + + NoticeStatusPending = "pending" + NoticeStatusSent = "sent" + NoticeStatusSkipped = "skipped" + NoticeStatusFailed = "failed" RewardSourceLevel = "level" RewardSourceTier = "tier" @@ -218,22 +238,121 @@ type SetUserLevelResult struct { ServerTimeMS int64 } -// RewardJob 是等级奖励资源组的异步发放任务。 -type RewardJob struct { - AppCode string +// TemporaryLevel 是真实成长账户之上的限时展示层。BaselineTotalValue 只做审计, +// 有效期经验始终按 value event 的 occurred_at_ms 落在 [StartedAtMS, ExpiresAtMS) 内聚合。 +type TemporaryLevel struct { + AppCode string + TemporaryLevelID string + CommandID string + UserID int64 + Track string + TargetLevel int32 + TargetRequiredValue int64 + BaselineTotalValue int64 + StartedAtMS int64 + ExpiresAtMS int64 + Status string + Generation int32 + OperatorAdminID int64 + Reason string + FinalLevel int32 + ActivationNoticeStatus string + ExpiryNoticeStatus string + AttemptCount int32 + FailureReason string + CreatedAtMS int64 + UpdatedAtMS int64 +} + +// TemporaryLevelAdjustment 是一次后台临时等级调整。wealth/charm 可在同一命令中各出现一次。 +type TemporaryLevelAdjustment struct { + Track string + Level int32 + DurationDays int32 +} + +// AdjustTemporaryLevelsCommand 以 CommandID 为整批幂等键;RequestHash 用于拒绝同键不同载荷。 +type AdjustTemporaryLevelsCommand struct { + CommandID string + RequestHash string + UserID int64 + Adjustments []TemporaryLevelAdjustment + OperatorAdminID int64 + Reason string +} + +// AdminTrackProfile 同时返回真实账户和当前展示层,后台无需从临时目标反推真实经验。 +type AdminTrackProfile struct { + Track string + RealLevel int32 + RealTotalValue int64 + DisplayLevel int32 + DisplayValue int64 + TemporaryLevelID string + TemporaryTargetLevel int32 + StartedAtMS int64 + ExpiresAtMS int64 +} + +type AdminUserLevelProfile struct { + UserID int64 + Tracks []AdminTrackProfile + ServerTimeMS int64 +} + +type AdminLevelProfiles struct { + Profiles []AdminUserLevelProfile + ServerTimeMS int64 +} + +// TemporaryLevelWork 是 cron 认领后的副作用快照。过期状态、奖励永久化/撤回准备均已在认领事务内提交。 +type TemporaryLevelWork struct { + TemporaryLevel + SendActivationNotice bool + SendExpiryNotice bool +} + +// RewardWalletGrant 保存一个奖励任务下的每次钱包发放。资源组、头像框和短徽章必须分别留痕。 +type RewardWalletGrant struct { + RewardJobID string + GrantKind string + WalletGrantID string + CreatedAtMS int64 +} + +// RewardRevocation 是一条可独立幂等重试的钱包 grant 撤回任务。 +type RewardRevocation struct { RewardJobID string + WalletGrantID string + TemporaryLevelID string UserID int64 Track string - RewardSourceType string - RewardSourceID string - ResourceGroupID int64 - WalletCommandID string - WalletGrantID string - Status string AttemptCount int32 - FailureReason string - CreatedAtMS int64 - UpdatedAtMS int64 +} + +// RewardJob 是等级奖励资源组的异步发放任务。 +type RewardJob struct { + AppCode string + RewardJobID string + UserID int64 + Track string + RewardSourceType string + RewardSourceID string + ResourceGroupID int64 + WalletCommandID string + WalletGrantID string + RewardOrigin string + TemporaryLevelID string + GrantGeneration int32 + RewardLevel int32 + Permanent bool + TemporaryExpiresAtMS int64 + RevokeStatus string + Status string + AttemptCount int32 + FailureReason string + CreatedAtMS int64 + UpdatedAtMS int64 } // RewardQuery 是用户奖励记录分页筛选。 diff --git a/services/activity-service/internal/service/broadcast/service.go b/services/activity-service/internal/service/broadcast/service.go index e77e5e19..ceaf834f 100644 --- a/services/activity-service/internal/service/broadcast/service.go +++ b/services/activity-service/internal/service/broadcast/service.go @@ -681,7 +681,9 @@ func normalizedPayloadJSON(input string, forced map[string]any) (string, error) } for key, value := range forced { if key == "region_id" && value.(int64) <= 0 { - // 全局播报不写 region_id,避免客户端误把 0 当作一个真实区域。 + // 全局播报必须删除调用方可能夹带的 region_id,避免客户端把伪造区域或 0 + // 当成真实路由维度;只跳过 forced 写入会保留原 payload 中的脏字段。 + delete(payload, "region_id") continue } // forced 字段覆盖调用方 payload,保证 event_id/scope/app_code/sent_at_ms 不被外部请求伪造。 diff --git a/services/activity-service/internal/service/broadcast/service_test.go b/services/activity-service/internal/service/broadcast/service_test.go index 5365dc05..8ecad56a 100644 --- a/services/activity-service/internal/service/broadcast/service_test.go +++ b/services/activity-service/internal/service/broadcast/service_test.go @@ -178,6 +178,54 @@ func TestProcessPendingBroadcastsPublishesCustomMessage(t *testing.T) { } } +func TestVIPOnlineNoticeUsesGlobalOutboxAndStableEnvelope(t *testing.T) { + repository := newFakeRepository() + publisher := &fakePublisher{} + service := New(Config{NodeID: "node-a"}, repository, publisher, nil) + service.SetClock(func() time.Time { return time.UnixMilli(1_800_000_000_000) }) + ctx := appcode.WithContext(context.Background(), "fami") + input := PublishInput{ + EventID: "vip_online_notice:42:digest", + BroadcastType: broadcastdomain.TypeVIPOnlineNotice, + PayloadJSON: `{"event_id":"forged","broadcast_type":"forged","scope":"region","app_code":"lalu","region_id":999,"user_id":42,"vip_level":9}`, + } + result, err := service.PublishGlobalBroadcast(ctx, input) + if err != nil { + t.Fatalf("PublishGlobalBroadcast failed: %v", err) + } + if !result.Created || result.GroupID != "hy_fami_bc_g_v2" || result.Status != broadcastdomain.StatusPending { + t.Fatalf("global publish result mismatch: %+v", result) + } + record := repository.records[input.EventID] + if record.Scope != broadcastdomain.ScopeGlobal || record.GroupID != "hy_fami_bc_g_v2" || record.BroadcastType != broadcastdomain.TypeVIPOnlineNotice { + t.Fatalf("global outbox mismatch: %+v", record) + } + var payload map[string]any + if err := json.Unmarshal([]byte(record.PayloadJSON), &payload); err != nil { + t.Fatalf("decode global payload: %v", err) + } + if payload["event_id"] != input.EventID || payload["broadcast_type"] != broadcastdomain.TypeVIPOnlineNotice || payload["scope"] != broadcastdomain.ScopeGlobal || payload["app_code"] != "fami" || payload["sent_at_ms"] != float64(1_800_000_000_000) { + t.Fatalf("forced global envelope mismatch: %+v", payload) + } + if _, exists := payload["region_id"]; exists { + t.Fatalf("global payload must not carry region_id: %+v", payload) + } + + // 同一个 event_id 的 HTTP 重试只返回已有 outbox,不能覆盖首个用户资料快照或重复发送。 + retry, err := service.PublishGlobalBroadcast(ctx, PublishInput{EventID: input.EventID, BroadcastType: broadcastdomain.TypeVIPOnlineNotice, PayloadJSON: `{"user_id":99}`}) + if err != nil || retry.Created || repository.records[input.EventID].PayloadJSON != record.PayloadJSON { + t.Fatalf("global retry must be idempotent: retry=%+v record=%+v err=%v", retry, repository.records[input.EventID], err) + } + processed, err := service.ProcessPendingBroadcasts(ctx, WorkerOptions{WorkerID: "worker-vip", BatchSize: 10}) + if err != nil || processed.SuccessCount != 1 || len(publisher.messages) != 2 { + // 全局 v2 成功后会向 v1 旧群补发一份,两个 TIMCustomElem 共享同一业务 payload。 + t.Fatalf("VIP online IM publish mismatch: result=%+v messages=%+v err=%v", processed, publisher.messages, err) + } + if publisher.messages[0].Desc != broadcastdomain.TypeVIPOnlineNotice || publisher.messages[0].Ext != "im_broadcast" || publisher.messages[0].EventID != input.EventID { + t.Fatalf("VIP online TIMCustomElem mismatch: %+v", publisher.messages[0]) + } +} + func TestConsumeRedPacketCreatedBuildsFullIMPayload(t *testing.T) { repository := newFakeRepository() service := New(Config{NodeID: "node-a"}, repository, nil, nil) diff --git a/services/activity-service/internal/service/growth/service.go b/services/activity-service/internal/service/growth/service.go index 79e02f26..54e668f2 100644 --- a/services/activity-service/internal/service/growth/service.go +++ b/services/activity-service/internal/service/growth/service.go @@ -2,8 +2,10 @@ package growth import ( "context" + "crypto/sha256" "encoding/json" "fmt" + "sort" "strconv" "strings" "time" @@ -15,6 +17,7 @@ import ( "hyapp/pkg/appcode" "hyapp/pkg/xerr" domain "hyapp/services/activity-service/internal/domain/growth" + messageservice "hyapp/services/activity-service/internal/service/message" ) const levelRewardReason = "growth_level_reward" @@ -38,29 +41,53 @@ type Repository interface { ListLevelRewards(ctx context.Context, query domain.RewardQuery) ([]domain.RewardJob, int64, error) ConsumeLevelEvent(ctx context.Context, event domain.ValueEvent, nowMS int64) (domain.EventResult, error) SetUserLevel(ctx context.Context, command domain.SetUserLevelCommand, nowMS int64) (domain.SetUserLevelResult, error) + BatchGetUserLevelAdminProfiles(ctx context.Context, userIDs []int64, nowMS int64) (domain.AdminLevelProfiles, error) + AdjustTemporaryUserLevels(ctx context.Context, command domain.AdjustTemporaryLevelsCommand, nowMS int64) (domain.AdminUserLevelProfile, error) UpsertLevelTrack(ctx context.Context, command domain.TrackCommand, nowMS int64) (domain.Track, bool, error) UpsertLevelRule(ctx context.Context, command domain.RuleCommand, nowMS int64) (domain.Rule, bool, error) UpsertLevelTier(ctx context.Context, command domain.TierCommand, nowMS int64) (domain.Tier, bool, error) ClaimPendingLevelRewardJobs(ctx context.Context, workerID string, nowMS int64, lockTTL time.Duration, batchSize int) ([]domain.RewardJob, error) - MarkLevelRewardGranted(ctx context.Context, rewardJobID string, walletGrantID string, nowMS int64) error - MarkLevelRewardFailed(ctx context.Context, rewardJobID string, failureReason string, nextRetryAtMS int64, nowMS int64) error + MarkLevelRewardGranted(ctx context.Context, rewardJobID string, grants []domain.RewardWalletGrant, nowMS int64) error + MarkLevelRewardFailed(ctx context.Context, rewardJobID string, grants []domain.RewardWalletGrant, failureReason string, nextRetryAtMS int64, nowMS int64) error + ClaimTemporaryLevelWork(ctx context.Context, workerID string, nowMS int64, lockTTL time.Duration, batchSize int) ([]domain.TemporaryLevelWork, error) + MarkTemporaryLevelNotices(ctx context.Context, temporaryLevelID string, activationStatus string, expiryStatus string, failureReason string, nextRetryAtMS int64, nowMS int64) error + ClaimLevelRewardRevocations(ctx context.Context, workerID string, nowMS int64, lockTTL time.Duration, batchSize int) ([]domain.RewardRevocation, error) + MarkLevelRewardRevoked(ctx context.Context, rewardJobID string, walletGrantID string, nowMS int64) error + MarkLevelRewardRevokeFailed(ctx context.Context, rewardJobID string, walletGrantID string, failureReason string, nextRetryAtMS int64, nowMS int64) error } // WalletClient 是等级奖励发放的唯一外部副作用。 type WalletClient interface { GrantResource(ctx context.Context, req *walletv1.GrantResourceRequest, opts ...grpc.CallOption) (*walletv1.ResourceGrantResponse, error) GrantResourceGroup(ctx context.Context, req *walletv1.GrantResourceGroupRequest, opts ...grpc.CallOption) (*walletv1.ResourceGrantResponse, error) + RevokeResourceGrant(ctx context.Context, req *walletv1.RevokeResourceGrantRequest, opts ...grpc.CallOption) (*walletv1.ResourceGrantResponse, error) +} + +// NoticeService 只调用 message service 的公开 helper;growth 不直接写 inbox 表。 +type NoticeService interface { + CreateSystemNotice(ctx context.Context, cmd messageservice.NoticeCommand) (messageservice.NoticeResult, error) +} + +type Option func(*Service) + +func WithNoticeService(notices NoticeService) Option { + return func(service *Service) { service.notices = notices } } // Service 承载 App 查询、事件消费、后台配置和等级奖励补偿。 type Service struct { repository Repository wallet WalletClient + notices NoticeService now func() time.Time } -func New(repository Repository, wallet WalletClient) *Service { - return &Service{repository: repository, wallet: wallet, now: time.Now} +func New(repository Repository, wallet WalletClient, options ...Option) *Service { + service := &Service{repository: repository, wallet: wallet, now: time.Now} + for _, option := range options { + option(service) + } + return service } func (s *Service) SetClock(now func() time.Time) { @@ -112,6 +139,65 @@ func (s *Service) BatchGetUserLevelDisplayProfiles(ctx context.Context, userIDs return s.repository.BatchGetUserLevelDisplayProfiles(ctx, normalized, s.now().UnixMilli()) } +// BatchGetUserLevelAdminProfiles 返回真实账户和当前有效 overlay;到期毫秒由 repository 读取条件立即排除, +// 所以后台展示不会依赖 cron 是否已经把记录推进为 expired。 +func (s *Service) BatchGetUserLevelAdminProfiles(ctx context.Context, userIDs []int64) (domain.AdminLevelProfiles, error) { + if err := s.requireRepository(); err != nil { + return domain.AdminLevelProfiles{}, err + } + normalized := uniquePositiveUserIDs(userIDs) + if len(normalized) == 0 { + return domain.AdminLevelProfiles{Profiles: []domain.AdminUserLevelProfile{}, ServerTimeMS: s.now().UnixMilli()}, nil + } + if len(normalized) > 500 { + return domain.AdminLevelProfiles{}, xerr.New(xerr.InvalidArgument, "too many user ids; maximum is 500") + } + return s.repository.BatchGetUserLevelAdminProfiles(ctx, normalized, s.now().UnixMilli()) +} + +// AdjustTemporaryUserLevels 校验整批命令后只调用一次 repository,保证 wealth/charm 要么一起生效、要么一起回滚。 +func (s *Service) AdjustTemporaryUserLevels(ctx context.Context, command domain.AdjustTemporaryLevelsCommand) (domain.AdminUserLevelProfile, error) { + if err := s.requireRepository(); err != nil { + return domain.AdminUserLevelProfile{}, err + } + command.CommandID = strings.TrimSpace(command.CommandID) + command.Reason = strings.TrimSpace(command.Reason) + if command.CommandID == "" || command.UserID <= 0 || command.OperatorAdminID <= 0 || len(command.Adjustments) == 0 || len(command.Adjustments) > 2 { + return domain.AdminUserLevelProfile{}, xerr.New(xerr.InvalidArgument, "temporary level command is incomplete") + } + seen := make(map[string]struct{}, len(command.Adjustments)) + for index := range command.Adjustments { + item := &command.Adjustments[index] + item.Track = normalizeTrack(item.Track) + if item.Track != domain.TrackWealth && item.Track != domain.TrackCharm { + return domain.AdminUserLevelProfile{}, xerr.New(xerr.InvalidArgument, "temporary level track must be wealth or charm") + } + if item.Level < 1 || item.Level > 50 || item.DurationDays <= 0 { + return domain.AdminUserLevelProfile{}, xerr.New(xerr.InvalidArgument, "temporary level must be 1..50 and duration_days must be positive") + } + if _, exists := seen[item.Track]; exists { + return domain.AdminUserLevelProfile{}, xerr.New(xerr.InvalidArgument, "temporary level track is duplicated") + } + seen[item.Track] = struct{}{} + } + // 排序让同一业务载荷生成稳定 hash,也让 repository 以固定轨道顺序加锁,降低双轨并发死锁概率。 + sort.Slice(command.Adjustments, func(i, j int) bool { return command.Adjustments[i].Track < command.Adjustments[j].Track }) + if command.Reason == "" { + command.Reason = "admin_temporary_level" + } + hashPayload, _ := json.Marshal(struct { + UserID int64 `json:"user_id"` + Adjustments []domain.TemporaryLevelAdjustment `json:"adjustments"` + OperatorAdminID int64 `json:"operator_admin_id"` + Reason string `json:"reason"` + }{ + UserID: command.UserID, Adjustments: command.Adjustments, + OperatorAdminID: command.OperatorAdminID, Reason: command.Reason, + }) + command.RequestHash = fmt.Sprintf("%x", sha256.Sum256(hashPayload)) + return s.repository.AdjustTemporaryUserLevels(ctx, command, s.now().UTC().UnixMilli()) +} + func (s *Service) IssueRegistrationLevelBadges(ctx context.Context, userID int64, commandID string) (domain.RegistrationLevelBadgeGrants, error) { if err := s.requireRepository(); err != nil { return domain.RegistrationLevelBadgeGrants{}, err @@ -386,14 +472,16 @@ func (s *Service) ProcessLevelRewardBatch(ctx context.Context, runID string, wor } for _, job := range jobs { processed++ - walletGrantID, grantErr := s.grantLevelRewardJob(ctx, job) + walletGrants, grantErr := s.grantLevelRewardJob(ctx, job) if grantErr != nil { failure++ nextRetry := s.now().Add(time.Minute).UnixMilli() - _ = s.repository.MarkLevelRewardFailed(ctx, job.RewardJobID, xerr.MessageOf(grantErr), nextRetry, s.now().UnixMilli()) + // One reward job may span several idempotent wallet commands. Persist every successful prefix even when a + // later command fails, otherwise an overlay expiry cannot discover and revoke the already-issued asset. + _ = s.repository.MarkLevelRewardFailed(ctx, job.RewardJobID, walletGrants, xerr.MessageOf(grantErr), nextRetry, s.now().UnixMilli()) continue } - if markErr := s.repository.MarkLevelRewardGranted(ctx, job.RewardJobID, walletGrantID, s.now().UnixMilli()); markErr != nil { + if markErr := s.repository.MarkLevelRewardGranted(ctx, job.RewardJobID, walletGrants, s.now().UnixMilli()); markErr != nil { failure++ continue } @@ -402,8 +490,9 @@ func (s *Service) ProcessLevelRewardBatch(ctx context.Context, runID string, wor return int32(len(jobs)), processed, success, failure, len(jobs) == batchSize, nil } -func (s *Service) grantLevelRewardJob(ctx context.Context, job domain.RewardJob) (string, error) { - walletGrantID := "" +func (s *Service) grantLevelRewardJob(ctx context.Context, job domain.RewardJob) ([]domain.RewardWalletGrant, error) { + grants := make([]domain.RewardWalletGrant, 0, 3) + nowMS := s.now().UnixMilli() if job.ResourceGroupID > 0 { // 资源组奖励沿用原有配置快照;command_id 后缀把组奖励和单资源等级物料奖励拆成多个钱包幂等动作。 resp, err := s.wallet.GrantResourceGroup(ctx, &walletv1.GrantResourceGroupRequest{ @@ -416,16 +505,19 @@ func (s *Service) grantLevelRewardJob(ctx context.Context, job domain.RewardJob) GrantSource: domain.GrantSourceGrowthLevel, }) if err != nil { - return "", err + return grants, err } if resp.GetGrant() != nil { - walletGrantID = resp.GetGrant().GetGrantId() + grants = append(grants, domain.RewardWalletGrant{RewardJobID: job.RewardJobID, GrantKind: "resource_group", WalletGrantID: resp.GetGrant().GetGrantId(), CreatedAtMS: nowMS}) } } levelResources, err := s.levelResourceIDsForRewardJob(ctx, job) if err != nil { - return "", err + return grants, err } + durationMS := levelAvatarFrameRewardDurationMS + // 临时直发物料也按自然奖励的长有效期授予,并由记录到子表的 grant 在 overlay 到期时显式撤回。 + // 这样用户在有效期内真实达到该等级后只需把任务提升为永久并跳过撤回,钱包权益不会仍按临时截止时间消失。 if levelResources.avatarFrameResourceID > 0 { // 等级头像框是每级固定物料,不依赖运营额外创建资源组;按产品要求直接发 9999 天权益。 resp, err := s.wallet.GrantResource(ctx, &walletv1.GrantResourceRequest{ @@ -434,16 +526,16 @@ func (s *Service) grantLevelRewardJob(ctx context.Context, job domain.RewardJob) TargetUserId: job.UserID, ResourceId: levelResources.avatarFrameResourceID, Quantity: 1, - DurationMs: levelAvatarFrameRewardDurationMS, + DurationMs: durationMS, Reason: levelRewardReason, OperatorUserId: job.UserID, GrantSource: domain.GrantSourceGrowthLevel, }) if err != nil { - return "", err + return grants, err } - if walletGrantID == "" && resp.GetGrant() != nil { - walletGrantID = resp.GetGrant().GetGrantId() + if resp.GetGrant() != nil { + grants = append(grants, domain.RewardWalletGrant{RewardJobID: job.RewardJobID, GrantKind: "avatar_frame", WalletGrantID: resp.GetGrant().GetGrantId(), CreatedAtMS: nowMS}) } } if levelResources.shortBadgeResourceID > 0 { @@ -454,19 +546,140 @@ func (s *Service) grantLevelRewardJob(ctx context.Context, job domain.RewardJob) TargetUserId: job.UserID, ResourceId: levelResources.shortBadgeResourceID, Quantity: 1, - DurationMs: levelAvatarFrameRewardDurationMS, + DurationMs: durationMS, Reason: levelRewardReason, OperatorUserId: job.UserID, GrantSource: domain.GrantSourceGrowthLevel, }) if err != nil { - return "", err + return grants, err } - if walletGrantID == "" && resp.GetGrant() != nil { - walletGrantID = resp.GetGrant().GetGrantId() + if resp.GetGrant() != nil { + grants = append(grants, domain.RewardWalletGrant{RewardJobID: job.RewardJobID, GrantKind: "short_badge", WalletGrantID: resp.GetGrant().GetGrantId(), CreatedAtMS: nowMS}) } } - return walletGrantID, nil + return grants, nil +} + +// ProcessTemporaryLevelBatch 推进过期状态、发送幂等系统消息并撤回不再应得的临时奖励。 +// 状态准备由 repository 事务完成,外部副作用失败只回写 retry_at,不会重新污染真实成长账户。 +func (s *Service) ProcessTemporaryLevelBatch(ctx context.Context, workerID string, batchSize int, lockTTL time.Duration) (claimed int32, processed int32, success int32, failure int32, hasMore bool, err error) { + if err := s.requireRepository(); err != nil { + return 0, 0, 0, 0, false, err + } + if s.wallet == nil || s.notices == nil { + return 0, 0, 0, 0, false, xerr.New(xerr.Unavailable, "temporary level side effects are not configured") + } + if batchSize <= 0 { + batchSize = 100 + } + if lockTTL <= 0 { + lockTTL = 30 * time.Second + } + if strings.TrimSpace(workerID) == "" { + workerID = "activity-temporary-level" + } + nowMS := s.now().UTC().UnixMilli() + works, err := s.repository.ClaimTemporaryLevelWork(ctx, workerID, nowMS, lockTTL, batchSize) + if err != nil { + return 0, 0, 0, 0, false, err + } + for _, work := range works { + processed++ + activationStatus, expiryStatus := "", "" + var workErr error + if work.SendActivationNotice { + workErr = s.sendTemporaryLevelNotice(ctx, work, false, nowMS) + if workErr == nil { + activationStatus = domain.NoticeStatusSent + } else { + activationStatus = domain.NoticeStatusFailed + } + } + if workErr == nil && work.SendExpiryNotice { + workErr = s.sendTemporaryLevelNotice(ctx, work, true, nowMS) + if workErr == nil { + expiryStatus = domain.NoticeStatusSent + } else { + expiryStatus = domain.NoticeStatusFailed + } + } + failureReason := "" + nextRetryAtMS := int64(0) + if workErr != nil { + failure++ + failureReason = xerr.MessageOf(workErr) + nextRetryAtMS = s.now().Add(time.Minute).UnixMilli() + } else { + success++ + } + if markErr := s.repository.MarkTemporaryLevelNotices(ctx, work.TemporaryLevelID, activationStatus, expiryStatus, failureReason, nextRetryAtMS, s.now().UnixMilli()); markErr != nil { + failure++ + if workErr == nil && success > 0 { + success-- + } + } + } + remaining := batchSize - len(works) + revocations := []domain.RewardRevocation{} + if remaining > 0 { + revocations, err = s.repository.ClaimLevelRewardRevocations(ctx, workerID, s.now().UnixMilli(), lockTTL, remaining) + if err != nil { + return int32(len(works)), processed, success, failure, false, err + } + } + for _, revoke := range revocations { + processed++ + _, revokeErr := s.wallet.RevokeResourceGrant(ctx, &walletv1.RevokeResourceGrantRequest{ + RequestId: fmt.Sprintf("temporary-level-revoke:%s:%s", revoke.RewardJobID, revoke.WalletGrantID), + AppCode: appcode.FromContext(ctx), + GrantId: revoke.WalletGrantID, + Reason: "temporary_level_expired", + OperatorUserId: revoke.UserID, + }) + if revokeErr != nil { + failure++ + _ = s.repository.MarkLevelRewardRevokeFailed(ctx, revoke.RewardJobID, revoke.WalletGrantID, xerr.MessageOf(revokeErr), s.now().Add(time.Minute).UnixMilli(), s.now().UnixMilli()) + continue + } + if markErr := s.repository.MarkLevelRewardRevoked(ctx, revoke.RewardJobID, revoke.WalletGrantID, s.now().UnixMilli()); markErr != nil { + failure++ + continue + } + success++ + } + claimed = int32(len(works) + len(revocations)) + hasMore = len(works) == batchSize || (remaining > 0 && len(revocations) == remaining) + return claimed, processed, success, failure, hasMore, nil +} + +func (s *Service) sendTemporaryLevelNotice(ctx context.Context, work domain.TemporaryLevelWork, expired bool, nowMS int64) error { + trackName := map[string]string{domain.TrackWealth: "富豪", domain.TrackCharm: "魅力"}[work.Track] + body := fmt.Sprintf("尊敬的用户,官方已将您%s等级临时升级为Lv%d,有效期%d天,请在有效期内继续升级哦", trackName, work.TargetLevel, (work.ExpiresAtMS-work.StartedAtMS)/(24*60*60*1000)) + eventSuffix := "activated" + eventType := "temporary_level_activated" + if expired { + body = fmt.Sprintf("您的临时%s等级Lv%d已到期,根据您在有效期内的经验值,现恢复为Lv%d", trackName, work.TargetLevel, work.FinalLevel) + eventSuffix = "expired" + eventType = "temporary_level_expired" + } + _, err := s.notices.CreateSystemNotice(ctx, messageservice.NoticeCommand{ + TargetUserID: work.UserID, + Producer: "growth-level", + ProducerEventID: fmt.Sprintf("temporary-level:%s:%s", work.TemporaryLevelID, eventSuffix), + ProducerEventType: eventType, + AggregateType: "temporary_growth_level", + AggregateID: work.TemporaryLevelID, + Title: "系统通知", + Summary: body, + Body: body, + SentAtMS: nowMS, + Metadata: map[string]any{ + "track": work.Track, "target_level": work.TargetLevel, "final_level": work.FinalLevel, + "started_at_ms": work.StartedAtMS, "expires_at_ms": work.ExpiresAtMS, + }, + }) + return err } type levelRewardResourceIDs struct { @@ -642,3 +855,19 @@ func validMetricForTrack(track string, metric string) bool { return false } } + +func uniquePositiveUserIDs(values []int64) []int64 { + result := make([]int64, 0, len(values)) + seen := make(map[int64]struct{}, len(values)) + for _, value := range values { + if value <= 0 { + continue + } + if _, exists := seen[value]; exists { + continue + } + seen[value] = struct{}{} + result = append(result, value) + } + return result +} diff --git a/services/activity-service/internal/service/growth/service_test.go b/services/activity-service/internal/service/growth/service_test.go index 86664be1..ff9a93d9 100644 --- a/services/activity-service/internal/service/growth/service_test.go +++ b/services/activity-service/internal/service/growth/service_test.go @@ -13,6 +13,7 @@ import ( "hyapp/pkg/appcode" domain "hyapp/services/activity-service/internal/domain/growth" growthservice "hyapp/services/activity-service/internal/service/growth" + messageservice "hyapp/services/activity-service/internal/service/message" "hyapp/services/activity-service/internal/testutil/mysqltest" ) @@ -88,6 +89,507 @@ func TestGrowthLevelEventRewardFlow(t *testing.T) { } } +func TestTemporaryGrowthLevelOverlayExpiresAndRevokesAllWalletGrants(t *testing.T) { + repository := mysqltest.NewRepository(t) + wallet := &fakeGrowthWallet{} + notices := &fakeGrowthNoticeService{} + now := fixedGrowthNow() + svc := growthservice.New(repository, wallet, growthservice.WithNoticeService(notices)) + svc.SetClock(func() time.Time { return now }) + ctx := appcode.WithContext(context.Background(), "lalu") + seedGrowthRules(t, ctx, svc, domain.TrackWealth) + if _, created, err := svc.UpsertLevelRule(ctx, domain.RuleCommand{ + Track: domain.TrackWealth, Level: 2, RequiredValue: 200, Name: "wealth 2", Status: domain.StatusActive, + RewardResourceGroupID: 9002, SortOrder: 2, + DisplayConfigJSON: `{"long_badge_resource_id":702,"avatar_frame_resource_id":802,"short_badge_resource_id":902}`, + OperatorAdminID: 90001, + }); err != nil || created { + t.Fatalf("update temporary reward resources failed: created=%v err=%v", created, err) + } + + profile, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-level-command-1", UserID: 51001, OperatorAdminID: 90001, + Adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 2, DurationDays: 7}}, + }) + if err != nil { + t.Fatalf("AdjustTemporaryUserLevels failed: %v", err) + } + wealth := findAdminTrack(profile.Tracks, domain.TrackWealth) + if wealth.RealLevel != 0 || wealth.DisplayLevel != 2 || wealth.DisplayValue != 200 || wealth.TemporaryLevelID == "" { + t.Fatalf("temporary profile mismatch: %+v", wealth) + } + // Same command and payload is a read-only idempotent replay; it must not create a second generation. + replayed, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-level-command-1", UserID: 51001, OperatorAdminID: 90001, + Adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 2, DurationDays: 7}}, + }) + if err != nil || findAdminTrack(replayed.Tracks, domain.TrackWealth).TemporaryLevelID != wealth.TemporaryLevelID { + t.Fatalf("temporary command replay mismatch: profile=%+v err=%v", replayed, err) + } + if _, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-level-command-1", UserID: 51001, OperatorAdminID: 90001, Reason: "changed-payload", + Adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 2, DurationDays: 7}}, + }); err == nil { + t.Fatal("same command id with a changed reason must be rejected as an idempotency conflict") + } + + if _, _, success, failure, _, err := svc.ProcessTemporaryLevelBatch(ctx, "worker-notice", 10, time.Second); err != nil || success != 1 || failure != 0 || len(notices.commands) != 1 { + t.Fatalf("activation notice batch mismatch: success=%d failure=%d notices=%d err=%v", success, failure, len(notices.commands), err) + } + if claimed, _, success, failure, _, err := svc.ProcessLevelRewardBatch(ctx, "run-temp-reward", "worker-reward", 10, time.Second); err != nil || claimed != 3 || success != 3 || failure != 0 { + t.Fatalf("temporary reward batch mismatch: claimed=%d success=%d failure=%d err=%v", claimed, success, failure, err) + } + for _, grant := range wallet.resourceGrants { + if grant.GetDurationMs() != 9999*24*time.Hour.Milliseconds() { + t.Fatalf("temporary direct resource must rely on explicit revoke instead of wallet expiry: %+v", grant) + } + } + + // The end instant is exclusive: before cron runs, every read must already ignore the overlay. + now = now.Add(7 * 24 * time.Hour) + profiles, err := svc.BatchGetUserLevelAdminProfiles(ctx, []int64{51001}) + if err != nil { + t.Fatalf("BatchGetUserLevelAdminProfiles at expiry failed: %v", err) + } + atExpiry := findAdminTrack(profiles.Profiles[0].Tracks, domain.TrackWealth) + if atExpiry.DisplayLevel != 0 || atExpiry.TemporaryLevelID != "" { + t.Fatalf("expired overlay must be ignored immediately: %+v", atExpiry) + } + claimed, processed, success, failure, _, err := svc.ProcessTemporaryLevelBatch(ctx, "worker-expiry", 20, time.Second) + if err != nil || claimed != 6 || processed != 6 || success != 6 || failure != 0 { + t.Fatalf("expiry batch mismatch: claimed=%d processed=%d success=%d failure=%d err=%v", claimed, processed, success, failure, err) + } + if len(wallet.revokes) != 5 || len(notices.commands) != 2 { + t.Fatalf("expiry side effects mismatch: revokes=%d notices=%d", len(wallet.revokes), len(notices.commands)) + } +} + +func TestTemporaryGrowthLevelExpiredGenerationIsMaterializedBeforeNewAdjustment(t *testing.T) { + repository := mysqltest.NewRepository(t) + wallet := &fakeGrowthWallet{} + notices := &fakeGrowthNoticeService{} + now := fixedGrowthNow() + svc := growthservice.New(repository, wallet, growthservice.WithNoticeService(notices)) + svc.SetClock(func() time.Time { return now }) + ctx := appcode.WithContext(context.Background(), "lalu") + seedGrowthRules(t, ctx, svc, domain.TrackWealth) + if _, created, err := svc.UpsertLevelRule(ctx, domain.RuleCommand{ + Track: domain.TrackWealth, Level: 3, RequiredValue: 300, Name: "wealth 3", Status: domain.StatusActive, + SortOrder: 3, DisplayConfigJSON: `{}`, OperatorAdminID: 90001, + }); err != nil || !created { + t.Fatalf("seed level 3 failed: created=%v err=%v", created, err) + } + first, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-expired-before-replace-1", UserID: 51007, OperatorAdminID: 90001, + Adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 2, DurationDays: 1}}, + }) + if err != nil { + t.Fatalf("create first temporary generation failed: %v", err) + } + firstID := findAdminTrack(first.Tracks, domain.TrackWealth).TemporaryLevelID + now = now.Add(24 * time.Hour) + second, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-expired-before-replace-2", UserID: 51007, OperatorAdminID: 90001, + Adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 3, DurationDays: 1}}, + }) + if err != nil { + t.Fatalf("create second temporary generation failed: %v", err) + } + current := findAdminTrack(second.Tracks, domain.TrackWealth) + if current.TemporaryLevelID == "" || current.TemporaryLevelID == firstID || current.DisplayLevel != 3 { + t.Fatalf("new generation must replace only after old expiry is materialized: first=%s current=%+v", firstID, current) + } + claimed, processed, success, failure, _, err := svc.ProcessTemporaryLevelBatch(ctx, "worker-expired-replace", 10, time.Second) + if err != nil || claimed != 2 || processed != 2 || success != 2 || failure != 0 || len(notices.commands) != 2 { + t.Fatalf("old expiry and new activation must both remain retryable: claimed=%d processed=%d success=%d failure=%d notices=%d err=%v", claimed, processed, success, failure, len(notices.commands), err) + } +} + +func TestTemporaryGrowthWorkersReclaimExpiredRunningLocks(t *testing.T) { + repository := mysqltest.NewRepository(t) + wallet := &fakeGrowthWallet{} + now := fixedGrowthNow() + svc := growthservice.New(repository, wallet, growthservice.WithNoticeService(&fakeGrowthNoticeService{})) + svc.SetClock(func() time.Time { return now }) + ctx := appcode.WithContext(context.Background(), "lalu") + seedGrowthRules(t, ctx, svc, domain.TrackWealth) + if _, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-reward-reclaim", UserID: 51008, OperatorAdminID: 90001, + Adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 2, DurationDays: 1}}, + }); err != nil { + t.Fatalf("seed reward reclaim generation failed: %v", err) + } + firstJobs, err := repository.ClaimPendingLevelRewardJobs(ctx, "crashed-reward-worker", now.UnixMilli(), time.Second, 20) + if err != nil || len(firstJobs) == 0 { + t.Fatalf("first reward claim failed: jobs=%d err=%v", len(firstJobs), err) + } + reclaimedJobs, err := repository.ClaimPendingLevelRewardJobs(ctx, "replacement-reward-worker", now.Add(time.Second).UnixMilli(), time.Second, 20) + if err != nil || len(reclaimedJobs) != len(firstJobs) { + t.Fatalf("expired running reward locks must be reclaimed: first=%d reclaimed=%d err=%v", len(firstJobs), len(reclaimedJobs), err) + } + + // A separate generation is fully granted so revocation child rows can exercise the same crash-recovery boundary. + if _, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-revoke-reclaim", UserID: 51009, OperatorAdminID: 90001, + Adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 2, DurationDays: 1}}, + }); err != nil { + t.Fatalf("seed revoke reclaim generation failed: %v", err) + } + if claimed, _, success, failure, _, err := svc.ProcessLevelRewardBatch(ctx, "revoke-reclaim-grant-run", "reward-worker", 20, time.Second); err != nil || claimed == 0 || success != claimed || failure != 0 { + t.Fatalf("grant revocation seed jobs failed: claimed=%d success=%d failure=%d err=%v", claimed, success, failure, err) + } + expiresAt := now.Add(24 * time.Hour) + if _, err := repository.ClaimTemporaryLevelWork(ctx, "expiry-materializer", expiresAt.UnixMilli(), time.Second, 20); err != nil { + t.Fatalf("materialize temporary expiry failed: %v", err) + } + firstRevokes, err := repository.ClaimLevelRewardRevocations(ctx, "crashed-revoke-worker", expiresAt.UnixMilli(), time.Second, 100) + if err != nil || len(firstRevokes) == 0 { + t.Fatalf("first revoke claim failed: revokes=%d err=%v", len(firstRevokes), err) + } + reclaimedRevokes, err := repository.ClaimLevelRewardRevocations(ctx, "replacement-revoke-worker", expiresAt.Add(time.Second).UnixMilli(), time.Second, 100) + if err != nil || len(reclaimedRevokes) != len(firstRevokes) { + t.Fatalf("expired running revoke locks must be reclaimed: first=%d reclaimed=%d err=%v", len(firstRevokes), len(reclaimedRevokes), err) + } +} + +func TestTemporaryRewardsBecomePermanentWhenRealLevelCatchesUp(t *testing.T) { + repository := mysqltest.NewRepository(t) + wallet := &fakeGrowthWallet{} + now := fixedGrowthNow() + svc := growthservice.New(repository, wallet, growthservice.WithNoticeService(&fakeGrowthNoticeService{})) + svc.SetClock(func() time.Time { return now }) + ctx := appcode.WithContext(context.Background(), "lalu") + seedGrowthRules(t, ctx, svc, domain.TrackWealth) + if _, created, err := svc.UpsertLevelRule(ctx, domain.RuleCommand{ + Track: domain.TrackWealth, Level: 2, RequiredValue: 200, Name: "wealth 2", Status: domain.StatusActive, + RewardResourceGroupID: 9002, SortOrder: 2, + DisplayConfigJSON: `{"avatar_frame_resource_id":802,"short_badge_resource_id":902}`, + OperatorAdminID: 90001, + }); err != nil || created { + t.Fatalf("update level 2 direct rewards failed: created=%v err=%v", created, err) + } + if _, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-promote-permanent", UserID: 51010, OperatorAdminID: 90001, + Adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 2, DurationDays: 1}}, + }); err != nil { + t.Fatalf("create temporary promotion generation failed: %v", err) + } + if claimed, _, success, _, _, err := svc.ProcessLevelRewardBatch(ctx, "temporary-promotion-grants", "reward-worker", 20, time.Second); err != nil || claimed == 0 || success != claimed { + t.Fatalf("grant temporary promotion rewards failed: claimed=%d success=%d err=%v", claimed, success, err) + } + now = now.Add(time.Millisecond) + if _, err := svc.ConsumeLevelEvent(ctx, domain.ValueEvent{ + EventID: "temporary-promotion-organic", SourceEventID: "temporary-promotion-organic", SourceService: "room-service", + SourceEventType: "RoomGiftSent", UserID: 51010, Track: domain.TrackWealth, + MetricType: domain.MetricGiftSpendCoin, ValueDelta: 200, OccurredAtMS: now.UnixMilli(), DimensionsJSON: `{}`, + }); err != nil { + t.Fatalf("organic catch-up event failed: %v", err) + } + now = fixedGrowthNow().Add(24 * time.Hour) + if _, _, _, _, _, err := svc.ProcessTemporaryLevelBatch(ctx, "promotion-expiry-worker", 20, time.Second); err != nil { + t.Fatalf("process promoted generation expiry failed: %v", err) + } + if len(wallet.revokes) != 0 { + t.Fatalf("rewards earned by real level must remain permanent, revokes=%d", len(wallet.revokes)) + } + for _, grant := range wallet.resourceGrants { + if grant.GetDurationMs() != 9999*24*time.Hour.Milliseconds() { + t.Fatalf("promoted direct resource would still expire in wallet: %+v", grant) + } + } +} + +func TestTemporaryRewardGenerationReplacementCarriesLiveGrantsWithoutDuplicateIssue(t *testing.T) { + repository := mysqltest.NewRepository(t) + wallet := &fakeGrowthWallet{} + now := fixedGrowthNow() + svc := growthservice.New(repository, wallet, growthservice.WithNoticeService(&fakeGrowthNoticeService{})) + svc.SetClock(func() time.Time { return now }) + ctx := appcode.WithContext(context.Background(), "lalu") + seedGrowthRules(t, ctx, svc, domain.TrackWealth) + if _, created, err := svc.UpsertLevelRule(ctx, domain.RuleCommand{ + Track: domain.TrackWealth, Level: 2, RequiredValue: 200, Name: "wealth 2", Status: domain.StatusActive, + RewardResourceGroupID: 9002, SortOrder: 2, + DisplayConfigJSON: `{"avatar_frame_resource_id":802,"short_badge_resource_id":902}`, + OperatorAdminID: 90001, + }); err != nil || created { + t.Fatalf("update level 2 resources failed: created=%v err=%v", created, err) + } + first, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-generation-carry-1", UserID: 51011, OperatorAdminID: 90001, + Adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 2, DurationDays: 1}}, + }) + if err != nil { + t.Fatalf("create first temporary generation failed: %v", err) + } + firstID := findAdminTrack(first.Tracks, domain.TrackWealth).TemporaryLevelID + if claimed, _, success, failure, _, err := svc.ProcessLevelRewardBatch(ctx, "temporary-generation-carry-grant", "reward-worker", 20, time.Second); err != nil || claimed == 0 || success != claimed || failure != 0 { + t.Fatalf("grant first generation failed: claimed=%d success=%d failure=%d err=%v", claimed, success, failure, err) + } + groupGrants, directGrants := len(wallet.grants), len(wallet.resourceGrants) + + // 覆盖调整建立新计时基线,但目标范围内已发放的 grant 必须迁移到新代,不能撤回再发造成重复权益。 + now = now.Add(time.Hour) + second, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-generation-carry-2", UserID: 51011, OperatorAdminID: 90001, + Adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 2, DurationDays: 1}}, + }) + if err != nil { + t.Fatalf("replace temporary generation failed: %v", err) + } + secondTrack := findAdminTrack(second.Tracks, domain.TrackWealth) + if secondTrack.TemporaryLevelID == "" || secondTrack.TemporaryLevelID == firstID { + t.Fatalf("replacement must create a distinct generation: first=%s second=%+v", firstID, secondTrack) + } + if claimed, _, success, failure, _, err := svc.ProcessLevelRewardBatch(ctx, "temporary-generation-carry-no-duplicate", "reward-worker", 20, time.Second); err != nil || claimed != 0 || success != 0 || failure != 0 { + t.Fatalf("replacement must not enqueue duplicate grants: claimed=%d success=%d failure=%d err=%v", claimed, success, failure, err) + } + if len(wallet.grants) != groupGrants || len(wallet.resourceGrants) != directGrants { + t.Fatalf("replacement duplicated wallet grants: groups=%d/%d direct=%d/%d", len(wallet.grants), groupGrants, len(wallet.resourceGrants), directGrants) + } + + // 自然成长只提升当前代中迁移过来的奖励;到期后这些 grant 不得再进入撤回队列。 + now = now.Add(time.Millisecond) + if _, err := svc.ConsumeLevelEvent(ctx, domain.ValueEvent{ + EventID: "temporary-generation-carry-organic", SourceEventID: "temporary-generation-carry-organic", SourceService: "room-service", + SourceEventType: "RoomGiftSent", UserID: 51011, Track: domain.TrackWealth, + MetricType: domain.MetricGiftSpendCoin, ValueDelta: 200, OccurredAtMS: now.UnixMilli(), DimensionsJSON: `{}`, + }); err != nil { + t.Fatalf("organic catch-up after replacement failed: %v", err) + } + now = time.UnixMilli(secondTrack.ExpiresAtMS).UTC() + if _, _, _, _, _, err := svc.ProcessTemporaryLevelBatch(ctx, "temporary-generation-carry-expiry", 100, time.Second); err != nil { + t.Fatalf("process replacement expiry failed: %v", err) + } + if len(wallet.revokes) != 0 { + t.Fatalf("current-generation grants promoted by real growth must not be revoked: revokes=%d", len(wallet.revokes)) + } +} + +func TestSupersededRewardWithFailedRevokeIsNotPromotedByNaturalGrowth(t *testing.T) { + repository := mysqltest.NewRepository(t) + wallet := &fakeGrowthWallet{} + now := fixedGrowthNow() + svc := growthservice.New(repository, wallet, growthservice.WithNoticeService(&fakeGrowthNoticeService{})) + svc.SetClock(func() time.Time { return now }) + ctx := appcode.WithContext(context.Background(), "lalu") + seedGrowthRules(t, ctx, svc, domain.TrackWealth) + if _, created, err := svc.UpsertLevelRule(ctx, domain.RuleCommand{ + Track: domain.TrackWealth, Level: 3, RequiredValue: 300, Name: "wealth 3", Status: domain.StatusActive, + RewardResourceGroupID: 9004, SortOrder: 3, + DisplayConfigJSON: `{"avatar_frame_resource_id":803,"short_badge_resource_id":903}`, + OperatorAdminID: 90001, + }); err != nil || !created { + t.Fatalf("seed level 3 resources failed: created=%v err=%v", created, err) + } + if _, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-failed-revoke-1", UserID: 51012, OperatorAdminID: 90001, + Adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 3, DurationDays: 1}}, + }); err != nil { + t.Fatalf("create high temporary generation failed: %v", err) + } + if claimed, _, success, failure, _, err := svc.ProcessLevelRewardBatch(ctx, "temporary-failed-revoke-grant", "reward-worker", 50, time.Second); err != nil || claimed == 0 || success != claimed || failure != 0 { + t.Fatalf("grant high temporary generation failed: claimed=%d success=%d failure=%d err=%v", claimed, success, failure, err) + } + + // 降低覆盖目标时仅 Lv3 留在旧代撤回;模拟钱包撤回失败,验证后续自然 Lv3 不会把旧代事实误标永久。 + now = now.Add(time.Hour) + if _, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-failed-revoke-2", UserID: 51012, OperatorAdminID: 90001, + Adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 2, DurationDays: 1}}, + }); err != nil { + t.Fatalf("replace with lower temporary target failed: %v", err) + } + revocations, err := repository.ClaimLevelRewardRevocations(ctx, "failed-revoke-worker", now.UnixMilli(), time.Second, 100) + if err != nil || len(revocations) == 0 { + t.Fatalf("claim superseded level 3 revocations failed: revocations=%d err=%v", len(revocations), err) + } + for _, revoke := range revocations { + if err := repository.MarkLevelRewardRevokeFailed(ctx, revoke.RewardJobID, revoke.WalletGrantID, "wallet timeout", now.Add(time.Minute).UnixMilli(), now.UnixMilli()); err != nil { + t.Fatalf("mark superseded revoke failed: %v", err) + } + } + + now = now.Add(time.Millisecond) + if _, err := svc.ConsumeLevelEvent(ctx, domain.ValueEvent{ + EventID: "temporary-failed-revoke-organic", SourceEventID: "temporary-failed-revoke-organic", SourceService: "room-service", + SourceEventType: "RoomGiftSent", UserID: 51012, Track: domain.TrackWealth, + MetricType: domain.MetricGiftSpendCoin, ValueDelta: 300, OccurredAtMS: now.UnixMilli(), DimensionsJSON: `{}`, + }); err != nil { + t.Fatalf("natural level 3 event failed: %v", err) + } + rewards, _, err := svc.ListLevelRewards(ctx, domain.RewardQuery{UserID: 51012, Track: domain.TrackWealth, PageSize: 100}) + if err != nil { + t.Fatalf("list rewards after natural level 3 failed: %v", err) + } + var oldTemporary, freshOrganic int + for _, reward := range rewards { + if reward.RewardSourceType != domain.RewardSourceLevel || reward.RewardSourceID != "level:3" { + continue + } + if reward.RewardOrigin == domain.RewardOriginTemporary && !reward.Permanent && reward.RevokeStatus == domain.RevokeStatusFailed { + oldTemporary++ + } + if reward.RewardOrigin == domain.RewardOriginOrganic && reward.Permanent { + freshOrganic++ + } + } + if oldTemporary != 1 || freshOrganic != 1 { + t.Fatalf("natural growth must preserve failed old revoke and create one new permanent job: old=%d organic=%d rewards=%+v", oldTemporary, freshOrganic, rewards) + } + groupGrants, directGrants := len(wallet.grants), len(wallet.resourceGrants) + if claimed, _, success, failure, _, err := svc.ProcessLevelRewardBatch(ctx, "temporary-failed-revoke-organic-grant", "reward-worker", 20, time.Second); err != nil || claimed != 1 || success != 1 || failure != 0 { + t.Fatalf("fresh organic level 3 grant failed: claimed=%d success=%d failure=%d err=%v", claimed, success, failure, err) + } + if len(wallet.grants) != groupGrants+1 || len(wallet.resourceGrants) != directGrants+2 { + t.Fatalf("fresh organic job must issue independent replacement grants: groups=%d/%d direct=%d/%d", len(wallet.grants), groupGrants, len(wallet.resourceGrants), directGrants) + } +} + +func TestTemporaryRewardPartialWalletSuccessIsDurableAndRevokedAtExpiry(t *testing.T) { + repository := mysqltest.NewRepository(t) + wallet := &fakePartialGrowthWallet{failNextResource: true} + now := fixedGrowthNow() + svc := growthservice.New(repository, wallet, growthservice.WithNoticeService(&fakeGrowthNoticeService{})) + svc.SetClock(func() time.Time { return now }) + ctx := appcode.WithContext(context.Background(), "lalu") + for _, rule := range []domain.RuleCommand{ + {Track: domain.TrackWealth, Level: 1, RequiredValue: 100, Name: "wealth 1", Status: domain.StatusActive, SortOrder: 1, DisplayConfigJSON: `{}`, OperatorAdminID: 90001}, + {Track: domain.TrackWealth, Level: 2, RequiredValue: 200, Name: "wealth 2", Status: domain.StatusActive, RewardResourceGroupID: 9002, SortOrder: 2, DisplayConfigJSON: `{"avatar_frame_resource_id":802}`, OperatorAdminID: 90001}, + } { + if _, created, err := svc.UpsertLevelRule(ctx, rule); err != nil || !created { + t.Fatalf("seed partial-grant rule level %d failed: created=%v err=%v", rule.Level, created, err) + } + } + profile, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-partial-wallet-grant", UserID: 51013, OperatorAdminID: 90001, + Adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 2, DurationDays: 1}}, + }) + if err != nil { + t.Fatalf("create partial-grant temporary level failed: %v", err) + } + track := findAdminTrack(profile.Tracks, domain.TrackWealth) + if claimed, _, success, failure, _, err := svc.ProcessLevelRewardBatch(ctx, "temporary-partial-wallet-grant-run", "reward-worker", 20, time.Second); err != nil || claimed != 1 || success != 0 || failure != 1 { + t.Fatalf("partial wallet grant batch mismatch: claimed=%d success=%d failure=%d err=%v", claimed, success, failure, err) + } + if len(wallet.grants) != 1 || len(wallet.resourceGrants) != 0 { + t.Fatalf("test precondition requires group success followed by direct-resource failure: groups=%d resources=%d", len(wallet.grants), len(wallet.resourceGrants)) + } + + // 到期事务必须能看见失败任务中已成功的资源组 grant,并把它交给撤回 worker。 + now = time.UnixMilli(track.ExpiresAtMS).UTC() + if _, _, _, failure, _, err := svc.ProcessTemporaryLevelBatch(ctx, "temporary-partial-wallet-expiry", 20, time.Second); err != nil || failure != 0 { + t.Fatalf("process partial-grant expiry failed: failure=%d err=%v", failure, err) + } + if len(wallet.revokes) != 1 || wallet.revokes[0].GetGrantId() != "grant-1" { + t.Fatalf("successful wallet prefix must be explicitly revoked: revokes=%+v", wallet.revokes) + } + rewards, _, err := svc.ListLevelRewards(ctx, domain.RewardQuery{UserID: 51013, Track: domain.TrackWealth, PageSize: 20}) + if err != nil || len(rewards) != 1 || rewards[0].Status != domain.RewardStatusCanceled || rewards[0].RevokeStatus != domain.RevokeStatusRevoked { + t.Fatalf("partial reward terminal state mismatch: rewards=%+v err=%v", rewards, err) + } +} + +func TestTemporaryGrowthLevelDualTrackValidationRollsBackWholeCommand(t *testing.T) { + svc, _ := newGrowthService(t) + ctx := appcode.WithContext(context.Background(), "lalu") + seedGrowthRules(t, ctx, svc, domain.TrackWealth) + + _, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-level-command-atomic", UserID: 51002, OperatorAdminID: 90001, + Adjustments: []domain.TemporaryLevelAdjustment{ + {Track: domain.TrackWealth, Level: 2, DurationDays: 7}, + // charm has no active level-2 rule in this isolated schema, so the whole transaction must fail. + {Track: domain.TrackCharm, Level: 2, DurationDays: 7}, + }, + }) + if err == nil { + t.Fatal("dual-track command should fail when one active rule is missing") + } + profiles, queryErr := svc.BatchGetUserLevelAdminProfiles(ctx, []int64{51002}) + if queryErr != nil { + t.Fatalf("BatchGetUserLevelAdminProfiles failed: %v", queryErr) + } + if wealth := findAdminTrack(profiles.Profiles[0].Tracks, domain.TrackWealth); wealth.TemporaryLevelID != "" || wealth.DisplayLevel != wealth.RealLevel { + t.Fatalf("wealth adjustment leaked from rolled-back command: %+v", wealth) + } +} + +func TestTemporaryGrowthLevelAddsWindowExperienceWithoutMutatingRealTotal(t *testing.T) { + repository := mysqltest.NewRepository(t) + wallet := &fakeGrowthWallet{} + now := fixedGrowthNow() + svc := growthservice.New(repository, wallet) + svc.SetClock(func() time.Time { return now }) + ctx := appcode.WithContext(context.Background(), "lalu") + seedGrowthRules(t, ctx, svc, domain.TrackWealth) + if _, created, err := svc.UpsertLevelRule(ctx, domain.RuleCommand{ + Track: domain.TrackWealth, Level: 3, RequiredValue: 300, Name: "wealth 3", Status: domain.StatusActive, + SortOrder: 3, DisplayConfigJSON: `{}`, OperatorAdminID: 90001, + }); err != nil || !created { + t.Fatalf("seed level 3 failed: created=%v err=%v", created, err) + } + if _, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: "temporary-level-window", UserID: 51003, OperatorAdminID: 90001, + Adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 2, DurationDays: 1}}, + }); err != nil { + t.Fatalf("AdjustTemporaryUserLevels failed: %v", err) + } + if _, err := svc.ConsumeLevelEvent(ctx, domain.ValueEvent{ + EventID: "temporary-window-event", SourceEventID: "temporary-window-event", SourceService: "room-service", + SourceEventType: "RoomGiftSent", UserID: 51003, Track: domain.TrackWealth, + MetricType: domain.MetricGiftSpendCoin, ValueDelta: 100, OccurredAtMS: now.UnixMilli(), DimensionsJSON: `{}`, + }); err != nil { + t.Fatalf("ConsumeLevelEvent failed: %v", err) + } + profiles, err := svc.BatchGetUserLevelAdminProfiles(ctx, []int64{51003}) + if err != nil { + t.Fatalf("BatchGetUserLevelAdminProfiles failed: %v", err) + } + wealth := findAdminTrack(profiles.Profiles[0].Tracks, domain.TrackWealth) + if wealth.RealTotalValue != 100 || wealth.RealLevel != 1 || wealth.DisplayValue != 300 || wealth.DisplayLevel != 3 { + t.Fatalf("real and overlay progress must remain separate: %+v", wealth) + } + now = now.Add(24 * time.Hour) + profiles, err = svc.BatchGetUserLevelAdminProfiles(ctx, []int64{51003}) + if err != nil { + t.Fatalf("expiry profile failed: %v", err) + } + wealth = findAdminTrack(profiles.Profiles[0].Tracks, domain.TrackWealth) + if wealth.RealTotalValue != 100 || wealth.DisplayValue != 100 || wealth.DisplayLevel != 1 || wealth.TemporaryLevelID != "" { + t.Fatalf("expiry must reveal untouched real account: %+v", wealth) + } +} + +func TestTemporaryGrowthLevelRejectsInvalidTracksBoundsAndDuration(t *testing.T) { + svc, _ := newGrowthService(t) + ctx := appcode.WithContext(context.Background(), "lalu") + tests := []struct { + name string + adjustments []domain.TemporaryLevelAdjustment + }{ + {name: "game is read only", adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackGame, Level: 2, DurationDays: 7}}}, + {name: "level zero", adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 0, DurationDays: 7}}}, + {name: "above level fifty", adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackCharm, Level: 51, DurationDays: 7}}}, + {name: "zero duration", adjustments: []domain.TemporaryLevelAdjustment{{Track: domain.TrackWealth, Level: 2, DurationDays: 0}}}, + {name: "duplicate track", adjustments: []domain.TemporaryLevelAdjustment{ + {Track: domain.TrackWealth, Level: 2, DurationDays: 7}, + {Track: domain.TrackWealth, Level: 3, DurationDays: 7}, + }}, + } + for index, test := range tests { + t.Run(test.name, func(t *testing.T) { + _, err := svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: fmt.Sprintf("temporary-invalid-%d", index), UserID: 51004, OperatorAdminID: 90001, + Adjustments: test.adjustments, + }) + if err == nil { + t.Fatalf("invalid adjustment was accepted: %+v", test.adjustments) + } + }) + } +} + func TestGrowthLevelEventConcurrentSameUserTrack(t *testing.T) { svc, _ := newGrowthService(t) ctx := appcode.WithContext(context.Background(), "lalu") @@ -488,9 +990,48 @@ func findTrackOverview(items []domain.TrackOverview, track string) domain.TrackO return domain.TrackOverview{} } +func findAdminTrack(items []domain.AdminTrackProfile, track string) domain.AdminTrackProfile { + for _, item := range items { + if item.Track == track { + return item + } + } + return domain.AdminTrackProfile{} +} + type fakeGrowthWallet struct { grants []*walletv1.GrantResourceGroupRequest resourceGrants []*walletv1.GrantResourceRequest + revokes []*walletv1.RevokeResourceGrantRequest +} + +// fakePartialGrowthWallet reproduces a multi-action reward where the resource group commits but a later direct +// resource RPC fails. Real wallet command IDs are idempotent; the test focuses on activity's durable grant ledger. +type fakePartialGrowthWallet struct { + fakeGrowthWallet + failNextResource bool +} + +func (f *fakePartialGrowthWallet) GrantResource(ctx context.Context, req *walletv1.GrantResourceRequest, opts ...grpc.CallOption) (*walletv1.ResourceGrantResponse, error) { + if f.failNextResource { + f.failNextResource = false + return nil, fmt.Errorf("injected direct resource failure") + } + return f.fakeGrowthWallet.GrantResource(ctx, req, opts...) +} + +func (f *fakeGrowthWallet) RevokeResourceGrant(_ context.Context, req *walletv1.RevokeResourceGrantRequest, _ ...grpc.CallOption) (*walletv1.ResourceGrantResponse, error) { + f.revokes = append(f.revokes, req) + return &walletv1.ResourceGrantResponse{Grant: &walletv1.ResourceGrant{GrantId: req.GetGrantId(), Status: "revoked"}}, nil +} + +type fakeGrowthNoticeService struct { + commands []messageservice.NoticeCommand +} + +func (f *fakeGrowthNoticeService) CreateSystemNotice(_ context.Context, cmd messageservice.NoticeCommand) (messageservice.NoticeResult, error) { + f.commands = append(f.commands, cmd) + return messageservice.NoticeResult{Created: true}, nil } func (f *fakeGrowthWallet) GrantResource(_ context.Context, req *walletv1.GrantResourceRequest, _ ...grpc.CallOption) (*walletv1.ResourceGrantResponse, error) { diff --git a/services/activity-service/internal/service/message/action_type_test.go b/services/activity-service/internal/service/message/action_type_test.go new file mode 100644 index 00000000..81139378 --- /dev/null +++ b/services/activity-service/internal/service/message/action_type_test.go @@ -0,0 +1,14 @@ +package message + +import "testing" + +func TestAllowedActionTypeIncludesVIPCoinRebateClaim(t *testing.T) { + // 返现通知由 wallet 事实触发,如果该动作从白名单回归,消息会在进入 MySQL 前被拒绝, + // Flutter 也就永远拿不到 rebate_id。这个纯单测不依赖可选的 MySQL 测试环境。 + if !allowedActionType("vip_coin_rebate_claim") { + t.Fatal("vip_coin_rebate_claim must remain an allowed system inbox action") + } + if allowedActionType("vip_coin_rebate_claim_javascript") { + t.Fatal("action whitelist must still reject unregistered variants") + } +} diff --git a/services/activity-service/internal/service/message/service.go b/services/activity-service/internal/service/message/service.go index 2bf9bc02..78317591 100644 --- a/services/activity-service/internal/service/message/service.go +++ b/services/activity-service/internal/service/message/service.go @@ -467,6 +467,10 @@ func allowedActionType(actionType string) bool { switch actionType { case "", "wallet_withdraw_detail", "host_application_detail", "activity_detail", "room_detail", "user_profile", "app_h5", "coin_seller_transfer_detail": return true + case "vip_coin_rebate_claim": + // VIP 返现通知只携带 wallet 生成的 rebate_id JSON,客户端仍需调用受鉴权的 + // claim 接口才能入账;它不是任意外链或脚本动作,可以进入 system inbox。 + return true default: return false } diff --git a/services/activity-service/internal/storage/mysql/growth_repository.go b/services/activity-service/internal/storage/mysql/growth_repository.go index b861b663..f3c09d8d 100644 --- a/services/activity-service/internal/storage/mysql/growth_repository.go +++ b/services/activity-service/internal/storage/mysql/growth_repository.go @@ -128,9 +128,58 @@ func (r *Repository) BatchGetUserLevelDisplayProfiles(ctx context.Context, userI if err := rows.Err(); err != nil { return domain.LevelDisplayProfiles{}, err } + adminProfiles, err := r.BatchGetUserLevelAdminProfiles(ctx, userIDs, nowMS) + if err != nil { + return domain.LevelDisplayProfiles{}, err + } + adminTracks := make(map[int64]map[string]domain.AdminTrackProfile, len(adminProfiles.Profiles)) + for _, profile := range adminProfiles.Profiles { + byTrack := make(map[string]domain.AdminTrackProfile, len(profile.Tracks)) + for _, track := range profile.Tracks { + byTrack[track.Track] = track + } + adminTracks[profile.UserID] = byTrack + } + rulesByTrack := make(map[string][]domain.Rule, 2) + tiersByTrack := make(map[string][]domain.Tier, 2) + for _, track := range []string{domain.TrackWealth, domain.TrackCharm} { + rules, err := r.listActiveLevelRules(ctx, r.db, track) + if err != nil { + return domain.LevelDisplayProfiles{}, err + } + tiers, err := r.listActiveLevelTiers(ctx, r.db, track) + if err != nil { + return domain.LevelDisplayProfiles{}, err + } + rulesByTrack[track] = rules + tiersByTrack[track] = tiers + } result := make([]domain.UserLevelDisplayProfile, 0, len(userIDs)) for _, userID := range userIDs { - result = append(result, profiles[userID]) + item := profiles[userID] + // 物化资料仍是真实账户快照;整批 admin profile 只在读取时覆盖有效 wealth/charm overlay, + // 既让到期毫秒立即生效,也避免房间资料批量接口按用户和轨道产生 N+1。 + for _, track := range []string{domain.TrackWealth, domain.TrackCharm} { + adminTrack := adminTracks[userID][track] + if adminTrack.TemporaryLevelID == "" { + continue + } + rules := rulesByTrack[track] + tiers := tiersByTrack[track] + tier := tierForLevel(tiers, adminTrack.DisplayLevel) + badgeID, badgeLevel := levelRuleBadgeForLevel(rules, adminTrack.DisplayLevel) + display := domain.LevelDisplayTrackProfile{ + Track: track, Level: adminTrack.DisplayLevel, TierID: tier.TierID, + AvatarFrameResourceID: levelRuleAvatarFrameForLevel(rules, adminTrack.DisplayLevel, tier.DisplayAvatarFrameResourceID), + BadgeResourceID: badgeID, BadgeSourceLevel: badgeLevel, UpdatedAtMS: nowMS, + } + if track == domain.TrackWealth { + item.Wealth = display + } else { + item.Charm = display + } + } + result = append(result, item) } return domain.LevelDisplayProfiles{Profiles: result, ServerTimeMS: nowMS}, nil } @@ -287,6 +336,25 @@ func (r *Repository) consumeLevelEventOnce(ctx context.Context, event domain.Val } rewardJobCount = count } + // While an overlay is active, only value events whose business time falls in [start,end) advance its displayed + // value. The real account above was updated independently and remains the sole permanent growth fact. + if temporary, found, err := r.activeTemporaryLevelForUpdate(ctx, tx, event.UserID, event.Track, nowMS); err != nil { + return domain.EventResult{}, err + } else if found && event.OccurredAtMS >= temporary.StartedAtMS && event.OccurredAtMS < temporary.ExpiresAtMS { + windowValue, err := r.temporaryWindowValue(ctx, tx, event.UserID, event.Track, temporary.StartedAtMS, temporary.ExpiresAtMS) + if err != nil { + return domain.EventResult{}, err + } + previousDisplayLevel := levelForValue(rules, temporary.TargetRequiredValue+windowValue-event.ValueDelta) + nextDisplayLevel := levelForValue(rules, temporary.TargetRequiredValue+windowValue) + if nextDisplayLevel > previousDisplayLevel { + count, err := r.createTemporaryRewardJobs(ctx, tx, event.UserID, event.Track, nextDisplayLevel, temporary.TemporaryLevelID, temporary.Generation, temporary.ExpiresAtMS, rules, tiers, nowMS) + if err != nil { + return domain.EventResult{}, err + } + rewardJobCount += count + } + } badgeResourceID, badgeSourceLevel := levelRuleBadgeForLevel(rules, nextLevel) avatarFrameResourceID := levelRuleAvatarFrameForLevel(rules, nextLevel, nextTier.DisplayAvatarFrameResourceID) if err := r.upsertLevelDisplayProfile(ctx, tx, event.UserID, event.Track, nextLevel, nextTier, avatarFrameResourceID, badgeResourceID, badgeSourceLevel, nowMS); err != nil { @@ -539,11 +607,12 @@ func (r *Repository) ClaimPendingLevelRewardJobs(ctx context.Context, workerID s } defer func() { _ = tx.Rollback() }() rows, err := tx.QueryContext(ctx, levelRewardSelectSQL()+` - WHERE app_code = ? AND status IN ('pending', 'failed') AND next_retry_at_ms <= ? + WHERE app_code = ? AND status IN ('pending', 'failed', 'running') AND next_retry_at_ms <= ? + AND (reward_origin = 'organic' OR is_permanent = 1 OR temporary_expires_at_ms > ?) AND (locked_until_ms = 0 OR locked_until_ms <= ?) ORDER BY created_at_ms ASC, reward_job_id ASC LIMIT ? FOR UPDATE SKIP LOCKED`, - appcode.FromContext(ctx), nowMS, nowMS, batchSize, + appcode.FromContext(ctx), nowMS, nowMS, nowMS, batchSize, ) if err != nil { return nil, err @@ -570,32 +639,141 @@ func (r *Repository) ClaimPendingLevelRewardJobs(ctx context.Context, workerID s return jobs, nil } -func (r *Repository) MarkLevelRewardGranted(ctx context.Context, rewardJobID string, walletGrantID string, nowMS int64) error { +func (r *Repository) MarkLevelRewardGranted(ctx context.Context, rewardJobID string, grants []domain.RewardWalletGrant, nowMS int64) error { if r == nil || r.db == nil { return xerr.New(xerr.Unavailable, "mysql repository is not configured") } - _, err := r.db.ExecContext(ctx, ` + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return err + } + defer func() { _ = tx.Rollback() }() + firstGrantID := "" + for _, grant := range grants { + if strings.TrimSpace(grant.WalletGrantID) == "" { + continue + } + if firstGrantID == "" { + firstGrantID = grant.WalletGrantID + } + // Each external action has its own wallet command. INSERT IGNORE makes a crash after wallet success safe to replay. + _, err := tx.ExecContext(ctx, ` + INSERT IGNORE INTO growth_level_reward_wallet_grants + (app_code, reward_job_id, grant_kind, wallet_grant_id, revoke_status, created_at_ms, updated_at_ms) + VALUES (?, ?, ?, ?, 'none', ?, ?)`, + appcode.FromContext(ctx), rewardJobID, grant.GrantKind, grant.WalletGrantID, nowMS, nowMS) + if err != nil { + return err + } + } + _, err = tx.ExecContext(ctx, ` UPDATE growth_level_reward_jobs SET status = 'granted', wallet_grant_id = ?, locked_by = '', locked_until_ms = 0, failure_reason = '', updated_at_ms = ? WHERE app_code = ? AND reward_job_id = ?`, - walletGrantID, nowMS, appcode.FromContext(ctx), rewardJobID, + firstGrantID, nowMS, appcode.FromContext(ctx), rewardJobID, ) - return err + if err != nil { + return err + } + var temporaryID string + var rewardLevel int32 + var permanent bool + if err := tx.QueryRowContext(ctx, `SELECT temporary_level_id, reward_level, is_permanent FROM growth_level_reward_jobs WHERE app_code = ? AND reward_job_id = ? FOR UPDATE`, appcode.FromContext(ctx), rewardJobID).Scan(&temporaryID, &rewardLevel, &permanent); err != nil { + return err + } + if temporaryID != "" && !permanent { + var status string + var finalLevel int32 + if err := tx.QueryRowContext(ctx, `SELECT status, final_level FROM growth_temporary_levels WHERE app_code = ? AND temporary_level_id = ?`, appcode.FromContext(ctx), temporaryID).Scan(&status, &finalLevel); err != nil { + return err + } + if status != domain.TemporaryLevelStatusActive && rewardLevel > finalLevel { + // A worker can finish after the overlay expires. Persist the grants, then immediately expose them to revoke worker. + revokeStatus := domain.RevokeStatusPending + if firstGrantID == "" { + revokeStatus = domain.RevokeStatusSkipped + } + if _, err := tx.ExecContext(ctx, `UPDATE growth_level_reward_jobs SET revoke_status = ?, updated_at_ms = ? WHERE app_code = ? AND reward_job_id = ?`, revokeStatus, nowMS, appcode.FromContext(ctx), rewardJobID); err != nil { + return err + } + if _, err := tx.ExecContext(ctx, `UPDATE growth_level_reward_wallet_grants SET revoke_status = 'pending', updated_at_ms = ? WHERE app_code = ? AND reward_job_id = ?`, nowMS, appcode.FromContext(ctx), rewardJobID); err != nil { + return err + } + } + } + return tx.Commit() } -func (r *Repository) MarkLevelRewardFailed(ctx context.Context, rewardJobID string, failureReason string, nextRetryAtMS int64, nowMS int64) error { +func (r *Repository) MarkLevelRewardFailed(ctx context.Context, rewardJobID string, grants []domain.RewardWalletGrant, failureReason string, nextRetryAtMS int64, nowMS int64) error { if r == nil || r.db == nil { return xerr.New(xerr.Unavailable, "mysql repository is not configured") } - _, err := r.db.ExecContext(ctx, ` + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return err + } + defer func() { _ = tx.Rollback() }() + for _, grant := range grants { + if strings.TrimSpace(grant.WalletGrantID) == "" { + continue + } + // Partial wallet success is a durable revoke fact even though the parent reward remains retryable. + if _, err := tx.ExecContext(ctx, ` + INSERT IGNORE INTO growth_level_reward_wallet_grants + (app_code, reward_job_id, grant_kind, wallet_grant_id, revoke_status, created_at_ms, updated_at_ms) + VALUES (?, ?, ?, ?, 'none', ?, ?)`, + appcode.FromContext(ctx), rewardJobID, grant.GrantKind, grant.WalletGrantID, nowMS, nowMS); err != nil { + return err + } + } + result, err := tx.ExecContext(ctx, ` UPDATE growth_level_reward_jobs SET status = 'failed', next_retry_at_ms = ?, locked_by = '', locked_until_ms = 0, failure_reason = ?, updated_at_ms = ? - WHERE app_code = ? AND reward_job_id = ? AND status <> 'granted'`, + WHERE app_code = ? AND reward_job_id = ? AND status = 'running'`, nextRetryAtMS, truncateGrowthFailure(failureReason), nowMS, appcode.FromContext(ctx), rewardJobID, ) - return err + if err != nil { + return err + } + if affected, err := result.RowsAffected(); err != nil { + return err + } else if affected == 0 { + return xerr.New(xerr.Conflict, "level reward job is no longer running") + } + var temporaryID string + var rewardLevel int32 + var permanent bool + if err := tx.QueryRowContext(ctx, `SELECT temporary_level_id, reward_level, is_permanent FROM growth_level_reward_jobs WHERE app_code = ? AND reward_job_id = ? FOR UPDATE`, appcode.FromContext(ctx), rewardJobID).Scan(&temporaryID, &rewardLevel, &permanent); err != nil { + return err + } + if temporaryID != "" && !permanent { + var status string + var finalLevel int32 + if err := tx.QueryRowContext(ctx, `SELECT status, final_level FROM growth_temporary_levels WHERE app_code = ? AND temporary_level_id = ?`, appcode.FromContext(ctx), temporaryID).Scan(&status, &finalLevel); err != nil { + return err + } + if status != domain.TemporaryLevelStatusActive && rewardLevel > finalLevel { + // Expiry/supersede can race the wallet calls. If it already won, expose the successful prefix directly to + // the revoke worker instead of leaving a failed parent whose assets are invisible forever. + var persistedGrantCount int + if err := tx.QueryRowContext(ctx, `SELECT COUNT(*) FROM growth_level_reward_wallet_grants WHERE app_code = ? AND reward_job_id = ?`, appcode.FromContext(ctx), rewardJobID).Scan(&persistedGrantCount); err != nil { + return err + } + revokeStatus := domain.RevokeStatusSkipped + if persistedGrantCount > 0 { + revokeStatus = domain.RevokeStatusPending + } + if _, err := tx.ExecContext(ctx, `UPDATE growth_level_reward_jobs SET status = 'canceled', revoke_status = ?, updated_at_ms = ? WHERE app_code = ? AND reward_job_id = ?`, revokeStatus, nowMS, appcode.FromContext(ctx), rewardJobID); err != nil { + return err + } + if _, err := tx.ExecContext(ctx, `UPDATE growth_level_reward_wallet_grants SET revoke_status = 'pending', revoke_next_retry_at_ms = 0, updated_at_ms = ? WHERE app_code = ? AND reward_job_id = ? AND revoke_status IN ('none','failed')`, nowMS, appcode.FromContext(ctx), rewardJobID); err != nil { + return err + } + } + } + return tx.Commit() } func (r *Repository) levelTrackOverview(ctx context.Context, userID int64, track domain.Track, nowMS int64) (domain.TrackOverview, error) { @@ -614,10 +792,25 @@ func (r *Repository) levelTrackOverview(ctx context.Context, userID int64, track if err != nil { return domain.TrackOverview{}, err } - tier := tierByID(tiers, account.CurrentTierID) - badgeResourceID, badgeSourceLevel := levelRuleBadgeForLevel(rules, account.CurrentLevel) - avatarFrameResourceID := levelRuleAvatarFrameForLevel(rules, account.CurrentLevel, tier.DisplayAvatarFrameResourceID) - currentRequired, nextLevel, nextRequired := levelProgress(rules, account.CurrentLevel) + displayLevel := account.CurrentLevel + displayValue := account.TotalValue + if temporary, found, err := r.activeTemporaryLevelForRead(ctx, userID, track.Track, nowMS); err != nil { + return domain.TrackOverview{}, err + } else if found { + increment, err := r.temporaryWindowValue(ctx, r.db, userID, track.Track, temporary.StartedAtMS, temporary.ExpiresAtMS) + if err != nil { + return domain.TrackOverview{}, err + } + displayValue = temporary.TargetRequiredValue + increment + displayLevel = levelForValue(rules, displayValue) + if displayLevel < temporary.TargetLevel { + displayLevel = temporary.TargetLevel + } + } + tier := tierForLevel(tiers, displayLevel) + badgeResourceID, badgeSourceLevel := levelRuleBadgeForLevel(rules, displayLevel) + avatarFrameResourceID := levelRuleAvatarFrameForLevel(rules, displayLevel, tier.DisplayAvatarFrameResourceID) + currentRequired, nextLevel, nextRequired := levelProgress(rules, displayLevel) pendingCount, err := r.pendingLevelRewardCount(ctx, userID, track.Track) if err != nil { return domain.TrackOverview{}, err @@ -625,9 +818,9 @@ func (r *Repository) levelTrackOverview(ctx context.Context, userID int64, track return domain.TrackOverview{ Track: track.Track, Name: track.Name, - Level: account.CurrentLevel, - TierID: account.CurrentTierID, - TotalValue: account.TotalValue, + Level: displayLevel, + TierID: tier.TierID, + TotalValue: displayValue, CurrentLevelRequiredValue: currentRequired, NextLevel: nextLevel, NextLevelRequiredValue: nextRequired, @@ -757,14 +950,48 @@ func (r *Repository) createLevelRewardJobs(ctx context.Context, tx *sql.Tx, user } func (r *Repository) insertLevelRewardJob(ctx context.Context, tx *sql.Tx, userID int64, track string, sourceType string, sourceID string, resourceGroupID int64, nowMS int64) (bool, error) { + // Natural growth permanently earns only the matching reward attached to the currently active overlay. Superseded, + // expired or already-revoking generations must finish revoke and get a fresh organic job; otherwise multiple old + // grants (or an RPC-timeout revoke that actually succeeded) could all be promoted into duplicate permanent assets. + promoted, err := tx.ExecContext(ctx, ` + UPDATE growth_level_reward_jobs j + JOIN growth_temporary_levels t + ON t.app_code = j.app_code AND t.temporary_level_id = j.temporary_level_id + SET j.is_permanent = 1, j.revoke_status = 'skipped', j.updated_at_ms = ? + WHERE j.app_code = ? AND j.user_id = ? AND j.track = ? + AND j.reward_source_type = ? AND j.reward_source_id = ? + AND j.reward_origin = 'temporary' AND j.is_permanent = 0 + AND j.status IN ('pending','failed','running','granted') AND j.revoke_status = 'none' + AND t.status = 'active' AND t.started_at_ms <= ? AND t.expires_at_ms > ?`, + nowMS, appcode.FromContext(ctx), userID, track, sourceType, sourceID, nowMS, nowMS) + if err != nil { + return false, err + } + if affected, err := promoted.RowsAffected(); err != nil { + return false, err + } else if affected > 0 { + _, err = tx.ExecContext(ctx, ` + UPDATE growth_level_reward_wallet_grants g + JOIN growth_level_reward_jobs j ON j.app_code = g.app_code AND j.reward_job_id = g.reward_job_id + JOIN growth_temporary_levels t ON t.app_code = j.app_code AND t.temporary_level_id = j.temporary_level_id + SET g.revoke_status = 'skipped', g.revoke_locked_by = '', g.revoke_locked_until_ms = 0, g.updated_at_ms = ? + WHERE j.app_code = ? AND j.user_id = ? AND j.track = ? AND j.reward_source_type = ? AND j.reward_source_id = ? + AND j.reward_origin = 'temporary' AND j.is_permanent = 1 + AND t.status = 'active' AND t.started_at_ms <= ? AND t.expires_at_ms > ? + AND g.revoke_status IN ('none','pending','failed')`, + nowMS, appcode.FromContext(ctx), userID, track, sourceType, sourceID, nowMS, nowMS) + return false, err + } rewardJobID := idgen.New("greward") + rewardLevel, _ := levelFromGrowthRewardSourceID(sourceID) result, err := tx.ExecContext(ctx, ` INSERT IGNORE INTO growth_level_reward_jobs ( app_code, reward_job_id, user_id, track, reward_source_type, reward_source_id, - resource_group_id, wallet_command_id, status, next_retry_at_ms, created_at_ms, updated_at_ms - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'pending', 0, ?, ?)`, + resource_group_id, wallet_command_id, reward_origin, grant_generation, reward_level, is_permanent, + status, next_retry_at_ms, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'organic', 0, ?, 1, 'pending', 0, ?, ?)`, appcode.FromContext(ctx), rewardJobID, userID, track, sourceType, sourceID, resourceGroupID, - "growth_level_reward:"+rewardJobID, nowMS, nowMS, + "growth_level_reward:"+rewardJobID, rewardLevel, nowMS, nowMS, ) if err != nil { return false, err @@ -1289,6 +1516,8 @@ func scanLevelReward(row rowScanner) (domain.RewardJob, error) { err := row.Scan( &item.AppCode, &item.RewardJobID, &item.UserID, &item.Track, &item.RewardSourceType, &item.RewardSourceID, &item.ResourceGroupID, &item.WalletCommandID, &item.WalletGrantID, + &item.RewardOrigin, &item.TemporaryLevelID, &item.GrantGeneration, &item.RewardLevel, + &item.Permanent, &item.TemporaryExpiresAtMS, &item.RevokeStatus, &item.Status, &item.AttemptCount, &item.FailureReason, &item.CreatedAtMS, &item.UpdatedAtMS, ) return item, err @@ -1311,7 +1540,8 @@ func levelTierSelectSQL() string { func levelRewardSelectSQL() string { return `SELECT app_code, reward_job_id, user_id, track, reward_source_type, reward_source_id, - resource_group_id, wallet_command_id, wallet_grant_id, status, attempt_count, + resource_group_id, wallet_command_id, wallet_grant_id, reward_origin, temporary_level_id, + grant_generation, reward_level, is_permanent, temporary_expires_at_ms, revoke_status, status, attempt_count, failure_reason, created_at_ms, updated_at_ms FROM growth_level_reward_jobs ` } diff --git a/services/activity-service/internal/storage/mysql/repository.go b/services/activity-service/internal/storage/mysql/repository.go index 51d15743..a8fc6fe9 100644 --- a/services/activity-service/internal/storage/mysql/repository.go +++ b/services/activity-service/internal/storage/mysql/repository.go @@ -84,6 +84,9 @@ func (r *Repository) Migrate(ctx context.Context) error { if err := r.ensureTaskRewardPolicyTables(ctx); err != nil { return err } + if err := r.ensureTemporaryGrowthLevelTables(ctx); err != nil { + return err + } return nil } diff --git a/services/activity-service/internal/storage/mysql/temporary_growth_level_migration.go b/services/activity-service/internal/storage/mysql/temporary_growth_level_migration.go new file mode 100644 index 00000000..be4af60e --- /dev/null +++ b/services/activity-service/internal/storage/mysql/temporary_growth_level_migration.go @@ -0,0 +1,88 @@ +package mysql + +import "context" + +// ensureTemporaryGrowthLevelTables keeps auto-migrated local/test databases compatible with the deploy migration. +// Production rollout still applies the explicit SQL before starting new binaries. +func (r *Repository) ensureTemporaryGrowthLevelTables(ctx context.Context) error { + additions := []struct { + column string + sql string + }{ + {"reward_origin", `ALTER TABLE growth_level_reward_jobs ADD COLUMN reward_origin VARCHAR(32) NOT NULL DEFAULT 'organic' AFTER wallet_grant_id`}, + {"temporary_level_id", `ALTER TABLE growth_level_reward_jobs ADD COLUMN temporary_level_id VARCHAR(96) NOT NULL DEFAULT '' AFTER reward_origin`}, + {"grant_generation", `ALTER TABLE growth_level_reward_jobs ADD COLUMN grant_generation INT NOT NULL DEFAULT 0 AFTER temporary_level_id`}, + {"reward_level", `ALTER TABLE growth_level_reward_jobs ADD COLUMN reward_level INT NOT NULL DEFAULT 0 AFTER grant_generation`}, + {"is_permanent", `ALTER TABLE growth_level_reward_jobs ADD COLUMN is_permanent TINYINT(1) NOT NULL DEFAULT 1 AFTER reward_level`}, + {"temporary_expires_at_ms", `ALTER TABLE growth_level_reward_jobs ADD COLUMN temporary_expires_at_ms BIGINT NOT NULL DEFAULT 0 AFTER is_permanent`}, + {"revoke_status", `ALTER TABLE growth_level_reward_jobs ADD COLUMN revoke_status VARCHAR(32) NOT NULL DEFAULT 'none' AFTER temporary_expires_at_ms`}, + } + for _, addition := range additions { + exists, err := r.columnExists(ctx, "growth_level_reward_jobs", addition.column) + if err != nil { + return err + } + if !exists { + if _, err := r.db.ExecContext(ctx, addition.sql); err != nil { + return err + } + } + } + oldIndex, err := r.indexExists(ctx, "growth_level_reward_jobs", "uk_growth_level_reward_once") + if err != nil { + return err + } + newIndex, err := r.indexExists(ctx, "growth_level_reward_jobs", "uk_growth_level_reward_generation") + if err != nil { + return err + } + if oldIndex { + if _, err := r.db.ExecContext(ctx, `ALTER TABLE growth_level_reward_jobs DROP INDEX uk_growth_level_reward_once`); err != nil { + return err + } + } + if !newIndex { + if _, err := r.db.ExecContext(ctx, `CREATE UNIQUE INDEX uk_growth_level_reward_generation ON growth_level_reward_jobs (app_code, user_id, track, reward_source_type, reward_source_id, reward_origin, grant_generation)`); err != nil { + return err + } + } + statements := []string{ + `CREATE TABLE IF NOT EXISTS growth_level_reward_wallet_grants ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu', reward_job_id VARCHAR(96) NOT NULL, + grant_kind VARCHAR(32) NOT NULL, wallet_grant_id VARCHAR(96) NOT NULL, + revoke_status VARCHAR(32) NOT NULL DEFAULT 'none', revoke_attempt_count INT NOT NULL DEFAULT 0, + revoke_next_retry_at_ms BIGINT NOT NULL DEFAULT 0, revoke_locked_by VARCHAR(128) NOT NULL DEFAULT '', + revoke_locked_until_ms BIGINT NOT NULL DEFAULT 0, revoke_failure_reason VARCHAR(255) NOT NULL DEFAULT '', + revoked_at_ms BIGINT NOT NULL DEFAULT 0, created_at_ms BIGINT NOT NULL, updated_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, reward_job_id, wallet_grant_id), + KEY idx_growth_reward_grant_revoke (app_code, revoke_status, revoke_next_retry_at_ms, created_at_ms) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, + `CREATE TABLE IF NOT EXISTS growth_temporary_level_commands ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu', command_id VARCHAR(128) NOT NULL, + request_hash VARCHAR(64) NOT NULL, user_id BIGINT NOT NULL, operator_admin_id BIGINT NOT NULL, + created_at_ms BIGINT NOT NULL, PRIMARY KEY (app_code, command_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, + `CREATE TABLE IF NOT EXISTS growth_temporary_levels ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu', temporary_level_id VARCHAR(96) NOT NULL, + command_id VARCHAR(128) NOT NULL, user_id BIGINT NOT NULL, track VARCHAR(32) NOT NULL, + target_level INT NOT NULL, target_required_value BIGINT NOT NULL, baseline_total_value BIGINT NOT NULL, + started_at_ms BIGINT NOT NULL, expires_at_ms BIGINT NOT NULL, status VARCHAR(32) NOT NULL, + generation INT NOT NULL, operator_admin_id BIGINT NOT NULL, reason VARCHAR(255) NOT NULL DEFAULT '', + final_level INT NOT NULL DEFAULT 0, activation_notice_status VARCHAR(32) NOT NULL DEFAULT 'pending', + expiry_notice_status VARCHAR(32) NOT NULL DEFAULT 'skipped', attempt_count INT NOT NULL DEFAULT 0, + next_retry_at_ms BIGINT NOT NULL DEFAULT 0, locked_by VARCHAR(128) NOT NULL DEFAULT '', + locked_until_ms BIGINT NOT NULL DEFAULT 0, failure_reason VARCHAR(255) NOT NULL DEFAULT '', + created_at_ms BIGINT NOT NULL, updated_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, temporary_level_id), + UNIQUE KEY uk_growth_temp_command_track (app_code, command_id, track), + KEY idx_growth_temp_user_track (app_code, user_id, track, status, expires_at_ms), + KEY idx_growth_temp_work (app_code, status, next_retry_at_ms, expires_at_ms, created_at_ms) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, + } + for _, statement := range statements { + if _, err := r.db.ExecContext(ctx, statement); err != nil { + return err + } + } + return nil +} diff --git a/services/activity-service/internal/storage/mysql/temporary_growth_level_repository.go b/services/activity-service/internal/storage/mysql/temporary_growth_level_repository.go new file mode 100644 index 00000000..ba8b48dd --- /dev/null +++ b/services/activity-service/internal/storage/mysql/temporary_growth_level_repository.go @@ -0,0 +1,761 @@ +package mysql + +import ( + "context" + "database/sql" + "fmt" + "math" + "strconv" + "strings" + "time" + + "hyapp/pkg/appcode" + "hyapp/pkg/idgen" + "hyapp/pkg/xerr" + domain "hyapp/services/activity-service/internal/domain/growth" +) + +const temporaryLevelDayMS = int64(24 * time.Hour / time.Millisecond) + +func (r *Repository) activeTemporaryLevelForUpdate(ctx context.Context, tx *sql.Tx, userID int64, track string, nowMS int64) (domain.TemporaryLevel, bool, error) { + row := tx.QueryRowContext(ctx, temporaryLevelSelectSQL()+` + WHERE app_code = ? AND user_id = ? AND track = ? AND status = 'active' + AND started_at_ms <= ? AND expires_at_ms > ? ORDER BY generation DESC LIMIT 1 FOR UPDATE`, + appcode.FromContext(ctx), userID, track, nowMS, nowMS) + var item domain.TemporaryLevel + err := row.Scan(&item.AppCode, &item.TemporaryLevelID, &item.CommandID, &item.UserID, &item.Track, + &item.TargetLevel, &item.TargetRequiredValue, &item.BaselineTotalValue, &item.StartedAtMS, &item.ExpiresAtMS, + &item.Status, &item.Generation, &item.OperatorAdminID, &item.Reason, &item.FinalLevel, + &item.ActivationNoticeStatus, &item.ExpiryNoticeStatus, &item.AttemptCount, &item.FailureReason, + &item.CreatedAtMS, &item.UpdatedAtMS) + if err == sql.ErrNoRows { + return domain.TemporaryLevel{}, false, nil + } + return item, err == nil, err +} + +func (r *Repository) activeTemporaryLevelForRead(ctx context.Context, userID int64, track string, nowMS int64) (domain.TemporaryLevel, bool, error) { + row := r.db.QueryRowContext(ctx, temporaryLevelSelectSQL()+` + WHERE app_code = ? AND user_id = ? AND track = ? AND status = 'active' + AND started_at_ms <= ? AND expires_at_ms > ? ORDER BY generation DESC LIMIT 1`, + appcode.FromContext(ctx), userID, track, nowMS, nowMS) + var item domain.TemporaryLevel + err := row.Scan(&item.AppCode, &item.TemporaryLevelID, &item.CommandID, &item.UserID, &item.Track, + &item.TargetLevel, &item.TargetRequiredValue, &item.BaselineTotalValue, &item.StartedAtMS, &item.ExpiresAtMS, + &item.Status, &item.Generation, &item.OperatorAdminID, &item.Reason, &item.FinalLevel, + &item.ActivationNoticeStatus, &item.ExpiryNoticeStatus, &item.AttemptCount, &item.FailureReason, + &item.CreatedAtMS, &item.UpdatedAtMS) + if err == sql.ErrNoRows { + return domain.TemporaryLevel{}, false, nil + } + return item, err == nil, err +} + +func levelFromGrowthRewardSourceID(sourceID string) (int32, bool) { + value := strings.TrimSpace(sourceID) + if !strings.HasPrefix(value, "level:") { + return 0, false + } + parsed, err := strconv.ParseInt(strings.TrimPrefix(value, "level:"), 10, 32) + if err != nil || parsed < 0 { + return 0, false + } + return int32(parsed), true +} + +// BatchGetUserLevelAdminProfiles 一次读取整批真实账户和有效 overlay。列表页不能按用户×轨道产生 N+1 查询; +// expires_at_ms 仍在 SQL 中按 [start,end) 判定,保证 cron 延迟时读路径也不会继续展示临时等级。 +func (r *Repository) BatchGetUserLevelAdminProfiles(ctx context.Context, userIDs []int64, nowMS int64) (domain.AdminLevelProfiles, error) { + if r == nil || r.db == nil { + return domain.AdminLevelProfiles{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + userIDs = uniquePositiveInt64s(userIDs) + if len(userIDs) == 0 { + return domain.AdminLevelProfiles{Profiles: []domain.AdminUserLevelProfile{}, ServerTimeMS: nowMS}, nil + } + profiles := make([]domain.AdminUserLevelProfile, len(userIDs)) + profileIndex := make(map[int64]int, len(userIDs)) + for index, userID := range userIDs { + profiles[index] = domain.AdminUserLevelProfile{UserID: userID, Tracks: []domain.AdminTrackProfile{ + {Track: domain.TrackWealth}, {Track: domain.TrackGame}, {Track: domain.TrackCharm}, + }, ServerTimeMS: nowMS} + profileIndex[userID] = index + } + trackIndex := map[string]int{domain.TrackWealth: 0, domain.TrackGame: 1, domain.TrackCharm: 2} + args := make([]any, 0, len(userIDs)+1) + args = append(args, appcode.FromContext(ctx)) + for _, userID := range userIDs { + args = append(args, userID) + } + rows, err := r.db.QueryContext(ctx, ` + SELECT user_id, track, total_value, current_level + FROM user_growth_level_accounts + WHERE app_code = ? AND user_id IN (`+placeholders(len(userIDs))+`) + AND track IN ('wealth','game','charm')`, args...) + if err != nil { + return domain.AdminLevelProfiles{}, err + } + for rows.Next() { + var userID int64 + var track string + var totalValue int64 + var level int32 + if err := rows.Scan(&userID, &track, &totalValue, &level); err != nil { + _ = rows.Close() + return domain.AdminLevelProfiles{}, err + } + profilePosition, profileFound := profileIndex[userID] + trackPosition, trackFound := trackIndex[track] + if !profileFound || !trackFound { + continue + } + item := &profiles[profilePosition].Tracks[trackPosition] + item.RealTotalValue = totalValue + item.RealLevel = level + item.DisplayValue = totalValue + item.DisplayLevel = level + } + if err := rows.Err(); err != nil { + _ = rows.Close() + return domain.AdminLevelProfiles{}, err + } + if err := rows.Close(); err != nil { + return domain.AdminLevelProfiles{}, err + } + + rulesByTrack := make(map[string][]domain.Rule, 2) + for _, track := range []string{domain.TrackWealth, domain.TrackCharm} { + rules, err := r.listActiveLevelRules(ctx, r.db, track) + if err != nil { + return domain.AdminLevelProfiles{}, err + } + rulesByTrack[track] = rules + } + overlayArgs := make([]any, 0, len(userIDs)+3) + overlayArgs = append(overlayArgs, appcode.FromContext(ctx), nowMS, nowMS) + for _, userID := range userIDs { + overlayArgs = append(overlayArgs, userID) + } + rows, err = r.db.QueryContext(ctx, ` + SELECT t.user_id, t.track, t.temporary_level_id, t.target_level, t.target_required_value, + t.started_at_ms, t.expires_at_ms, t.generation, COALESCE(SUM(e.value_delta), 0) + FROM growth_temporary_levels t + LEFT JOIN growth_level_value_events e + ON e.app_code = t.app_code AND e.user_id = t.user_id AND e.track = t.track + AND e.occurred_at_ms >= t.started_at_ms AND e.occurred_at_ms < t.expires_at_ms + WHERE t.app_code = ? AND t.status = 'active' AND t.started_at_ms <= ? AND t.expires_at_ms > ? + AND t.user_id IN (`+placeholders(len(userIDs))+`) + GROUP BY t.user_id, t.track, t.temporary_level_id, t.target_level, t.target_required_value, + t.started_at_ms, t.expires_at_ms, t.generation + ORDER BY t.user_id ASC, t.track ASC, t.generation DESC`, overlayArgs...) + if err != nil { + return domain.AdminLevelProfiles{}, err + } + seenOverlay := make(map[string]struct{}, len(userIDs)*2) + for rows.Next() { + var userID int64 + var track string + var temporaryID string + var targetLevel int32 + var targetRequiredValue int64 + var startedAtMS, expiresAtMS int64 + var generation int32 + var windowIncrement int64 + if err := rows.Scan(&userID, &track, &temporaryID, &targetLevel, &targetRequiredValue, &startedAtMS, &expiresAtMS, &generation, &windowIncrement); err != nil { + _ = rows.Close() + return domain.AdminLevelProfiles{}, err + } + key := fmt.Sprintf("%d:%s", userID, track) + if _, exists := seenOverlay[key]; exists { + continue + } + seenOverlay[key] = struct{}{} + profilePosition, profileFound := profileIndex[userID] + trackPosition, trackFound := trackIndex[track] + if !profileFound || !trackFound { + continue + } + item := &profiles[profilePosition].Tracks[trackPosition] + item.TemporaryLevelID = temporaryID + item.TemporaryTargetLevel = targetLevel + item.StartedAtMS = startedAtMS + item.ExpiresAtMS = expiresAtMS + item.DisplayValue = targetRequiredValue + windowIncrement + item.DisplayLevel = levelForValue(rulesByTrack[track], item.DisplayValue) + if item.DisplayLevel < targetLevel { + // 目标规则在下发时已校验并快照阈值;有效期内后续禁用配置不能让已生效 overlay 倒退。 + item.DisplayLevel = targetLevel + } + } + if err := rows.Err(); err != nil { + _ = rows.Close() + return domain.AdminLevelProfiles{}, err + } + if err := rows.Close(); err != nil { + return domain.AdminLevelProfiles{}, err + } + return domain.AdminLevelProfiles{Profiles: profiles, ServerTimeMS: nowMS}, nil +} + +func (r *Repository) adminTrackProfile(ctx context.Context, q queryer, userID int64, track string, nowMS int64) (domain.AdminTrackProfile, error) { + item := domain.AdminTrackProfile{Track: track} + row := q.QueryRowContext(ctx, ` + SELECT total_value, current_level + FROM user_growth_level_accounts + WHERE app_code = ? AND user_id = ? AND track = ?`, appcode.FromContext(ctx), userID, track) + if err := row.Scan(&item.RealTotalValue, &item.RealLevel); err != nil && err != sql.ErrNoRows { + return domain.AdminTrackProfile{}, err + } + item.DisplayLevel = item.RealLevel + item.DisplayValue = item.RealTotalValue + var targetRequired int64 + err := q.QueryRowContext(ctx, ` + SELECT temporary_level_id, target_level, target_required_value, started_at_ms, expires_at_ms + FROM growth_temporary_levels + WHERE app_code = ? AND user_id = ? AND track = ? AND status = 'active' + AND started_at_ms <= ? AND expires_at_ms > ? + ORDER BY generation DESC LIMIT 1`, + appcode.FromContext(ctx), userID, track, nowMS, nowMS, + ).Scan(&item.TemporaryLevelID, &item.TemporaryTargetLevel, &targetRequired, &item.StartedAtMS, &item.ExpiresAtMS) + if err == sql.ErrNoRows { + return item, nil + } + if err != nil { + return domain.AdminTrackProfile{}, err + } + increment, err := r.temporaryWindowValue(ctx, q, userID, track, item.StartedAtMS, item.ExpiresAtMS) + if err != nil { + return domain.AdminTrackProfile{}, err + } + rules, err := r.listActiveLevelRules(ctx, q, track) + if err != nil { + return domain.AdminTrackProfile{}, err + } + item.DisplayValue = targetRequired + increment + item.DisplayLevel = levelForValue(rules, item.DisplayValue) + if item.DisplayLevel < item.TemporaryTargetLevel { + item.DisplayLevel = item.TemporaryTargetLevel + } + return item, nil +} + +func (r *Repository) temporaryWindowValue(ctx context.Context, q queryer, userID int64, track string, startMS int64, endMS int64) (int64, error) { + var value int64 + // occurred_at_ms, not processing time, defines the experience window. Late events outside the window cannot leak into overlay progress. + err := q.QueryRowContext(ctx, ` + SELECT COALESCE(SUM(value_delta), 0) + FROM growth_level_value_events + WHERE app_code = ? AND user_id = ? AND track = ? AND occurred_at_ms >= ? AND occurred_at_ms < ?`, + appcode.FromContext(ctx), userID, track, startMS, endMS, + ).Scan(&value) + return value, err +} + +// AdjustTemporaryUserLevels locks both requested tracks in deterministic order and commits command idempotency, +// supersession, overlay rows and temporary reward jobs as one transaction. +func (r *Repository) AdjustTemporaryUserLevels(ctx context.Context, command domain.AdjustTemporaryLevelsCommand, nowMS int64) (domain.AdminUserLevelProfile, error) { + if r == nil || r.db == nil { + return domain.AdminUserLevelProfile{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return domain.AdminUserLevelProfile{}, err + } + defer func() { _ = tx.Rollback() }() + + result, err := tx.ExecContext(ctx, ` + INSERT IGNORE INTO growth_temporary_level_commands + (app_code, command_id, request_hash, user_id, operator_admin_id, created_at_ms) + VALUES (?, ?, ?, ?, ?, ?)`, appcode.FromContext(ctx), command.CommandID, command.RequestHash, command.UserID, command.OperatorAdminID, nowMS) + if err != nil { + return domain.AdminUserLevelProfile{}, err + } + inserted, err := result.RowsAffected() + if err != nil { + return domain.AdminUserLevelProfile{}, err + } + if inserted == 0 { + var requestHash string + var userID int64 + if err := tx.QueryRowContext(ctx, `SELECT request_hash, user_id FROM growth_temporary_level_commands WHERE app_code = ? AND command_id = ? FOR UPDATE`, appcode.FromContext(ctx), command.CommandID).Scan(&requestHash, &userID); err != nil { + return domain.AdminUserLevelProfile{}, err + } + if requestHash != command.RequestHash || userID != command.UserID { + return domain.AdminUserLevelProfile{}, xerr.New(xerr.IdempotencyConflict, "temporary level command payload conflicts with existing command") + } + if err := tx.Commit(); err != nil { + return domain.AdminUserLevelProfile{}, err + } + return r.singleAdminLevelProfile(ctx, command.UserID, nowMS) + } + + for _, adjustment := range command.Adjustments { + account, err := r.ensureLevelAccountForUpdate(ctx, tx, command.UserID, adjustment.Track, nowMS) + if err != nil { + return domain.AdminUserLevelProfile{}, err + } + rules, err := r.listActiveLevelRules(ctx, tx, adjustment.Track) + if err != nil { + return domain.AdminUserLevelProfile{}, err + } + targetRequired, found := requiredValueForLevel(rules, adjustment.Level) + if !found { + return domain.AdminUserLevelProfile{}, xerr.New(xerr.NotFound, "active level rule not found") + } + if adjustment.Level <= account.CurrentLevel { + return domain.AdminUserLevelProfile{}, xerr.New(xerr.Conflict, "temporary target level must be higher than real level") + } + // 新调整只能覆盖仍在有效期内的 overlay;先把已越过 end 边界但 cron 尚未处理的旧事实按正常到期语义物化。 + if err := r.materializeExpiredTemporaryLevelsForUpdate(ctx, tx, command.UserID, adjustment.Track, rules, nowMS); err != nil { + return domain.AdminUserLevelProfile{}, err + } + generation, err := r.nextTemporaryGeneration(ctx, tx, command.UserID, adjustment.Track) + if err != nil { + return domain.AdminUserLevelProfile{}, err + } + // Superseded records never emit an expiry notice. Common rewards are moved to the new generation below; + // only rewards outside the new target remain associated with the old record and enter revoke processing. + oldIDs, err := r.supersedeTemporaryLevels(ctx, tx, command.UserID, adjustment.Track, nowMS) + if err != nil { + return domain.AdminUserLevelProfile{}, err + } + temporaryID := idgen.New("tmplevel") + durationMS := int64(adjustment.DurationDays) * temporaryLevelDayMS + if durationMS <= 0 || durationMS/temporaryLevelDayMS != int64(adjustment.DurationDays) || nowMS > math.MaxInt64-durationMS { + return domain.AdminUserLevelProfile{}, xerr.New(xerr.InvalidArgument, "temporary level duration exceeds epoch millisecond range") + } + expiresAtMS := nowMS + durationMS + _, err = tx.ExecContext(ctx, ` + INSERT INTO growth_temporary_levels ( + app_code, temporary_level_id, command_id, user_id, track, target_level, target_required_value, + baseline_total_value, started_at_ms, expires_at_ms, status, generation, operator_admin_id, reason, + activation_notice_status, expiry_notice_status, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'active', ?, ?, ?, 'pending', 'skipped', ?, ?)`, + appcode.FromContext(ctx), temporaryID, command.CommandID, command.UserID, adjustment.Track, + adjustment.Level, targetRequired, account.TotalValue, nowMS, expiresAtMS, generation, + command.OperatorAdminID, command.Reason, nowMS, nowMS, + ) + if err != nil { + return domain.AdminUserLevelProfile{}, err + } + for _, oldID := range oldIDs { + if err := r.carryTemporaryRewardsToGeneration(ctx, tx, oldID, temporaryID, generation, adjustment.Level, expiresAtMS, nowMS); err != nil { + return domain.AdminUserLevelProfile{}, err + } + if err := r.prepareTemporaryRewardsForRevocation(ctx, tx, oldID, 0, nowMS); err != nil { + return domain.AdminUserLevelProfile{}, err + } + } + tiers, err := r.listActiveLevelTiers(ctx, tx, adjustment.Track) + if err != nil { + return domain.AdminUserLevelProfile{}, err + } + if _, err := r.createTemporaryRewardJobs(ctx, tx, command.UserID, adjustment.Track, adjustment.Level, temporaryID, generation, expiresAtMS, rules, tiers, nowMS); err != nil { + return domain.AdminUserLevelProfile{}, err + } + } + if err := tx.Commit(); err != nil { + return domain.AdminUserLevelProfile{}, err + } + return r.singleAdminLevelProfile(ctx, command.UserID, nowMS) +} + +// carryTemporaryRewardsToGeneration transfers rewards that remain covered by the replacement target instead of +// revoking and regranting them. This makes one source/level have exactly one live temporary generation, so a later +// organic promotion cannot accidentally preserve both the old and the new wallet grants. +func (r *Repository) carryTemporaryRewardsToGeneration(ctx context.Context, tx *sql.Tx, oldTemporaryID string, newTemporaryID string, generation int32, targetLevel int32, expiresAtMS int64, nowMS int64) error { + _, err := tx.ExecContext(ctx, ` + UPDATE growth_level_reward_jobs + SET temporary_level_id = ?, grant_generation = ?, temporary_expires_at_ms = ?, updated_at_ms = ? + WHERE app_code = ? AND temporary_level_id = ? AND reward_origin = 'temporary' + AND is_permanent = 0 AND reward_level <= ? + AND status IN ('pending','failed','running','granted') + AND revoke_status = 'none'`, + newTemporaryID, generation, expiresAtMS, nowMS, + appcode.FromContext(ctx), oldTemporaryID, targetLevel, + ) + return err +} + +func (r *Repository) singleAdminLevelProfile(ctx context.Context, userID int64, nowMS int64) (domain.AdminUserLevelProfile, error) { + profiles, err := r.BatchGetUserLevelAdminProfiles(ctx, []int64{userID}, nowMS) + if err != nil { + return domain.AdminUserLevelProfile{}, err + } + if len(profiles.Profiles) == 0 { + return domain.AdminUserLevelProfile{UserID: userID, ServerTimeMS: nowMS}, nil + } + return profiles.Profiles[0], nil +} + +func (r *Repository) nextTemporaryGeneration(ctx context.Context, tx *sql.Tx, userID int64, track string) (int32, error) { + var generation int32 + err := tx.QueryRowContext(ctx, `SELECT COALESCE(MAX(generation), 0) + 1 FROM growth_temporary_levels WHERE app_code = ? AND user_id = ? AND track = ?`, appcode.FromContext(ctx), userID, track).Scan(&generation) + return generation, err +} + +func (r *Repository) supersedeTemporaryLevels(ctx context.Context, tx *sql.Tx, userID int64, track string, nowMS int64) ([]string, error) { + rows, err := tx.QueryContext(ctx, `SELECT temporary_level_id FROM growth_temporary_levels WHERE app_code = ? AND user_id = ? AND track = ? AND status = 'active' AND expires_at_ms > ? FOR UPDATE`, appcode.FromContext(ctx), userID, track, nowMS) + if err != nil { + return nil, err + } + var ids []string + for rows.Next() { + var id string + if err := rows.Scan(&id); err != nil { + _ = rows.Close() + return nil, err + } + ids = append(ids, id) + } + if err := rows.Close(); err != nil { + return nil, err + } + if len(ids) > 0 { + _, err = tx.ExecContext(ctx, `UPDATE growth_temporary_levels SET status = 'superseded', expiry_notice_status = 'skipped', locked_by = '', locked_until_ms = 0, updated_at_ms = ? WHERE app_code = ? AND user_id = ? AND track = ? AND status = 'active' AND expires_at_ms > ?`, nowMS, appcode.FromContext(ctx), userID, track, nowMS) + } + return ids, err +} + +func (r *Repository) materializeExpiredTemporaryLevelsForUpdate(ctx context.Context, tx *sql.Tx, userID int64, track string, rules []domain.Rule, nowMS int64) error { + rows, err := tx.QueryContext(ctx, temporaryLevelSelectSQL()+` + WHERE app_code = ? AND user_id = ? AND track = ? AND status = 'active' AND expires_at_ms <= ? + ORDER BY generation ASC FOR UPDATE`, appcode.FromContext(ctx), userID, track, nowMS) + if err != nil { + return err + } + items, err := scanTemporaryLevels(rows) + _ = rows.Close() + if err != nil { + return err + } + for _, item := range items { + increment, err := r.temporaryWindowValue(ctx, tx, item.UserID, item.Track, item.StartedAtMS, item.ExpiresAtMS) + if err != nil { + return err + } + item.FinalLevel = levelForValue(rules, item.BaselineTotalValue+increment) + if item.ActivationNoticeStatus == domain.NoticeStatusPending || item.ActivationNoticeStatus == domain.NoticeStatusFailed { + item.ActivationNoticeStatus = domain.NoticeStatusSkipped + } + if item.FinalLevel < item.TargetLevel { + item.ExpiryNoticeStatus = domain.NoticeStatusPending + } else { + item.ExpiryNoticeStatus = domain.NoticeStatusSkipped + } + if err := r.prepareTemporaryRewardsForRevocation(ctx, tx, item.TemporaryLevelID, item.FinalLevel, nowMS); err != nil { + return err + } + if _, err := tx.ExecContext(ctx, ` + UPDATE growth_temporary_levels + SET status = 'expired', final_level = ?, activation_notice_status = ?, expiry_notice_status = ?, + locked_by = '', locked_until_ms = 0, next_retry_at_ms = 0, updated_at_ms = ? + WHERE app_code = ? AND temporary_level_id = ? AND status = 'active'`, + item.FinalLevel, item.ActivationNoticeStatus, item.ExpiryNoticeStatus, nowMS, + appcode.FromContext(ctx), item.TemporaryLevelID, + ); err != nil { + return err + } + } + return nil +} + +func (r *Repository) createTemporaryRewardJobs(ctx context.Context, tx *sql.Tx, userID int64, track string, targetLevel int32, temporaryID string, generation int32, expiresAtMS int64, rules []domain.Rule, tiers []domain.Tier, nowMS int64) (int64, error) { + var created int64 + for _, rule := range rules { + if rule.Level < 1 || rule.Level > targetLevel || (rule.RewardResourceGroupID <= 0 && avatarFrameResourceIDFromDisplayConfig(rule.DisplayConfigJSON) <= 0 && shortBadgeResourceIDFromDisplayConfig(rule.DisplayConfigJSON) <= 0) { + continue + } + changed, err := r.insertTemporaryRewardJob(ctx, tx, userID, track, domain.RewardSourceLevel, fmt.Sprintf("level:%d", rule.Level), rule.Level, rule.RewardResourceGroupID, temporaryID, generation, expiresAtMS, nowMS) + if err != nil { + return 0, err + } + if changed { + created++ + } + } + for _, tier := range tiers { + if tier.MinLevel < 1 || tier.MinLevel > targetLevel || tier.RewardResourceGroupID <= 0 { + continue + } + changed, err := r.insertTemporaryRewardJob(ctx, tx, userID, track, domain.RewardSourceTier, fmt.Sprintf("tier:%d", tier.TierID), tier.MinLevel, tier.RewardResourceGroupID, temporaryID, generation, expiresAtMS, nowMS) + if err != nil { + return 0, err + } + if changed { + created++ + } + } + return created, nil +} + +func (r *Repository) insertTemporaryRewardJob(ctx context.Context, tx *sql.Tx, userID int64, track string, sourceType string, sourceID string, rewardLevel int32, resourceGroupID int64, temporaryID string, generation int32, expiresAtMS int64, nowMS int64) (bool, error) { + // Any organic/permanent row means this user already owns the reward; temporary generations must not duplicate it. + var permanentCount int + if err := tx.QueryRowContext(ctx, `SELECT COUNT(*) FROM growth_level_reward_jobs WHERE app_code = ? AND user_id = ? AND track = ? AND reward_source_type = ? AND reward_source_id = ? AND is_permanent = 1 AND status <> 'canceled'`, appcode.FromContext(ctx), userID, track, sourceType, sourceID).Scan(&permanentCount); err != nil { + return false, err + } + if permanentCount > 0 { + return false, nil + } + rewardJobID := idgen.New("greward") + result, err := tx.ExecContext(ctx, ` + INSERT IGNORE INTO growth_level_reward_jobs ( + app_code, reward_job_id, user_id, track, reward_source_type, reward_source_id, resource_group_id, + wallet_command_id, reward_origin, temporary_level_id, grant_generation, reward_level, + is_permanent, temporary_expires_at_ms, revoke_status, status, next_retry_at_ms, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'temporary', ?, ?, ?, 0, ?, 'none', 'pending', 0, ?, ?)`, + appcode.FromContext(ctx), rewardJobID, userID, track, sourceType, sourceID, resourceGroupID, + "growth_level_reward:"+rewardJobID, temporaryID, generation, rewardLevel, expiresAtMS, nowMS, nowMS) + if err != nil { + return false, err + } + affected, err := result.RowsAffected() + return affected > 0, err +} + +// ClaimTemporaryLevelWork first materializes expiry facts in the same transaction, then leases only message work. +// Reward revocations are leased from their own child rows because one reward job may contain three wallet grants. +func (r *Repository) ClaimTemporaryLevelWork(ctx context.Context, workerID string, nowMS int64, lockTTL time.Duration, batchSize int) ([]domain.TemporaryLevelWork, error) { + if r == nil || r.db == nil { + return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return nil, err + } + defer func() { _ = tx.Rollback() }() + rows, err := tx.QueryContext(ctx, temporaryLevelSelectSQL()+` + WHERE app_code = ? AND next_retry_at_ms <= ? AND (locked_until_ms = 0 OR locked_until_ms <= ?) + AND ((status = 'active' AND expires_at_ms <= ?) + OR (status = 'active' AND expires_at_ms > ? AND activation_notice_status IN ('pending','failed')) + OR (status = 'expired' AND expiry_notice_status IN ('pending','failed'))) + ORDER BY expires_at_ms ASC, created_at_ms ASC LIMIT ? FOR UPDATE SKIP LOCKED`, + appcode.FromContext(ctx), nowMS, nowMS, nowMS, nowMS, batchSize) + if err != nil { + return nil, err + } + levels, err := scanTemporaryLevels(rows) + _ = rows.Close() + if err != nil { + return nil, err + } + works := make([]domain.TemporaryLevelWork, 0, len(levels)) + lockUntil := nowMS + lockTTL.Milliseconds() + for _, item := range levels { + if item.Status == domain.TemporaryLevelStatusActive && item.ExpiresAtMS <= nowMS { + increment, err := r.temporaryWindowValue(ctx, tx, item.UserID, item.Track, item.StartedAtMS, item.ExpiresAtMS) + if err != nil { + return nil, err + } + rules, err := r.listActiveLevelRules(ctx, tx, item.Track) + if err != nil { + return nil, err + } + item.FinalLevel = levelForValue(rules, item.BaselineTotalValue+increment) + item.Status = domain.TemporaryLevelStatusExpired + if item.ActivationNoticeStatus == domain.NoticeStatusPending || item.ActivationNoticeStatus == domain.NoticeStatusFailed { + // A stale activation message after expiry is misleading; expiry truth is still sent when the user fell below target. + item.ActivationNoticeStatus = domain.NoticeStatusSkipped + } + if item.FinalLevel < item.TargetLevel { + item.ExpiryNoticeStatus = domain.NoticeStatusPending + } else { + item.ExpiryNoticeStatus = domain.NoticeStatusSkipped + } + if err := r.prepareTemporaryRewardsForRevocation(ctx, tx, item.TemporaryLevelID, item.FinalLevel, nowMS); err != nil { + return nil, err + } + _, err = tx.ExecContext(ctx, ` + UPDATE growth_temporary_levels + SET status = 'expired', final_level = ?, activation_notice_status = ?, expiry_notice_status = ?, updated_at_ms = ? + WHERE app_code = ? AND temporary_level_id = ?`, item.FinalLevel, item.ActivationNoticeStatus, item.ExpiryNoticeStatus, nowMS, appcode.FromContext(ctx), item.TemporaryLevelID) + if err != nil { + return nil, err + } + } + work := domain.TemporaryLevelWork{TemporaryLevel: item} + work.SendActivationNotice = item.Status == domain.TemporaryLevelStatusActive && item.ExpiresAtMS > nowMS && (item.ActivationNoticeStatus == domain.NoticeStatusPending || item.ActivationNoticeStatus == domain.NoticeStatusFailed) + work.SendExpiryNotice = item.Status == domain.TemporaryLevelStatusExpired && (item.ExpiryNoticeStatus == domain.NoticeStatusPending || item.ExpiryNoticeStatus == domain.NoticeStatusFailed) + _, err := tx.ExecContext(ctx, `UPDATE growth_temporary_levels SET locked_by = ?, locked_until_ms = ?, attempt_count = attempt_count + 1, updated_at_ms = ? WHERE app_code = ? AND temporary_level_id = ?`, workerID, lockUntil, nowMS, appcode.FromContext(ctx), item.TemporaryLevelID) + if err != nil { + return nil, err + } + works = append(works, work) + } + if err := tx.Commit(); err != nil { + return nil, err + } + return works, nil +} + +// prepareTemporaryRewardsForRevocation promotes rewards earned by the real final level and schedules every wallet +// grant above it for revoke. Ungranted jobs above the final level are canceled, preventing a late worker grant. +func (r *Repository) prepareTemporaryRewardsForRevocation(ctx context.Context, tx *sql.Tx, temporaryID string, finalLevel int32, nowMS int64) error { + _, err := tx.ExecContext(ctx, ` + UPDATE growth_level_reward_jobs + SET is_permanent = 1, revoke_status = 'skipped', updated_at_ms = ? + WHERE app_code = ? AND temporary_level_id = ? AND is_permanent = 0 AND reward_level <= ?`, + nowMS, appcode.FromContext(ctx), temporaryID, finalLevel) + if err != nil { + return err + } + _, err = tx.ExecContext(ctx, ` + UPDATE growth_level_reward_jobs + SET status = 'canceled', + revoke_status = CASE + WHEN EXISTS (SELECT 1 FROM growth_level_reward_wallet_grants g WHERE g.app_code = growth_level_reward_jobs.app_code AND g.reward_job_id = growth_level_reward_jobs.reward_job_id) + THEN 'pending' ELSE 'skipped' END, + locked_by = '', locked_until_ms = 0, updated_at_ms = ? + WHERE app_code = ? AND temporary_level_id = ? AND is_permanent = 0 AND reward_level > ? AND status IN ('pending','failed')`, + nowMS, appcode.FromContext(ctx), temporaryID, finalLevel) + if err != nil { + return err + } + _, err = tx.ExecContext(ctx, ` + UPDATE growth_level_reward_jobs j + SET revoke_status = CASE + WHEN EXISTS (SELECT 1 FROM growth_level_reward_wallet_grants g WHERE g.app_code = j.app_code AND g.reward_job_id = j.reward_job_id) + THEN 'pending' ELSE 'skipped' END, + updated_at_ms = ? + WHERE j.app_code = ? AND j.temporary_level_id = ? AND j.is_permanent = 0 AND j.reward_level > ? AND j.status = 'granted'`, + nowMS, appcode.FromContext(ctx), temporaryID, finalLevel) + if err != nil { + return err + } + _, err = tx.ExecContext(ctx, ` + UPDATE growth_level_reward_wallet_grants g + JOIN growth_level_reward_jobs j ON j.app_code = g.app_code AND j.reward_job_id = g.reward_job_id + SET g.revoke_status = 'pending', g.revoke_next_retry_at_ms = 0, g.updated_at_ms = ? + WHERE j.app_code = ? AND j.temporary_level_id = ? AND j.is_permanent = 0 AND j.reward_level > ? + AND j.status IN ('granted','canceled') AND g.revoke_status IN ('none','failed')`, + nowMS, appcode.FromContext(ctx), temporaryID, finalLevel) + return err +} + +func (r *Repository) MarkTemporaryLevelNotices(ctx context.Context, temporaryLevelID string, activationStatus string, expiryStatus string, failureReason string, nextRetryAtMS int64, nowMS int64) error { + if r == nil || r.db == nil { + return xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + sets := []string{"locked_by = ''", "locked_until_ms = 0", "failure_reason = ?", "next_retry_at_ms = ?", "updated_at_ms = ?"} + args := []any{truncateGrowthFailure(failureReason), nextRetryAtMS, nowMS} + if activationStatus != "" { + sets = append(sets, "activation_notice_status = ?") + args = append(args, activationStatus) + } + if expiryStatus != "" { + sets = append(sets, "expiry_notice_status = ?") + args = append(args, expiryStatus) + } + args = append(args, appcode.FromContext(ctx), temporaryLevelID) + _, err := r.db.ExecContext(ctx, `UPDATE growth_temporary_levels SET `+strings.Join(sets, ", ")+` WHERE app_code = ? AND temporary_level_id = ?`, args...) + return err +} + +func (r *Repository) ClaimLevelRewardRevocations(ctx context.Context, workerID string, nowMS int64, lockTTL time.Duration, batchSize int) ([]domain.RewardRevocation, error) { + if r == nil || r.db == nil { + return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return nil, err + } + defer func() { _ = tx.Rollback() }() + rows, err := tx.QueryContext(ctx, ` + SELECT g.reward_job_id, g.wallet_grant_id, j.temporary_level_id, j.user_id, j.track, g.revoke_attempt_count + FROM growth_level_reward_wallet_grants g + JOIN growth_level_reward_jobs j ON j.app_code = g.app_code AND j.reward_job_id = g.reward_job_id + WHERE g.app_code = ? AND g.revoke_status IN ('pending','failed','running') AND g.revoke_next_retry_at_ms <= ? + AND (g.revoke_locked_until_ms = 0 OR g.revoke_locked_until_ms <= ?) + ORDER BY g.created_at_ms ASC LIMIT ? FOR UPDATE SKIP LOCKED`, appcode.FromContext(ctx), nowMS, nowMS, batchSize) + if err != nil { + return nil, err + } + items := make([]domain.RewardRevocation, 0) + for rows.Next() { + var item domain.RewardRevocation + if err := rows.Scan(&item.RewardJobID, &item.WalletGrantID, &item.TemporaryLevelID, &item.UserID, &item.Track, &item.AttemptCount); err != nil { + _ = rows.Close() + return nil, err + } + items = append(items, item) + } + _ = rows.Close() + lockUntil := nowMS + lockTTL.Milliseconds() + for _, item := range items { + _, err := tx.ExecContext(ctx, `UPDATE growth_level_reward_wallet_grants SET revoke_status = 'running', revoke_attempt_count = revoke_attempt_count + 1, revoke_locked_by = ?, revoke_locked_until_ms = ?, updated_at_ms = ? WHERE app_code = ? AND reward_job_id = ? AND wallet_grant_id = ?`, workerID, lockUntil, nowMS, appcode.FromContext(ctx), item.RewardJobID, item.WalletGrantID) + if err != nil { + return nil, err + } + } + if err := tx.Commit(); err != nil { + return nil, err + } + return items, nil +} + +func (r *Repository) MarkLevelRewardRevoked(ctx context.Context, rewardJobID string, walletGrantID string, nowMS int64) error { + if r == nil || r.db == nil { + return xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return err + } + defer func() { _ = tx.Rollback() }() + _, err = tx.ExecContext(ctx, `UPDATE growth_level_reward_wallet_grants SET revoke_status = 'revoked', revoked_at_ms = ?, revoke_locked_by = '', revoke_locked_until_ms = 0, revoke_failure_reason = '', updated_at_ms = ? WHERE app_code = ? AND reward_job_id = ? AND wallet_grant_id = ?`, nowMS, nowMS, appcode.FromContext(ctx), rewardJobID, walletGrantID) + if err != nil { + return err + } + var remaining int + if err := tx.QueryRowContext(ctx, `SELECT COUNT(*) FROM growth_level_reward_wallet_grants WHERE app_code = ? AND reward_job_id = ? AND revoke_status NOT IN ('revoked','skipped')`, appcode.FromContext(ctx), rewardJobID).Scan(&remaining); err != nil { + return err + } + if remaining == 0 { + if _, err := tx.ExecContext(ctx, `UPDATE growth_level_reward_jobs SET revoke_status = 'revoked', updated_at_ms = ? WHERE app_code = ? AND reward_job_id = ?`, nowMS, appcode.FromContext(ctx), rewardJobID); err != nil { + return err + } + } + return tx.Commit() +} + +func (r *Repository) MarkLevelRewardRevokeFailed(ctx context.Context, rewardJobID string, walletGrantID string, failureReason string, nextRetryAtMS int64, nowMS int64) error { + if r == nil || r.db == nil { + return xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return err + } + defer func() { _ = tx.Rollback() }() + if _, err := tx.ExecContext(ctx, `UPDATE growth_level_reward_wallet_grants SET revoke_status = 'failed', revoke_next_retry_at_ms = ?, revoke_locked_by = '', revoke_locked_until_ms = 0, revoke_failure_reason = ?, updated_at_ms = ? WHERE app_code = ? AND reward_job_id = ? AND wallet_grant_id = ?`, nextRetryAtMS, truncateGrowthFailure(failureReason), nowMS, appcode.FromContext(ctx), rewardJobID, walletGrantID); err != nil { + return err + } + if _, err := tx.ExecContext(ctx, `UPDATE growth_level_reward_jobs SET revoke_status = 'failed', updated_at_ms = ? WHERE app_code = ? AND reward_job_id = ? AND revoke_status <> 'revoked'`, nowMS, appcode.FromContext(ctx), rewardJobID); err != nil { + return err + } + return tx.Commit() +} + +func temporaryLevelSelectSQL() string { + return `SELECT app_code, temporary_level_id, command_id, user_id, track, target_level, target_required_value, + baseline_total_value, started_at_ms, expires_at_ms, status, generation, operator_admin_id, reason, + final_level, activation_notice_status, expiry_notice_status, attempt_count, failure_reason, + created_at_ms, updated_at_ms FROM growth_temporary_levels ` +} + +func scanTemporaryLevels(rows *sql.Rows) ([]domain.TemporaryLevel, error) { + items := make([]domain.TemporaryLevel, 0) + for rows.Next() { + var item domain.TemporaryLevel + if err := rows.Scan(&item.AppCode, &item.TemporaryLevelID, &item.CommandID, &item.UserID, &item.Track, + &item.TargetLevel, &item.TargetRequiredValue, &item.BaselineTotalValue, &item.StartedAtMS, &item.ExpiresAtMS, + &item.Status, &item.Generation, &item.OperatorAdminID, &item.Reason, &item.FinalLevel, + &item.ActivationNoticeStatus, &item.ExpiryNoticeStatus, &item.AttemptCount, &item.FailureReason, + &item.CreatedAtMS, &item.UpdatedAtMS); err != nil { + return nil, err + } + items = append(items, item) + } + return items, rows.Err() +} diff --git a/services/activity-service/internal/transport/grpc/cron_server.go b/services/activity-service/internal/transport/grpc/cron_server.go index d21c8fc4..1f6965dd 100644 --- a/services/activity-service/internal/transport/grpc/cron_server.go +++ b/services/activity-service/internal/transport/grpc/cron_server.go @@ -85,6 +85,19 @@ func (s *CronServer) ProcessLevelRewardBatch(ctx context.Context, req *activityv }, nil } +// ProcessTemporaryLevelBatch advances expired overlays, sends owner-created inbox notices and revokes temporary grants. +func (s *CronServer) ProcessTemporaryLevelBatch(ctx context.Context, req *activityv1.CronBatchRequest) (*activityv1.CronBatchResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + if s.growth == nil { + return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "growth service is not configured")) + } + claimed, processed, success, failure, hasMore, err := s.growth.ProcessTemporaryLevelBatch(ctx, req.GetWorkerId(), int(req.GetBatchSize()), durationFromMillis(req.GetLockTtlMs())) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.CronBatchResponse{ClaimedCount: claimed, ProcessedCount: processed, SuccessCount: success, FailureCount: failure, HasMore: hasMore}, nil +} + // ProcessAchievementRewardBatch claims and grants pending achievement badge/resource rewards. func (s *CronServer) ProcessAchievementRewardBatch(ctx context.Context, req *activityv1.CronBatchRequest) (*activityv1.CronBatchResponse, error) { ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) diff --git a/services/activity-service/internal/transport/grpc/growth_server.go b/services/activity-service/internal/transport/grpc/growth_server.go index 6b2baa59..a5e890fb 100644 --- a/services/activity-service/internal/transport/grpc/growth_server.go +++ b/services/activity-service/internal/transport/grpc/growth_server.go @@ -199,6 +199,35 @@ func (s *AdminGrowthLevelServer) ListLevelConfig(ctx context.Context, req *activ return resp, nil } +func (s *AdminGrowthLevelServer) BatchGetUserLevelAdminProfiles(ctx context.Context, req *activityv1.BatchGetUserLevelAdminProfilesRequest) (*activityv1.BatchGetUserLevelAdminProfilesResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + profiles, err := s.svc.BatchGetUserLevelAdminProfiles(ctx, req.GetUserIds()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + resp := &activityv1.BatchGetUserLevelAdminProfilesResponse{Profiles: make([]*activityv1.AdminUserLevelProfile, 0, len(profiles.Profiles)), ServerTimeMs: profiles.ServerTimeMS} + for _, profile := range profiles.Profiles { + resp.Profiles = append(resp.Profiles, adminUserLevelProfileToProto(profile)) + } + return resp, nil +} + +func (s *AdminGrowthLevelServer) AdjustTemporaryUserLevels(ctx context.Context, req *activityv1.AdjustTemporaryUserLevelsRequest) (*activityv1.AdjustTemporaryUserLevelsResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + adjustments := make([]domain.TemporaryLevelAdjustment, 0, len(req.GetAdjustments())) + for _, item := range req.GetAdjustments() { + adjustments = append(adjustments, domain.TemporaryLevelAdjustment{Track: item.GetTrack(), Level: item.GetLevel(), DurationDays: item.GetDurationDays()}) + } + profile, err := s.svc.AdjustTemporaryUserLevels(ctx, domain.AdjustTemporaryLevelsCommand{ + CommandID: req.GetCommandId(), UserID: req.GetUserId(), Adjustments: adjustments, + OperatorAdminID: req.GetOperatorAdminId(), Reason: req.GetReason(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.AdjustTemporaryUserLevelsResponse{Profile: adminUserLevelProfileToProto(profile), ServerTimeMs: profile.ServerTimeMS}, nil +} + func (s *AdminGrowthLevelServer) UpsertLevelTrack(ctx context.Context, req *activityv1.UpsertLevelTrackRequest) (*activityv1.UpsertLevelTrackResponse, error) { ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) item, created, err := s.svc.UpsertLevelTrack(ctx, domain.TrackCommand{ @@ -343,19 +372,26 @@ func levelDisplayTrackProfileToProto(item domain.LevelDisplayTrackProfile) *acti func levelRewardToProto(item domain.RewardJob) *activityv1.LevelRewardJob { return &activityv1.LevelRewardJob{ - RewardJobId: item.RewardJobID, - UserId: item.UserID, - Track: item.Track, - RewardSourceType: item.RewardSourceType, - RewardSourceId: item.RewardSourceID, - ResourceGroupId: item.ResourceGroupID, - WalletCommandId: item.WalletCommandID, - WalletGrantId: item.WalletGrantID, - Status: item.Status, - AttemptCount: item.AttemptCount, - FailureReason: item.FailureReason, - CreatedAtMs: item.CreatedAtMS, - UpdatedAtMs: item.UpdatedAtMS, + RewardJobId: item.RewardJobID, + UserId: item.UserID, + Track: item.Track, + RewardSourceType: item.RewardSourceType, + RewardSourceId: item.RewardSourceID, + ResourceGroupId: item.ResourceGroupID, + WalletCommandId: item.WalletCommandID, + WalletGrantId: item.WalletGrantID, + Status: item.Status, + AttemptCount: item.AttemptCount, + FailureReason: item.FailureReason, + CreatedAtMs: item.CreatedAtMS, + UpdatedAtMs: item.UpdatedAtMS, + RewardOrigin: item.RewardOrigin, + TemporaryLevelId: item.TemporaryLevelID, + GrantGeneration: item.GrantGeneration, + RewardLevel: item.RewardLevel, + Permanent: item.Permanent, + TemporaryExpiresAtMs: item.TemporaryExpiresAtMS, + RevokeStatus: item.RevokeStatus, } } @@ -367,3 +403,16 @@ func registrationLevelBadgeGrantToProto(item domain.RegistrationLevelBadgeGrant) GrantId: item.GrantID, } } + +func adminUserLevelProfileToProto(item domain.AdminUserLevelProfile) *activityv1.AdminUserLevelProfile { + result := &activityv1.AdminUserLevelProfile{UserId: item.UserID, Tracks: make([]*activityv1.AdminLevelTrackProfile, 0, len(item.Tracks))} + for _, track := range item.Tracks { + result.Tracks = append(result.Tracks, &activityv1.AdminLevelTrackProfile{ + Track: track.Track, RealLevel: track.RealLevel, RealTotalValue: track.RealTotalValue, + DisplayLevel: track.DisplayLevel, DisplayValue: track.DisplayValue, + TemporaryLevelId: track.TemporaryLevelID, TemporaryTargetLevel: track.TemporaryTargetLevel, + StartedAtMs: track.StartedAtMS, ExpiresAtMs: track.ExpiresAtMS, + }) + } + return result +} diff --git a/services/cron-service/configs/config.docker.yaml b/services/cron-service/configs/config.docker.yaml index eeb73d72..5f1f49c9 100644 --- a/services/cron-service/configs/config.docker.yaml +++ b/services/cron-service/configs/config.docker.yaml @@ -21,63 +21,77 @@ tasks: timeout: "3s" lock_ttl: "30s" batch_size: 100 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] user_region_rebuild: enabled: true interval: "5s" timeout: "5s" lock_ttl: "30s" batch_size: 500 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] message_fanout: enabled: true interval: "1s" timeout: "10s" lock_ttl: "30s" batch_size: 500 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] + vip_daily_coin_rebate: + enabled: true + interval: "1m" + timeout: "30s" + lock_ttl: "1m" + batch_size: 500 + app_codes: ["lalu","fami","huwaa"] growth_level_reward: enabled: true interval: "5s" timeout: "10s" lock_ttl: "30s" batch_size: 100 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] + temporary_growth_level: + enabled: true + interval: "5s" + timeout: "15s" + lock_ttl: "30s" + batch_size: 100 + app_codes: ["lalu","fami","huwaa"] weekly_star_settlement: enabled: true interval: "5s" timeout: "20s" lock_ttl: "1m" batch_size: 50 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] agency_opening_settlement: enabled: true interval: "5s" timeout: "20s" lock_ttl: "1m" batch_size: 50 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] room_turnover_reward_settlement: enabled: true interval: "5m" timeout: "30s" lock_ttl: "5m" batch_size: 100 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] cp_intimacy_leaderboard: enabled: true interval: "5m" timeout: "20s" lock_ttl: "5m" batch_size: 10000 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] game_level_event_relay: enabled: true interval: "5s" timeout: "10s" lock_ttl: "30s" batch_size: 100 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] mic_open_session_compensation: enabled: true interval: "60s" @@ -86,4 +100,26 @@ tasks: batch_size: 100 pending_publish_max_age: "2m" publishing_session_max_age: "12h" - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] + room_open_session_compensation: + enabled: true + interval: "60s" + timeout: "10s" + lock_ttl: "60s" + batch_size: 200 + open_session_max_age: "24h" + app_codes: ["lalu","fami","huwaa"] + manager_user_block_expiry: + enabled: true + interval: "30s" + timeout: "10s" + lock_ttl: "30s" + batch_size: 100 + app_codes: ["lalu","fami","huwaa"] + admin_user_ban_expiry: + enabled: true + interval: "30s" + timeout: "10s" + lock_ttl: "30s" + batch_size: 100 + app_codes: ["lalu","fami","huwaa"] diff --git a/services/cron-service/configs/config.tencent.example.yaml b/services/cron-service/configs/config.tencent.example.yaml index e6092dc6..a4c76da2 100644 --- a/services/cron-service/configs/config.tencent.example.yaml +++ b/services/cron-service/configs/config.tencent.example.yaml @@ -21,63 +21,77 @@ tasks: timeout: "3s" lock_ttl: "30s" batch_size: 100 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] user_region_rebuild: enabled: true interval: "5s" timeout: "5s" lock_ttl: "30s" batch_size: 500 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] message_fanout: enabled: true interval: "1s" timeout: "10s" lock_ttl: "30s" batch_size: 500 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] + vip_daily_coin_rebate: + enabled: true + interval: "1m" + timeout: "30s" + lock_ttl: "1m" + batch_size: 500 + app_codes: ["lalu","fami","huwaa"] growth_level_reward: enabled: true interval: "5s" timeout: "10s" lock_ttl: "30s" batch_size: 100 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] + temporary_growth_level: + enabled: true + interval: "5s" + timeout: "15s" + lock_ttl: "30s" + batch_size: 100 + app_codes: ["lalu","fami","huwaa"] weekly_star_settlement: enabled: true interval: "5s" timeout: "20s" lock_ttl: "1m" batch_size: 50 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] agency_opening_settlement: enabled: true interval: "5s" timeout: "20s" lock_ttl: "1m" batch_size: 50 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] room_turnover_reward_settlement: enabled: true interval: "5m" timeout: "30s" lock_ttl: "5m" batch_size: 100 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] cp_intimacy_leaderboard: enabled: true interval: "5m" timeout: "20s" lock_ttl: "5m" batch_size: 10000 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] game_level_event_relay: enabled: true interval: "5s" timeout: "10s" lock_ttl: "30s" batch_size: 100 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] mic_open_session_compensation: enabled: true interval: "60s" @@ -86,4 +100,26 @@ tasks: batch_size: 100 pending_publish_max_age: "2m" publishing_session_max_age: "12h" - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] + room_open_session_compensation: + enabled: true + interval: "60s" + timeout: "10s" + lock_ttl: "60s" + batch_size: 200 + open_session_max_age: "24h" + app_codes: ["lalu","fami","huwaa"] + manager_user_block_expiry: + enabled: true + interval: "30s" + timeout: "10s" + lock_ttl: "30s" + batch_size: 100 + app_codes: ["lalu","fami","huwaa"] + admin_user_ban_expiry: + enabled: true + interval: "30s" + timeout: "10s" + lock_ttl: "30s" + batch_size: 100 + app_codes: ["lalu","fami","huwaa"] diff --git a/services/cron-service/configs/config.yaml b/services/cron-service/configs/config.yaml index e8d8a21d..6d345ede 100644 --- a/services/cron-service/configs/config.yaml +++ b/services/cron-service/configs/config.yaml @@ -21,63 +21,77 @@ tasks: timeout: "3s" lock_ttl: "30s" batch_size: 100 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] user_region_rebuild: enabled: true interval: "5s" timeout: "5s" lock_ttl: "30s" batch_size: 500 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] message_fanout: enabled: true interval: "1s" timeout: "10s" lock_ttl: "30s" batch_size: 500 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] + vip_daily_coin_rebate: + enabled: true + interval: "1m" + timeout: "30s" + lock_ttl: "1m" + batch_size: 500 + app_codes: ["lalu","fami","huwaa"] growth_level_reward: enabled: true interval: "5s" timeout: "10s" lock_ttl: "30s" batch_size: 100 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] + temporary_growth_level: + enabled: true + interval: "5s" + timeout: "15s" + lock_ttl: "30s" + batch_size: 100 + app_codes: ["lalu","fami","huwaa"] weekly_star_settlement: enabled: true interval: "5s" timeout: "20s" lock_ttl: "1m" batch_size: 50 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] agency_opening_settlement: enabled: true interval: "5s" timeout: "20s" lock_ttl: "1m" batch_size: 50 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] room_turnover_reward_settlement: enabled: true interval: "5m" timeout: "30s" lock_ttl: "5m" batch_size: 100 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] cp_intimacy_leaderboard: enabled: true interval: "5m" timeout: "20s" lock_ttl: "5m" batch_size: 10000 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] game_level_event_relay: enabled: true interval: "5s" timeout: "10s" lock_ttl: "30s" batch_size: 100 - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] mic_open_session_compensation: enabled: true interval: "60s" @@ -86,4 +100,26 @@ tasks: batch_size: 100 pending_publish_max_age: "2m" publishing_session_max_age: "12h" - app_codes: ["lalu"] + app_codes: ["lalu","fami","huwaa"] + room_open_session_compensation: + enabled: true + interval: "60s" + timeout: "10s" + lock_ttl: "60s" + batch_size: 200 + open_session_max_age: "24h" + app_codes: ["lalu","fami","huwaa"] + manager_user_block_expiry: + enabled: true + interval: "30s" + timeout: "10s" + lock_ttl: "30s" + batch_size: 100 + app_codes: ["lalu","fami","huwaa"] + admin_user_ban_expiry: + enabled: true + interval: "30s" + timeout: "10s" + lock_ttl: "30s" + batch_size: 100 + app_codes: ["lalu","fami","huwaa"] diff --git a/services/cron-service/internal/app/app.go b/services/cron-service/internal/app/app.go index 05513b6d..cd67d519 100644 --- a/services/cron-service/internal/app/app.go +++ b/services/cron-service/internal/app/app.go @@ -116,12 +116,15 @@ func New(cfg config.Config) (*App, error) { taskScheduler := scheduler.New(cfg.NodeID, cfg.Tasks, repository, map[string]scheduler.Handler{ "login_ip_risk": userCron.ProcessLoginIPRiskBatch, "user_region_rebuild": userCron.ProcessRegionRebuildBatch, - "mic_open_session_compensation": userCron.CompensateMicOpenSessions, + "mic_open_session_compensation": userCron.CompensateMicOpenSessions, + "room_open_session_compensation": userCron.CompensateRoomOpenSessions, "manager_user_block_expiry": userCron.ExpireManagerUserBlocks, + "admin_user_ban_expiry": userCron.ExpireAdminUserBans, // CP 榜单任务只占 cron 租约并调用 user-service;真实 MySQL 读取、wallet 头像框补齐和 Redis 替换都在 user-service 内完成。 "cp_intimacy_leaderboard": userCron.RefreshCPIntimacyLeaderboard, "message_fanout": activityCron.ProcessMessageFanoutBatch, "growth_level_reward": activityCron.ProcessLevelRewardBatch, + "temporary_growth_level": activityCron.ProcessTemporaryLevelBatch, "achievement_reward": activityCron.ProcessAchievementRewardBatch, "weekly_star_settlement": activityCron.ProcessWeeklyStarSettlementBatch, "agency_opening_settlement": activityCron.ProcessAgencyOpeningSettlementBatch, @@ -129,6 +132,7 @@ func New(cfg config.Config) (*App, error) { "room_turnover_reward_settlement": activityCron.ProcessRoomTurnoverRewardSettlementBatch, "game_level_event_relay": gameCron.ProcessLevelEventOutboxBatch, "host_salary_daily_settlement": walletCron.ProcessHostSalaryDailySettlementBatch, + "vip_daily_coin_rebate": walletCron.ProcessVIPDailyCoinRebateBatch, "host_salary_half_month_settlement": walletCron.ProcessHostSalaryHalfMonthSettlementBatch, "host_salary_month_end": walletCron.ProcessHostSalaryMonthEndBatch, }) diff --git a/services/cron-service/internal/config/config.go b/services/cron-service/internal/config/config.go index 19f828c0..d6a038ad 100644 --- a/services/cron-service/internal/config/config.go +++ b/services/cron-service/internal/config/config.go @@ -57,6 +57,8 @@ type TaskConfig struct { PendingPublishMaxAge string `yaml:"pending_publish_max_age"` // PublishingSessionMaxAge is used by mic_open_session_compensation for publishing sessions. PublishingSessionMaxAge string `yaml:"publishing_session_max_age"` + // OpenSessionMaxAge is used by room_open_session_compensation for open in-room sessions. + OpenSessionMaxAge string `yaml:"open_session_max_age"` } // Default returns local development defaults that follow the 13xxx port rule. @@ -148,6 +150,16 @@ func defaultTasks() map[string]TaskConfig { BatchSize: 500, AppCodes: []string{defaultAppCode}, }, + "vip_daily_coin_rebate": { + // scheduler 启动即执行,因此不能用 24h 间隔假装 UTC 0 点;每分钟触发一次, + // wallet owner 以 UTC task_day 的 completed run 快速 no-op,并在跨日后创建新批次。 + Enabled: true, + Interval: "1m", + Timeout: "30s", + LockTTL: "1m", + BatchSize: 500, + AppCodes: []string{"lalu", "fami"}, + }, "growth_level_reward": { Enabled: true, Interval: "5s", @@ -156,6 +168,14 @@ func defaultTasks() map[string]TaskConfig { BatchSize: 100, AppCodes: []string{defaultAppCode}, }, + "temporary_growth_level": { + Enabled: true, + Interval: "5s", + Timeout: "15s", + LockTTL: "30s", + BatchSize: 100, + AppCodes: []string{defaultAppCode}, + }, "achievement_reward": { Enabled: true, Interval: "5s", @@ -246,6 +266,16 @@ func defaultTasks() map[string]TaskConfig { PendingPublishMaxAge: "2m", PublishingSessionMaxAge: "12h", }, + "room_open_session_compensation": { + Enabled: true, + Interval: "60s", + Timeout: "10s", + LockTTL: "60s", + BatchSize: 200, + AppCodes: []string{defaultAppCode}, + // stale worker 2 分钟兜底断线离房;24h 只兜 room-service 节点崩溃或 outbox 丢失的极端场景。 + OpenSessionMaxAge: "24h", + }, "manager_user_block_expiry": { Enabled: true, Interval: "30s", @@ -254,6 +284,14 @@ func defaultTasks() map[string]TaskConfig { BatchSize: 100, AppCodes: []string{defaultAppCode}, }, + "admin_user_ban_expiry": { + Enabled: true, + Interval: "30s", + Timeout: "10s", + LockTTL: "30s", + BatchSize: 100, + AppCodes: []string{defaultAppCode}, + }, } } @@ -303,6 +341,10 @@ func mergeTaskConfig(def TaskConfig, current TaskConfig) TaskConfig { if current.PublishingSessionMaxAge == "" { current.PublishingSessionMaxAge = def.PublishingSessionMaxAge } + current.OpenSessionMaxAge = strings.TrimSpace(current.OpenSessionMaxAge) + if current.OpenSessionMaxAge == "" { + current.OpenSessionMaxAge = def.OpenSessionMaxAge + } if current.BatchSize <= 0 { current.BatchSize = def.BatchSize } diff --git a/services/cron-service/internal/config/config_test.go b/services/cron-service/internal/config/config_test.go index 4cd0200e..eb357a46 100644 --- a/services/cron-service/internal/config/config_test.go +++ b/services/cron-service/internal/config/config_test.go @@ -32,3 +32,13 @@ func TestDefaultCPIntimacyLeaderboardCronTaskRunsEveryFiveMinutes(t *testing.T) t.Fatalf("cp intimacy leaderboard cron task has unexpected defaults: %+v", task) } } + +func TestDefaultVIPDailyCoinRebatePollsBothApps(t *testing.T) { + task, ok := Default().Tasks["vip_daily_coin_rebate"] + if !ok || !task.Enabled || task.Interval != "1m" || task.BatchSize != 500 { + t.Fatalf("VIP daily coin rebate task mismatch: %+v", task) + } + if len(task.AppCodes) != 2 || task.AppCodes[0] != "lalu" || task.AppCodes[1] != "fami" { + t.Fatalf("VIP rebate must be app-scoped for both configured apps: %+v", task.AppCodes) + } +} diff --git a/services/cron-service/internal/integration/activity.go b/services/cron-service/internal/integration/activity.go index 4baf13ce..174bb97e 100644 --- a/services/cron-service/internal/integration/activity.go +++ b/services/cron-service/internal/integration/activity.go @@ -36,6 +36,15 @@ func (c *ActivityCronClient) ProcessLevelRewardBatch(ctx context.Context, req sc return activityCronBatchResult(resp), nil } +// ProcessTemporaryLevelBatch handles overlay expiry, notice retries and wallet-grant revocations in activity-service. +func (c *ActivityCronClient) ProcessTemporaryLevelBatch(ctx context.Context, req scheduler.BatchRequest) (scheduler.BatchResult, error) { + resp, err := c.client.ProcessTemporaryLevelBatch(ctx, activityCronBatchRequest(req)) + if err != nil { + return scheduler.BatchResult{}, err + } + return activityCronBatchResult(resp), nil +} + // ProcessAchievementRewardBatch handles achievement_reward_jobs. func (c *ActivityCronClient) ProcessAchievementRewardBatch(ctx context.Context, req scheduler.BatchRequest) (scheduler.BatchResult, error) { resp, err := c.client.ProcessAchievementRewardBatch(ctx, activityCronBatchRequest(req)) diff --git a/services/cron-service/internal/integration/user.go b/services/cron-service/internal/integration/user.go index a14b5c13..120a06ba 100644 --- a/services/cron-service/internal/integration/user.go +++ b/services/cron-service/internal/integration/user.go @@ -38,12 +38,24 @@ func (c *UserCronClient) CompensateMicOpenSessions(ctx context.Context, req sche return userCronResult(resp), err } +// CompensateRoomOpenSessions handles abnormal user_room_sessions closure. +func (c *UserCronClient) CompensateRoomOpenSessions(ctx context.Context, req scheduler.BatchRequest) (scheduler.BatchResult, error) { + resp, err := c.client.CompensateRoomOpenSessions(ctx, userCronRequest(req)) + return userCronResult(resp), err +} + // ExpireManagerUserBlocks handles timed manager-center bans after their unblock time. func (c *UserCronClient) ExpireManagerUserBlocks(ctx context.Context, req scheduler.BatchRequest) (scheduler.BatchResult, error) { resp, err := c.client.ExpireManagerUserBlocks(ctx, userCronRequest(req)) return userCronResult(resp), err } +// ExpireAdminUserBans handles timed admin bans; permanent bans are never selected by user-service. +func (c *UserCronClient) ExpireAdminUserBans(ctx context.Context, req scheduler.BatchRequest) (scheduler.BatchResult, error) { + resp, err := c.client.ExpireAdminUserBans(ctx, userCronRequest(req)) + return userCronResult(resp), err +} + // RefreshCPIntimacyLeaderboard 只触发 user-service 重建 CP 亲密值 zset 读模型,cron 不读取业务表。 func (c *UserCronClient) RefreshCPIntimacyLeaderboard(ctx context.Context, req scheduler.BatchRequest) (scheduler.BatchResult, error) { // userCronRequest 会带 run_id、worker_id、app_code 和 batch_size;user-service 用这些值做日志追踪、租户隔离和刷新上限。 @@ -66,6 +78,7 @@ func userCronRequest(req scheduler.BatchRequest) *userv1.CronBatchRequest { LockTtlMs: req.LockTTL.Milliseconds(), PendingPublishMaxAgeMs: req.PendingPublishMaxAge.Milliseconds(), PublishingSessionMaxAgeMs: req.PublishingSessionMaxAge.Milliseconds(), + OpenSessionMaxAgeMs: req.OpenSessionMaxAge.Milliseconds(), } } diff --git a/services/cron-service/internal/integration/wallet.go b/services/cron-service/internal/integration/wallet.go index 79c823f7..35ea45b8 100644 --- a/services/cron-service/internal/integration/wallet.go +++ b/services/cron-service/internal/integration/wallet.go @@ -27,6 +27,25 @@ func (c *WalletCronClient) ProcessHostSalaryDailySettlementBatch(ctx context.Con return walletCronBatchResult(resp), err } +// ProcessVIPDailyCoinRebateBatch 每分钟触发 wallet owner 的 UTC 日 run。cron 不传 task_day, +// 避免调度进程所在时区或延迟重启改变业务日期;wallet 会以自己的 UTC 时钟创建/复用当日快照。 +func (c *WalletCronClient) ProcessVIPDailyCoinRebateBatch(ctx context.Context, req scheduler.BatchRequest) (scheduler.BatchResult, error) { + resp, err := c.client.ProcessVipDailyCoinRebateBatch(ctx, &walletv1.ProcessVipDailyCoinRebateBatchRequest{ + RequestId: req.RunID, + AppCode: req.AppCode, + BatchSize: int32(req.BatchSize), + }) + if err != nil || resp == nil { + return scheduler.BatchResult{}, err + } + return scheduler.BatchResult{ + ClaimedCount: int(resp.GetScannedCount()), + ProcessedCount: int(resp.GetScannedCount()), + SuccessCount: int(resp.GetCreatedCount()), + HasMore: resp.GetHasMore(), + }, nil +} + func (c *WalletCronClient) ProcessHostSalaryHalfMonthSettlementBatch(ctx context.Context, req scheduler.BatchRequest) (scheduler.BatchResult, error) { if !isHostSalaryHalfMonthDue(walletCronNowUTC()) { // 半月结是否适用于某个主播由后台工资政策 settlement_mode 决定;cron 这里只负责在月中打开一次全局触发窗口。 diff --git a/services/cron-service/internal/scheduler/scheduler.go b/services/cron-service/internal/scheduler/scheduler.go index 92312c03..cebee78e 100644 --- a/services/cron-service/internal/scheduler/scheduler.go +++ b/services/cron-service/internal/scheduler/scheduler.go @@ -38,6 +38,7 @@ type BatchRequest struct { LockTTL time.Duration PendingPublishMaxAge time.Duration PublishingSessionMaxAge time.Duration + OpenSessionMaxAge time.Duration } // BatchResult summarizes one owner-service batch response. @@ -167,6 +168,7 @@ func (s *Scheduler) runOnce(ctx context.Context, taskName string, appCode string LockTTL: lockTTL, PendingPublishMaxAge: parseDuration(task.PendingPublishMaxAge, 0), PublishingSessionMaxAge: parseDuration(task.PublishingSessionMaxAge, 0), + OpenSessionMaxAge: parseDuration(task.OpenSessionMaxAge, 0), }) cancel() diff --git a/services/gateway-service/internal/client/broadcast_client.go b/services/gateway-service/internal/client/broadcast_client.go index f652487e..4be21cc8 100644 --- a/services/gateway-service/internal/client/broadcast_client.go +++ b/services/gateway-service/internal/client/broadcast_client.go @@ -10,6 +10,7 @@ import ( // BroadcastClient abstracts gateway access to activity-service IM broadcast membership operations. type BroadcastClient interface { + PublishGlobalBroadcast(ctx context.Context, req *activityv1.PublishGlobalBroadcastRequest) (*activityv1.PublishBroadcastResponse, error) RemoveRegionBroadcastMember(ctx context.Context, req *activityv1.RemoveRegionBroadcastMemberRequest) (*activityv1.RemoveRegionBroadcastMemberResponse, error) } @@ -22,6 +23,10 @@ func NewGRPCBroadcastClient(conn *grpc.ClientConn) BroadcastClient { return &grpcBroadcastClient{client: activityv1.NewBroadcastServiceClient(conn)} } +func (c *grpcBroadcastClient) PublishGlobalBroadcast(ctx context.Context, req *activityv1.PublishGlobalBroadcastRequest) (*activityv1.PublishBroadcastResponse, error) { + return c.client.PublishGlobalBroadcast(ctx, req) +} + func (c *grpcBroadcastClient) RemoveRegionBroadcastMember(ctx context.Context, req *activityv1.RemoveRegionBroadcastMemberRequest) (*activityv1.RemoveRegionBroadcastMemberResponse, error) { return c.client.RemoveRegionBroadcastMember(ctx, req) } diff --git a/services/gateway-service/internal/client/user_client.go b/services/gateway-service/internal/client/user_client.go index 966fb0d6..64bb11d3 100644 --- a/services/gateway-service/internal/client/user_client.go +++ b/services/gateway-service/internal/client/user_client.go @@ -98,8 +98,9 @@ type UserCountryQueryClient interface { ListLoginRiskBlockedCountries(ctx context.Context, req *userv1.ListLoginRiskBlockedCountriesRequest) (*userv1.ListLoginRiskBlockedCountriesResponse, error) } -// UserRegionClient 抽象 gateway 对 user-service 区域国家归属查询的依赖。 +// UserRegionClient 抽象 gateway 对 user-service 区域目录和国家归属查询的依赖。 type UserRegionClient interface { + ListRegions(ctx context.Context, req *userv1.ListRegionsRequest) (*userv1.ListRegionsResponse, error) GetRegion(ctx context.Context, req *userv1.GetRegionRequest) (*userv1.RegionResponse, error) } @@ -509,6 +510,10 @@ func (c *grpcUserCountryQueryClient) ListLoginRiskBlockedCountries(ctx context.C return c.client.ListLoginRiskBlockedCountries(ctx, req) } +func (c *grpcUserRegionClient) ListRegions(ctx context.Context, req *userv1.ListRegionsRequest) (*userv1.ListRegionsResponse, error) { + return c.client.ListRegions(ctx, req) +} + func (c *grpcUserRegionClient) GetRegion(ctx context.Context, req *userv1.GetRegionRequest) (*userv1.RegionResponse, error) { return c.client.GetRegion(ctx, req) } diff --git a/services/gateway-service/internal/client/wallet_client.go b/services/gateway-service/internal/client/wallet_client.go index 78064b5c..acbd735e 100644 --- a/services/gateway-service/internal/client/wallet_client.go +++ b/services/gateway-service/internal/client/wallet_client.go @@ -34,7 +34,16 @@ type WalletClient interface { ListWalletTransactions(ctx context.Context, req *walletv1.ListWalletTransactionsRequest) (*walletv1.ListWalletTransactionsResponse, error) ListVipPackages(ctx context.Context, req *walletv1.ListVipPackagesRequest) (*walletv1.ListVipPackagesResponse, error) GetMyVip(ctx context.Context, req *walletv1.GetMyVipRequest) (*walletv1.GetMyVipResponse, error) + GetVipProgramConfig(ctx context.Context, req *walletv1.GetVipProgramConfigRequest) (*walletv1.GetVipProgramConfigResponse, error) + CheckVipBenefit(ctx context.Context, req *walletv1.CheckVipBenefitRequest) (*walletv1.CheckVipBenefitResponse, error) + UpdateMyVipSettings(ctx context.Context, req *walletv1.UpdateMyVipSettingsRequest) (*walletv1.UpdateMyVipSettingsResponse, error) PurchaseVip(ctx context.Context, req *walletv1.PurchaseVipRequest) (*walletv1.PurchaseVipResponse, error) + GrantVipTrialCard(ctx context.Context, req *walletv1.GrantVipTrialCardRequest) (*walletv1.GrantVipTrialCardResponse, error) + EquipVipTrialCard(ctx context.Context, req *walletv1.EquipVipTrialCardRequest) (*walletv1.EquipVipTrialCardResponse, error) + UnequipVipTrialCard(ctx context.Context, req *walletv1.UnequipVipTrialCardRequest) (*walletv1.UnequipVipTrialCardResponse, error) + GetMyCurrentVipDailyCoinRebate(ctx context.Context, req *walletv1.GetMyCurrentVipDailyCoinRebateRequest) (*walletv1.GetMyCurrentVipDailyCoinRebateResponse, error) + ListMyVipDailyCoinRebateStatuses(ctx context.Context, req *walletv1.ListMyVipDailyCoinRebateStatusesRequest) (*walletv1.ListMyVipDailyCoinRebateStatusesResponse, error) + ClaimVipDailyCoinRebate(ctx context.Context, req *walletv1.ClaimVipDailyCoinRebateRequest) (*walletv1.ClaimVipDailyCoinRebateResponse, error) DebitCPBreakupFee(ctx context.Context, req *walletv1.DebitCPBreakupFeeRequest) (*walletv1.DebitCPBreakupFeeResponse, error) DebitWheelDraw(ctx context.Context, req *walletv1.DebitWheelDrawRequest) (*walletv1.DebitWheelDrawResponse, error) GrantVip(ctx context.Context, req *walletv1.GrantVipRequest) (*walletv1.GrantVipResponse, error) @@ -170,10 +179,46 @@ func (c *grpcWalletClient) GetMyVip(ctx context.Context, req *walletv1.GetMyVipR return c.client.GetMyVip(ctx, req) } +func (c *grpcWalletClient) GetVipProgramConfig(ctx context.Context, req *walletv1.GetVipProgramConfigRequest) (*walletv1.GetVipProgramConfigResponse, error) { + return c.client.GetVipProgramConfig(ctx, req) +} + +func (c *grpcWalletClient) CheckVipBenefit(ctx context.Context, req *walletv1.CheckVipBenefitRequest) (*walletv1.CheckVipBenefitResponse, error) { + return c.client.CheckVipBenefit(ctx, req) +} + +func (c *grpcWalletClient) UpdateMyVipSettings(ctx context.Context, req *walletv1.UpdateMyVipSettingsRequest) (*walletv1.UpdateMyVipSettingsResponse, error) { + return c.client.UpdateMyVipSettings(ctx, req) +} + func (c *grpcWalletClient) PurchaseVip(ctx context.Context, req *walletv1.PurchaseVipRequest) (*walletv1.PurchaseVipResponse, error) { return c.client.PurchaseVip(ctx, req) } +func (c *grpcWalletClient) GrantVipTrialCard(ctx context.Context, req *walletv1.GrantVipTrialCardRequest) (*walletv1.GrantVipTrialCardResponse, error) { + return c.client.GrantVipTrialCard(ctx, req) +} + +func (c *grpcWalletClient) EquipVipTrialCard(ctx context.Context, req *walletv1.EquipVipTrialCardRequest) (*walletv1.EquipVipTrialCardResponse, error) { + return c.client.EquipVipTrialCard(ctx, req) +} + +func (c *grpcWalletClient) UnequipVipTrialCard(ctx context.Context, req *walletv1.UnequipVipTrialCardRequest) (*walletv1.UnequipVipTrialCardResponse, error) { + return c.client.UnequipVipTrialCard(ctx, req) +} + +func (c *grpcWalletClient) GetMyCurrentVipDailyCoinRebate(ctx context.Context, req *walletv1.GetMyCurrentVipDailyCoinRebateRequest) (*walletv1.GetMyCurrentVipDailyCoinRebateResponse, error) { + return c.client.GetMyCurrentVipDailyCoinRebate(ctx, req) +} + +func (c *grpcWalletClient) ListMyVipDailyCoinRebateStatuses(ctx context.Context, req *walletv1.ListMyVipDailyCoinRebateStatusesRequest) (*walletv1.ListMyVipDailyCoinRebateStatusesResponse, error) { + return c.client.ListMyVipDailyCoinRebateStatuses(ctx, req) +} + +func (c *grpcWalletClient) ClaimVipDailyCoinRebate(ctx context.Context, req *walletv1.ClaimVipDailyCoinRebateRequest) (*walletv1.ClaimVipDailyCoinRebateResponse, error) { + return c.client.ClaimVipDailyCoinRebate(ctx, req) +} + func (c *grpcWalletClient) DebitCPBreakupFee(ctx context.Context, req *walletv1.DebitCPBreakupFeeRequest) (*walletv1.DebitCPBreakupFeeResponse, error) { return c.client.DebitCPBreakupFee(ctx, req) } diff --git a/services/gateway-service/internal/transport/http/httproutes/router.go b/services/gateway-service/internal/transport/http/httproutes/router.go index 0edcba8b..87c6599b 100644 --- a/services/gateway-service/internal/transport/http/httproutes/router.go +++ b/services/gateway-service/internal/transport/http/httproutes/router.go @@ -154,6 +154,7 @@ type ManagerHandlers struct { type RoomHandlers struct { GetMyRoom http.HandlerFunc ListRoomFeeds http.HandlerFunc + ListRoomFilters http.HandlerFunc ListRooms http.HandlerFunc GetCurrentRoom http.HandlerFunc GetRoomSnapshot http.HandlerFunc @@ -298,9 +299,16 @@ type WalletHandlers struct { } type VIPHandlers struct { - GetMyVIP http.HandlerFunc - ListVIPPackages http.HandlerFunc - PurchaseVIP http.HandlerFunc + GetMyVIP http.HandlerFunc + ListVIPPackages http.HandlerFunc + PurchaseVIP http.HandlerFunc + EquipVIPTrialCard http.HandlerFunc + UnequipVIPTrialCard http.HandlerFunc + TriggerOnlineNotice http.HandlerFunc + HandleVIPSettings http.HandlerFunc + GetCurrentCoinRebate http.HandlerFunc + ListCoinRebateStatuses http.HandlerFunc + ClaimCoinRebate http.HandlerFunc } type GameHandlers struct { @@ -519,6 +527,7 @@ func (r routes) registerManagerRoutes() { func (r routes) registerRoomRoutes() { h := r.config.Room r.rootPublic("/share/rooms/{room_id}", http.MethodGet, h.GetRoomShareLanding) + r.profile("/rooms/filters", http.MethodGet, h.ListRoomFilters) r.profile("/rooms/me", http.MethodGet, h.GetMyRoom) r.profile("/rooms/feeds", http.MethodGet, h.ListRoomFeeds) r.profile("/rooms", http.MethodGet, h.ListRooms) @@ -691,6 +700,13 @@ func (r routes) registerVIPRoutes() { r.profile("/vip/me", http.MethodGet, h.GetMyVIP) r.profile("/vip/packages", http.MethodGet, h.ListVIPPackages) r.profile("/vip/purchase", http.MethodPost, h.PurchaseVIP) + r.profile("/vip/trial-cards/{entitlement_id}/equip", http.MethodPost, h.EquipVIPTrialCard) + r.profile("/vip/trial-cards/equipped", http.MethodDelete, h.UnequipVIPTrialCard) + r.profile("/vip/online-notice", http.MethodPost, h.TriggerOnlineNotice) + r.profile("/vip/settings", "", h.HandleVIPSettings) + r.profile("/vip/coin-rebates/current", http.MethodGet, h.GetCurrentCoinRebate) + r.profile("/vip/coin-rebates/statuses", http.MethodPost, h.ListCoinRebateStatuses) + r.profile("/vip/coin-rebates/{rebate_id}/claim", http.MethodPost, h.ClaimCoinRebate) } func (r routes) registerGameRoutes() { diff --git a/services/gateway-service/internal/transport/http/manager_center_handler_test.go b/services/gateway-service/internal/transport/http/manager_center_handler_test.go index da3868e6..9548bef1 100644 --- a/services/gateway-service/internal/transport/http/manager_center_handler_test.go +++ b/services/gateway-service/internal/transport/http/manager_center_handler_test.go @@ -306,6 +306,65 @@ func TestSearchManagerUsersDefaultsSameCountryAndAllowsAllForCountryTransfer(t * } } +func TestSearchManagerUsersAllowsCrossCountryOnlyForHuwaaBDLeaderAction(t *testing.T) { + profileClient := &fakeUserProfileClient{ + businessLookupResp: &userv1.BusinessUserLookupResponse{Users: []*userv1.BusinessUserLookupItem{ + {UserId: 900001, Status: userv1.UserStatus_USER_STATUS_ACTIVE}, + {UserId: 900002, Status: userv1.UserStatus_USER_STATUS_ACTIVE}, + }}, + usersByID: map[int64]*userv1.User{ + 42: {UserId: 42, Status: userv1.UserStatus_USER_STATUS_ACTIVE, Country: "US"}, + 900001: {UserId: 900001, Status: userv1.UserStatus_USER_STATUS_ACTIVE, Country: "US"}, + 900002: {UserId: 900002, Status: userv1.UserStatus_USER_STATUS_ACTIVE, Country: "CA"}, + }, + } + router := newManagerCenterTestRouter(&fakeWalletClient{}, &fakeUserHostClient{}, profileClient) + + bdLeaderRequest := httptest.NewRequest(http.MethodGet, "/api/v1/manager-center/users/search?keyword=900&action=add-bd-leader", nil) + bdLeaderRequest.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "huwaa")) + bdLeaderRequest.Header.Set("X-Request-ID", "req-huwaa-manager-search-bdleader") + bdLeaderRecorder := httptest.NewRecorder() + router.ServeHTTP(bdLeaderRecorder, bdLeaderRequest) + + if bdLeaderRecorder.Code != http.StatusOK { + t.Fatalf("Huwaa BD Leader search status mismatch: got %d body=%s", bdLeaderRecorder.Code, bdLeaderRecorder.Body.String()) + } + var bdLeaderEnvelope struct { + Data struct { + Items []struct { + UserID string `json:"user_id"` + } `json:"items"` + Total int `json:"total"` + } `json:"data"` + } + if err := json.NewDecoder(bdLeaderRecorder.Body).Decode(&bdLeaderEnvelope); err != nil { + t.Fatalf("decode Huwaa BD Leader search response failed: %v", err) + } + if bdLeaderEnvelope.Data.Total != 2 || profileClient.lastBusinessLookup.GetScene() != "manager_add_bd_leader" || profileClient.lastBusinessLookup.GetMeta().GetAppCode() != "huwaa" { + t.Fatalf("Huwaa BD Leader search must keep app scope while including cross-country targets: data=%+v req=%+v", bdLeaderEnvelope.Data, profileClient.lastBusinessLookup) + } + + adminRequest := httptest.NewRequest(http.MethodGet, "/api/v1/manager-center/users/search?keyword=900&action=add-admin", nil) + adminRequest.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "huwaa")) + adminRequest.Header.Set("X-Request-ID", "req-huwaa-manager-search-admin") + adminRecorder := httptest.NewRecorder() + router.ServeHTTP(adminRecorder, adminRequest) + if adminRecorder.Code != http.StatusOK { + t.Fatalf("Huwaa admin search status mismatch: got %d body=%s", adminRecorder.Code, adminRecorder.Body.String()) + } + var adminEnvelope struct { + Data struct { + Total int `json:"total"` + } `json:"data"` + } + if err := json.NewDecoder(adminRecorder.Body).Decode(&adminEnvelope); err != nil { + t.Fatalf("decode Huwaa admin search response failed: %v", err) + } + if adminEnvelope.Data.Total != 1 { + t.Fatalf("Huwaa non-role manager actions must remain same-country: %+v", adminEnvelope.Data) + } +} + func TestGrantManagerResourceUsesServerControlledGrantShape(t *testing.T) { walletClient := &fakeWalletClient{} hostClient := &fakeUserHostClient{} @@ -542,6 +601,55 @@ func TestGrantManagerVIPUsesManagerCenterGrantSource(t *testing.T) { } } +func TestGrantManagerVIPUsesTrialCardForConfiguredApp(t *testing.T) { + walletClient := &fakeWalletClient{ + vipProgramResp: &walletv1.GetVipProgramConfigResponse{Config: &walletv1.VipProgramConfig{ + AppCode: "lalu", GrantMode: "trial_card", TrialCardEnabled: true, Status: "active", + }}, + trialGrantResp: &walletv1.GrantVipTrialCardResponse{ + TrialCard: &walletv1.VipTrialCard{ + TrialCardId: "card-5", EntitlementId: "ent-5", SourceGrantId: "grant-5", + Level: 5, Status: "active", ExpiresAtMs: 1_800_000_000_000, + }, + ServerTimeMs: 1_790_000_000_000, + }, + } + router := newManagerCenterTestRouter(walletClient, &fakeUserHostClient{}, &fakeUserProfileClient{}) + body := []byte(`{"command_id":"mgr-fami-vip-5","target_user_id":"900001","level":5}`) + request := httptest.NewRequest(http.MethodPost, "/api/v1/manager-center/vip-grants", bytes.NewReader(body)) + request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) + request.Header.Set("X-Request-ID", "req-manager-fami-vip5") + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if walletClient.lastGrantVip != nil { + t.Fatalf("trial-card program must not call direct GrantVip: %+v", walletClient.lastGrantVip) + } + req := walletClient.lastTrialGrant + if req == nil || req.GetAppCode() != "lalu" || req.GetCommandId() != "mgr-fami-vip-5" || req.GetTargetUserId() != 900001 || req.GetLevel() != 5 || req.GetDurationMs() != 30*24*60*60*1000 || req.GetGrantSource() != "manager_center" || req.GetOperatorUserId() != 42 { + t.Fatalf("wallet GrantVipTrialCard request mismatch: %+v", req) + } + var envelope struct { + Data struct { + GrantMode string `json:"grant_mode"` + TrialCardID string `json:"trial_card_id"` + EntitlementID string `json:"entitlement_id"` + Active bool `json:"active"` + Equipped bool `json:"equipped"` + } `json:"data"` + } + if err := json.Unmarshal(recorder.Body.Bytes(), &envelope); err != nil { + t.Fatalf("decode response failed: %v", err) + } + if envelope.Data.GrantMode != "trial_card" || envelope.Data.TrialCardID != "card-5" || envelope.Data.EntitlementID != "ent-5" || envelope.Data.Active || envelope.Data.Equipped { + t.Fatalf("trial-card manager response mismatch: %+v", envelope.Data) + } +} + func TestManagerBlockAndUnblockCallUserService(t *testing.T) { profileClient := &fakeUserProfileClient{} router := newManagerCenterTestRouter(&fakeWalletClient{}, &fakeUserHostClient{}, profileClient) @@ -660,6 +768,29 @@ func TestCreateManagerBDLeaderRejectsCrossCountryTarget(t *testing.T) { } } +func TestCreateManagerBDLeaderAllowsCrossCountryTargetForHuwaa(t *testing.T) { + hostAdminClient := &fakeUserHostAdminClient{} + profileClient := &fakeUserProfileClient{usersByID: map[int64]*userv1.User{ + 42: {UserId: 42, Status: userv1.UserStatus_USER_STATUS_ACTIVE, Country: "US", RegionId: 1001}, + 900001: {UserId: 900001, Status: userv1.UserStatus_USER_STATUS_ACTIVE, DisplayUserId: "163006", Country: "CA", RegionId: 2002}, + }} + router := newManagerCenterTestRouterWithHostAdmin(&fakeWalletClient{}, &fakeUserHostClient{}, hostAdminClient, profileClient) + body := []byte(`{"command_id":"huwaa-mgr-bdleader-cross","target_user_id":"900001"}`) + request := httptest.NewRequest(http.MethodPost, "/api/v1/manager-center/bd-leaders", bytes.NewReader(body)) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "huwaa")) + request.Header.Set("X-Request-ID", "req-huwaa-manager-bdleader-cross") + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("Huwaa cross-country BD Leader status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if req := hostAdminClient.lastCreateBDLeader; req == nil || req.GetMeta().GetAppCode() != "huwaa" || req.GetAdminUserId() != 42 || req.GetTargetUserId() != 900001 { + t.Fatalf("Huwaa cross-country target must reach app-scoped CreateBDLeader: %+v", req) + } +} + func TestTransferManagerUserCountryUsesAdminCountryChangeWithoutSameCountryFilter(t *testing.T) { profileClient := &fakeUserProfileClient{usersByID: map[int64]*userv1.User{ 42: {UserId: 42, Status: userv1.UserStatus_USER_STATUS_ACTIVE, Country: "US", RegionId: 1001}, diff --git a/services/gateway-service/internal/transport/http/managerapi/manager_center_handler.go b/services/gateway-service/internal/transport/http/managerapi/manager_center_handler.go index dffa3114..5f957388 100644 --- a/services/gateway-service/internal/transport/http/managerapi/manager_center_handler.go +++ b/services/gateway-service/internal/transport/http/managerapi/manager_center_handler.go @@ -30,8 +30,10 @@ const managerBlockUserCapability = "manager_block_user" const managerTransferUserCountryCapability = "manager_transfer_user_country" const managerGrantDayMS int64 = 24 * 60 * 60 * 1000 const managerGrantDefaultDurationMS int64 = 7 * managerGrantDayMS +const managerGrantVIPDurationMS int64 = 30 * managerGrantDayMS const managerGrantMaxResourceIDs = 20 const managerGrantMaxVIPLevel int32 = 5 +const huwaaAppCode = "huwaa" type managerGrantResourceData struct { ResourceID string `json:"resource_id"` @@ -166,16 +168,19 @@ func (h *Handler) searchManagerUsers(writer http.ResponseWriter, request *http.R return } // 搜索先走已有 business lookup 保持短号/昵称解析一致,再用 BatchGetUsers 拿国家和等级投影做最终过滤。 - // 只有国家转移入口显式带 scope=all 且经理拥有对应开关时,才允许跨国家搜索;其他动作继续默认同国家。 + // 国家转移依赖显式 scope=all 和权限;Huwaa 的 add-bd-leader 是唯一无需该权限即可跨国家选人的角色例外。 actor, ok := h.requireManagerCenterActor(writer, request) if !ok { return } scope := strings.ToLower(strings.TrimSpace(request.URL.Query().Get("scope"))) - allCountries := scope == "all" - if allCountries && !h.requireManagerCapability(writer, request, managerTransferUserCountryCapability) { + requestedAllCountries := scope == "all" + // Huwaa 的 BD Leader 拓展不受区域/国家边界限制;例外只绑定 add-bd-leader 场景,资源发放等高风险动作仍保持同国家。 + bdLeaderCrossRegion := huwaaBDLeaderSearchRegionUnrestricted(request) + if requestedAllCountries && !bdLeaderCrossRegion && !h.requireManagerCapability(writer, request, managerTransferUserCountryCapability) { return } + allCountries := requestedAllCountries || bdLeaderCrossRegion pageSize, ok := httpkit.PositiveInt32Query(request, "page_size", 20) if !ok { httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") @@ -460,7 +465,8 @@ func (h *Handler) grantManagerVIP(writer http.ResponseWriter, request *http.Requ if !h.requireManagerCapability(writer, request, managerGrantVIPCapability) { return } - // 经理中心复用后台 VIP 发放账务能力,但 source 固定为 manager_center,钱包侧据此保留统一 IM/outbox 行为。 + // 经理中心先读取 App 级 program,再选择直接会员或体验卡专用命令。钱包会在写事务内再次校验, + // 因此配置在两次 RPC 之间切换时只会明确失败,不会绕过当前发放语义。 if _, ok := h.requireSameCountryTarget(writer, request, targetUserID); !ok { return } @@ -468,9 +474,63 @@ func (h *Handler) grantManagerVIP(writer http.ResponseWriter, request *http.Requ if reason == "" { reason = "manager_center" } + appCode := appcode.FromContext(request.Context()) + programResp, err := h.walletClient.GetVipProgramConfig(request.Context(), &walletv1.GetVipProgramConfigRequest{ + RequestId: httpkit.RequestIDFromContext(request.Context()), + AppCode: appCode, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + program := programResp.GetConfig() + if program == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + if program.GetGrantMode() == "trial_card" { + if !program.GetTrialCardEnabled() { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + resp, err := h.walletClient.GrantVipTrialCard(request.Context(), &walletv1.GrantVipTrialCardRequest{ + CommandId: commandID, + AppCode: appCode, + TargetUserId: targetUserID, + Level: body.Level, + DurationMs: managerGrantVIPDurationMS, + GrantSource: "manager_center", + OperatorUserId: auth.UserIDFromContext(request.Context()), + Reason: reason, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + card := resp.GetTrialCard() + httpkit.WriteOK(writer, request, map[string]any{ + "grant_mode": "trial_card", + "transaction_id": "", + "trial_card_id": card.GetTrialCardId(), + "entitlement_id": card.GetEntitlementId(), + "source_grant_id": card.GetSourceGrantId(), + "level": card.GetLevel(), + // 发卡只入背包且从发卡时开始绝对计时;active=false 明确表示未直接激活会员。 + "active": false, + "card_status": card.GetStatus(), + "equipped": card.GetEquipped(), + "expires_at_ms": card.GetExpiresAtMs(), + "server_time_ms": resp.GetServerTimeMs(), + }) + return + } + if program.GetGrantMode() != "direct_membership" { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } resp, err := h.walletClient.GrantVip(request.Context(), &walletv1.GrantVipRequest{ CommandId: commandID, - AppCode: appcode.FromContext(request.Context()), + AppCode: appCode, TargetUserId: targetUserID, Level: body.Level, GrantSource: "manager_center", @@ -482,6 +542,7 @@ func (h *Handler) grantManagerVIP(writer http.ResponseWriter, request *http.Requ return } httpkit.WriteOK(writer, request, map[string]any{ + "grant_mode": "direct_membership", "transaction_id": resp.GetTransactionId(), "level": resp.GetVip().GetLevel(), "active": resp.GetVip().GetActive(), @@ -711,9 +772,13 @@ func (h *Handler) createManagerBDLeader(writer http.ResponseWriter, request *htt httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") return } - // manager-center 的搜索接口已经按同国家过滤,但写入口必须重新读取目标用户做权限判定。 - // 这样即使 H5 被篡改直接提交 target_user_id,也不能把跨国家用户提升为 BD Leader。 - target, ok := h.requireSameCountryTargetWithActor(writer, request, actor, targetUserID) + // 写入口必须重新读取 active 目标用户;Huwaa 只取消区域/国家匹配,经理身份和 add-bd-leader 能力仍在上方强制校验。 + var target *userv1.User + if huwaaRoleRegionUnrestricted(request) { + target, ok = h.requireActiveTarget(writer, request, targetUserID) + } else { + target, ok = h.requireSameCountryTargetWithActor(writer, request, actor, targetUserID) + } if !ok { return } @@ -889,6 +954,19 @@ func (h *Handler) requireSameCountryTarget(writer http.ResponseWriter, request * } func (h *Handler) requireSameCountryTargetWithActor(writer http.ResponseWriter, request *http.Request, actor *userv1.User, targetUserID int64) (*userv1.User, bool) { + target, ok := h.requireActiveTarget(writer, request, targetUserID) + if !ok { + return nil, false + } + if !sameCountry(actor.GetCountry(), target.GetCountry()) { + httpkit.WriteError(writer, request, http.StatusForbidden, httpkit.CodePermissionDenied, "permission denied") + return nil, false + } + return target, true +} + +// requireActiveTarget 是经理写入口共同的目标用户真实性门禁;区域策略只能决定后续是否比较国家,不能绕过 active 用户校验。 +func (h *Handler) requireActiveTarget(writer http.ResponseWriter, request *http.Request, targetUserID int64) (*userv1.User, bool) { targetResp, err := h.userProfileClient.GetUser(request.Context(), &userv1.GetUserRequest{ Meta: httpkit.UserMeta(request, ""), UserId: targetUserID, @@ -902,13 +980,17 @@ func (h *Handler) requireSameCountryTargetWithActor(writer http.ResponseWriter, httpkit.WriteError(writer, request, http.StatusNotFound, httpkit.CodeNotFound, "not found") return nil, false } - if !sameCountry(actor.GetCountry(), target.GetCountry()) { - httpkit.WriteError(writer, request, http.StatusForbidden, httpkit.CodePermissionDenied, "permission denied") - return nil, false - } return target, true } +func huwaaRoleRegionUnrestricted(request *http.Request) bool { + return request != nil && appcode.FromContext(request.Context()) == huwaaAppCode +} + +func huwaaBDLeaderSearchRegionUnrestricted(request *http.Request) bool { + return huwaaRoleRegionUnrestricted(request) && managerSearchScene(request) == managerAddBDLeaderCapability +} + func (h *Handler) managerPermissionOverview(request *http.Request) map[string]bool { permissions := map[string]bool{ "can_grant_avatar_frame": false, diff --git a/services/gateway-service/internal/transport/http/response_test.go b/services/gateway-service/internal/transport/http/response_test.go index 4ae838f5..9fbb4e2f 100644 --- a/services/gateway-service/internal/transport/http/response_test.go +++ b/services/gateway-service/internal/transport/http/response_test.go @@ -458,9 +458,12 @@ type fakeUserCountryQueryClient struct { } type fakeUserRegionClient struct { - last *userv1.GetRegionRequest - resp *userv1.RegionResponse - err error + lastList *userv1.ListRegionsRequest + listResp *userv1.ListRegionsResponse + listErr error + last *userv1.GetRegionRequest + resp *userv1.RegionResponse + err error } type fakeUserHostClient struct { @@ -617,11 +620,29 @@ type fakeWalletClient struct { vipPackagesResp *walletv1.ListVipPackagesResponse lastMyVip *walletv1.GetMyVipRequest myVipResp *walletv1.GetMyVipResponse + lastUpdateVIPSettings *walletv1.UpdateMyVipSettingsRequest + updateVIPSettingsResp *walletv1.UpdateMyVipSettingsResponse vipErr error + lastVipProgram *walletv1.GetVipProgramConfigRequest + vipProgramResp *walletv1.GetVipProgramConfigResponse + lastBenefitCheck *walletv1.CheckVipBenefitRequest + benefitCheckResp *walletv1.CheckVipBenefitResponse lastPurchaseVip *walletv1.PurchaseVipRequest purchaseVipResp *walletv1.PurchaseVipResponse lastGrantVip *walletv1.GrantVipRequest grantVipResp *walletv1.GrantVipResponse + lastTrialGrant *walletv1.GrantVipTrialCardRequest + trialGrantResp *walletv1.GrantVipTrialCardResponse + lastTrialEquip *walletv1.EquipVipTrialCardRequest + trialEquipResp *walletv1.EquipVipTrialCardResponse + lastTrialUnequip *walletv1.UnequipVipTrialCardRequest + trialUnequipResp *walletv1.UnequipVipTrialCardResponse + lastCurrentVIPRebate *walletv1.GetMyCurrentVipDailyCoinRebateRequest + currentVIPRebateResp *walletv1.GetMyCurrentVipDailyCoinRebateResponse + lastVIPRebateStatuses *walletv1.ListMyVipDailyCoinRebateStatusesRequest + vipRebateStatusesResp *walletv1.ListMyVipDailyCoinRebateStatusesResponse + lastClaimVIPRebate *walletv1.ClaimVipDailyCoinRebateRequest + claimVIPRebateResp *walletv1.ClaimVipDailyCoinRebateResponse lastTransfer *walletv1.TransferCoinFromSellerRequest transferResp *walletv1.TransferCoinFromSellerResponse transferErr error @@ -787,6 +808,7 @@ type fakeUserCPClient struct { } type fakeBroadcastClient struct { + lastGlobal *activityv1.PublishGlobalBroadcastRequest lastRemove *activityv1.RemoveRegionBroadcastMemberRequest err error } @@ -1438,6 +1460,18 @@ func (f *fakeUserCountryQueryClient) ListLoginRiskBlockedCountries(_ context.Con return &userv1.ListLoginRiskBlockedCountriesResponse{}, nil } +func (f *fakeUserRegionClient) ListRegions(_ context.Context, req *userv1.ListRegionsRequest) (*userv1.ListRegionsResponse, error) { + f.lastList = req + if f.listErr != nil { + return nil, f.listErr + } + if f.listResp != nil { + return f.listResp, nil + } + + return &userv1.ListRegionsResponse{}, nil +} + func (f *fakeUserRegionClient) GetRegion(_ context.Context, req *userv1.GetRegionRequest) (*userv1.RegionResponse, error) { f.last = req if f.err != nil { @@ -1637,6 +1671,14 @@ func (f *fakeUserCPClient) CancelBreakCPRelationship(context.Context, *userv1.Ca return &userv1.CancelBreakCPRelationshipResponse{}, nil } +func (f *fakeBroadcastClient) PublishGlobalBroadcast(_ context.Context, req *activityv1.PublishGlobalBroadcastRequest) (*activityv1.PublishBroadcastResponse, error) { + f.lastGlobal = req + if f.err != nil { + return nil, f.err + } + return &activityv1.PublishBroadcastResponse{EventId: req.GetEventId(), GroupId: "hy_fami_bc_g_v2", Status: "pending", Created: true}, nil +} + func (f *fakeBroadcastClient) RemoveRegionBroadcastMember(_ context.Context, req *activityv1.RemoveRegionBroadcastMemberRequest) (*activityv1.RemoveRegionBroadcastMemberResponse, error) { f.lastRemove = req if f.err != nil { @@ -2299,6 +2341,42 @@ func (f *fakeWalletClient) GetMyVip(_ context.Context, req *walletv1.GetMyVipReq return &walletv1.GetMyVipResponse{Vip: &walletv1.UserVip{UserId: req.GetUserId()}}, nil } +func (f *fakeWalletClient) UpdateMyVipSettings(_ context.Context, req *walletv1.UpdateMyVipSettingsRequest) (*walletv1.UpdateMyVipSettingsResponse, error) { + f.lastUpdateVIPSettings = req + if f.vipErr != nil { + return nil, f.vipErr + } + if f.updateVIPSettingsResp != nil { + return f.updateVIPSettingsResp, nil + } + return &walletv1.UpdateMyVipSettingsResponse{}, nil +} + +func (f *fakeWalletClient) GetVipProgramConfig(_ context.Context, req *walletv1.GetVipProgramConfigRequest) (*walletv1.GetVipProgramConfigResponse, error) { + f.lastVipProgram = req + if f.vipErr != nil { + return nil, f.vipErr + } + if f.vipProgramResp != nil { + return f.vipProgramResp, nil + } + // 多数既有 gateway 测试建模 Lalu;明确返回 legacy direct,避免测试桩用空配置掩盖真实路由分支。 + return &walletv1.GetVipProgramConfigResponse{Config: &walletv1.VipProgramConfig{ + AppCode: req.GetAppCode(), GrantMode: "direct_membership", Status: "active", + }}, nil +} + +func (f *fakeWalletClient) CheckVipBenefit(_ context.Context, req *walletv1.CheckVipBenefitRequest) (*walletv1.CheckVipBenefitResponse, error) { + f.lastBenefitCheck = req + if f.vipErr != nil { + return nil, f.vipErr + } + if f.benefitCheckResp != nil { + return f.benefitCheckResp, nil + } + return &walletv1.CheckVipBenefitResponse{}, nil +} + func (f *fakeWalletClient) PurchaseVip(_ context.Context, req *walletv1.PurchaseVipRequest) (*walletv1.PurchaseVipResponse, error) { f.lastPurchaseVip = req if f.vipErr != nil { @@ -2310,6 +2388,72 @@ func (f *fakeWalletClient) PurchaseVip(_ context.Context, req *walletv1.Purchase return &walletv1.PurchaseVipResponse{}, nil } +func (f *fakeWalletClient) GetMyCurrentVipDailyCoinRebate(_ context.Context, req *walletv1.GetMyCurrentVipDailyCoinRebateRequest) (*walletv1.GetMyCurrentVipDailyCoinRebateResponse, error) { + f.lastCurrentVIPRebate = req + if f.vipErr != nil { + return nil, f.vipErr + } + if f.currentVIPRebateResp != nil { + return f.currentVIPRebateResp, nil + } + return &walletv1.GetMyCurrentVipDailyCoinRebateResponse{}, nil +} + +func (f *fakeWalletClient) ListMyVipDailyCoinRebateStatuses(_ context.Context, req *walletv1.ListMyVipDailyCoinRebateStatusesRequest) (*walletv1.ListMyVipDailyCoinRebateStatusesResponse, error) { + f.lastVIPRebateStatuses = req + if f.vipErr != nil { + return nil, f.vipErr + } + if f.vipRebateStatusesResp != nil { + return f.vipRebateStatusesResp, nil + } + return &walletv1.ListMyVipDailyCoinRebateStatusesResponse{}, nil +} + +func (f *fakeWalletClient) ClaimVipDailyCoinRebate(_ context.Context, req *walletv1.ClaimVipDailyCoinRebateRequest) (*walletv1.ClaimVipDailyCoinRebateResponse, error) { + f.lastClaimVIPRebate = req + if f.vipErr != nil { + return nil, f.vipErr + } + if f.claimVIPRebateResp != nil { + return f.claimVIPRebateResp, nil + } + return &walletv1.ClaimVipDailyCoinRebateResponse{}, nil +} + +func (f *fakeWalletClient) GrantVipTrialCard(_ context.Context, req *walletv1.GrantVipTrialCardRequest) (*walletv1.GrantVipTrialCardResponse, error) { + f.lastTrialGrant = req + if f.vipErr != nil { + return nil, f.vipErr + } + if f.trialGrantResp != nil { + return f.trialGrantResp, nil + } + return &walletv1.GrantVipTrialCardResponse{}, nil +} + +func (f *fakeWalletClient) EquipVipTrialCard(_ context.Context, req *walletv1.EquipVipTrialCardRequest) (*walletv1.EquipVipTrialCardResponse, error) { + f.lastTrialEquip = req + if f.vipErr != nil { + return nil, f.vipErr + } + if f.trialEquipResp != nil { + return f.trialEquipResp, nil + } + return &walletv1.EquipVipTrialCardResponse{}, nil +} + +func (f *fakeWalletClient) UnequipVipTrialCard(_ context.Context, req *walletv1.UnequipVipTrialCardRequest) (*walletv1.UnequipVipTrialCardResponse, error) { + f.lastTrialUnequip = req + if f.vipErr != nil { + return nil, f.vipErr + } + if f.trialUnequipResp != nil { + return f.trialUnequipResp, nil + } + return &walletv1.UnequipVipTrialCardResponse{}, nil +} + func (f *fakeWalletClient) DebitCPBreakupFee(context.Context, *walletv1.DebitCPBreakupFeeRequest) (*walletv1.DebitCPBreakupFeeResponse, error) { return &walletv1.DebitCPBreakupFeeResponse{}, nil } @@ -3305,8 +3449,9 @@ func TestJoinRoomReturnsInitialDataWithIMGroupRTCTokenAndProfiles(t *testing.T) defer func() { roomapi.TimeNow = previousNow }() roomClient := &fakeRoomClient{joinResp: &roomv1.JoinRoomResponse{ - Result: &roomv1.CommandResult{Applied: true, RoomVersion: 7, ServerTimeMs: 1_700_000_000_123}, - User: &roomv1.RoomUser{UserId: 42, Role: "audience", JoinedAtMs: 1_700_000_000_000, LastSeenAtMs: 1_700_000_000_100}, + Result: &roomv1.CommandResult{Applied: true, RoomVersion: 7, ServerTimeMs: 1_700_000_000_123}, + User: &roomv1.RoomUser{UserId: 42, Role: "audience", JoinedAtMs: 1_700_000_000_000, LastSeenAtMs: 1_700_000_000_100}, + EffectiveVip: &roomv1.RoomEffectiveVipSnapshot{ProgramType: "tiered_privilege_v1", Level: 8, Name: "VIP8", RoomEntryNoticeEnabled: true}, Room: &roomv1.RoomSnapshot{ RoomId: "room_1001", OwnerUserId: 101, @@ -3422,6 +3567,10 @@ func TestJoinRoomReturnsInitialDataWithIMGroupRTCTokenAndProfiles(t *testing.T) if roomClient.lastJoin == nil || roomClient.lastJoin.GetPassword() != "1234" { t.Fatalf("join must forward room password to room-service: %+v", roomClient.lastJoin) } + effectiveVIP := data["effective_vip"].(map[string]any) + if effectiveVIP["program_type"] != "tiered_privilege_v1" || effectiveVIP["level"] != float64(8) || effectiveVIP["name"] != "VIP8" || effectiveVIP["room_entry_notice_enabled"] != true { + t.Fatalf("join response must expose room effective VIP snapshot: %+v", effectiveVIP) + } joinProfile := roomClient.lastJoin.GetActorDisplayProfile() if joinProfile.GetUserId() != 42 || joinProfile.GetNickname() != "hy" || joinProfile.GetAvatar() != "https://cdn.example/avatar.png" || joinProfile.GetDisplayUserId() != "100001" { t.Fatalf("join must inject actor display profile snapshot: %+v", joinProfile) @@ -3650,6 +3799,242 @@ func TestListRoomsUsesUserRegionFromUserService(t *testing.T) { } } +func TestListRoomsHuwaaDefaultsToAllRegionsAndSupportsValidatedFilters(t *testing.T) { + newHandler := func(regionClient *fakeUserRegionClient, countryClient *fakeUserCountryQueryClient, queryClient *fakeRoomQueryClient) http.Handler { + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, &fakeUserProfileClient{regionID: 1001}) + handler.SetRoomQueryClient(queryClient) + handler.SetUserRegionClient(regionClient) + handler.SetUserCountryQueryClient(countryClient) + return handler.Routes(auth.NewVerifier("secret")) + } + currentRegion := &userv1.RegionResponse{Region: &userv1.Region{ + RegionId: 1001, RegionCode: "ME", Status: "active", Countries: []string{"US", "AE"}, + }} + activeRegions := &userv1.ListRegionsResponse{Regions: []*userv1.Region{ + {RegionId: 1001, RegionCode: "ME", Status: "active", Countries: []string{"US", "AE"}}, + {RegionId: 2002, RegionCode: "SEA", Status: "active", Countries: []string{"BD", "PK"}}, + }} + registrationCountries := &userv1.ListRegistrationCountriesResponse{Countries: []*userv1.Country{ + {CountryId: 1, CountryCode: "US"}, + {CountryId: 2, CountryCode: "AE"}, + {CountryId: 3, CountryCode: "BD"}, + {CountryId: 4, CountryCode: "PK"}, + }} + + t.Run("all", func(t *testing.T) { + regionClient := &fakeUserRegionClient{resp: currentRegion} + queryClient := &fakeRoomQueryClient{} + router := newHandler(regionClient, &fakeUserCountryQueryClient{resp: registrationCountries}, queryClient) + request := httptest.NewRequest(http.MethodGet, "/api/v1/rooms?tab=hot", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "huwaa")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if queryClient.lastList == nil || !queryClient.lastList.GetAllVisibleRegions() || queryClient.lastList.GetFilterRegionId() != 0 || queryClient.lastList.GetVisibleRegionId() != 1001 { + t.Fatalf("Huwaa All must preserve viewer region only as sort context and query every region: %+v", queryClient.lastList) + } + if regionClient.lastList != nil { + t.Fatalf("All needs no catalog validation RPC: %+v", regionClient.lastList) + } + }) + + t.Run("region", func(t *testing.T) { + regionClient := &fakeUserRegionClient{resp: currentRegion, listResp: activeRegions} + queryClient := &fakeRoomQueryClient{} + router := newHandler(regionClient, &fakeUserCountryQueryClient{resp: registrationCountries}, queryClient) + request := httptest.NewRequest(http.MethodGet, "/api/v1/rooms?region_id=2002", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "huwaa")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if queryClient.lastList == nil || queryClient.lastList.GetAllVisibleRegions() || queryClient.lastList.GetFilterRegionId() != 2002 || queryClient.lastList.GetVisibleRegionId() != 2002 { + t.Fatalf("validated Huwaa region filter mismatch: %+v", queryClient.lastList) + } + if regionClient.lastList == nil || regionClient.lastList.GetStatus() != "active" { + t.Fatalf("region filter must resolve against active catalog: %+v", regionClient.lastList) + } + }) + + t.Run("country", func(t *testing.T) { + regionClient := &fakeUserRegionClient{resp: currentRegion, listResp: activeRegions} + queryClient := &fakeRoomQueryClient{} + router := newHandler(regionClient, &fakeUserCountryQueryClient{resp: registrationCountries}, queryClient) + request := httptest.NewRequest(http.MethodGet, "/api/v1/rooms?country_code=BD", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "huwaa")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if queryClient.lastList == nil || !queryClient.lastList.GetAllVisibleRegions() || queryClient.lastList.GetCountryCode() != "BD" || queryClient.lastList.GetFilterRegionId() != 0 { + t.Fatalf("validated Huwaa country filter mismatch: %+v", queryClient.lastList) + } + }) + + t.Run("country_without_active_region_mapping", func(t *testing.T) { + regionClient := &fakeUserRegionClient{resp: currentRegion, listResp: activeRegions} + queryClient := &fakeRoomQueryClient{} + countries := &userv1.ListRegistrationCountriesResponse{Countries: append(append([]*userv1.Country{}, registrationCountries.GetCountries()...), &userv1.Country{CountryId: 5, CountryCode: "CN"})} + router := newHandler(regionClient, &fakeUserCountryQueryClient{resp: countries}, queryClient) + request := httptest.NewRequest(http.MethodGet, "/api/v1/rooms?country_code=CN", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "huwaa")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusBadRequest || queryClient.lastList != nil { + t.Fatalf("unmapped country must be rejected before room-service: status=%d req=%+v body=%s", recorder.Code, queryClient.lastList, recorder.Body.String()) + } + }) + + t.Run("region_outside_active_catalog", func(t *testing.T) { + regionClient := &fakeUserRegionClient{resp: currentRegion, listResp: activeRegions} + queryClient := &fakeRoomQueryClient{} + router := newHandler(regionClient, &fakeUserCountryQueryClient{resp: registrationCountries}, queryClient) + request := httptest.NewRequest(http.MethodGet, "/api/v1/rooms?region_id=9999", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "huwaa")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusBadRequest || queryClient.lastList != nil { + t.Fatalf("unknown region must be rejected before room-service: status=%d req=%+v body=%s", recorder.Code, queryClient.lastList, recorder.Body.String()) + } + }) +} + +func TestListRoomsHuwaaAllowsAllAndCatalogFiltersWithoutViewerRegion(t *testing.T) { + activeRegions := &userv1.ListRegionsResponse{Regions: []*userv1.Region{ + {RegionId: 2002, RegionCode: "SEA", Status: "active", Countries: []string{"BD"}}, + }} + registrationCountries := &userv1.ListRegistrationCountriesResponse{Countries: []*userv1.Country{ + {CountryId: 3, CountryCode: "BD"}, + }} + tests := []struct { + name string + path string + wantAll bool + wantRegion int64 + wantVisibleRegion int64 + wantCountry string + }{ + {name: "all", path: "/api/v1/rooms", wantAll: true}, + {name: "region", path: "/api/v1/rooms?region_id=2002", wantRegion: 2002, wantVisibleRegion: 2002}, + {name: "country", path: "/api/v1/rooms?country_code=BD", wantAll: true, wantCountry: "BD"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + profileClient := &fakeUserProfileClient{usersByID: map[int64]*userv1.User{ + 42: {UserId: 42, Country: "US", RegionId: 0}, + }} + regionClient := &fakeUserRegionClient{listResp: activeRegions} + countryClient := &fakeUserCountryQueryClient{resp: registrationCountries} + queryClient := &fakeRoomQueryClient{} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetRoomQueryClient(queryClient) + handler.SetUserRegionClient(regionClient) + handler.SetUserCountryQueryClient(countryClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, tt.path, nil) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "huwaa")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if queryClient.lastList == nil || queryClient.lastList.GetVisibleRegionId() != tt.wantVisibleRegion || queryClient.lastList.GetAllVisibleRegions() != tt.wantAll || queryClient.lastList.GetFilterRegionId() != tt.wantRegion || queryClient.lastList.GetCountryCode() != tt.wantCountry { + t.Fatalf("regionless Huwaa list scope mismatch: %+v", queryClient.lastList) + } + if regionClient.last != nil { + t.Fatalf("regionless Huwaa user must not trigger GetRegion or guess a legacy region: %+v", regionClient.last) + } + var envelope httpkit.ResponseEnvelope + if err := json.NewDecoder(recorder.Body).Decode(&envelope); err != nil { + t.Fatalf("decode room list response failed: %v", err) + } + if rawCountries, exists := envelope.Data.(map[string]any)["countries"]; exists { + if countries, ok := rawCountries.([]any); !ok || len(countries) != 0 { + t.Fatalf("regionless Huwaa legacy countries must stay empty: %+v", rawCountries) + } + } + }) + } +} + +func TestListRoomsRejectsConflictingFiltersAndKeepsNonHuwaaRegionIsolation(t *testing.T) { + t.Run("conflicting_huwaa_filters", func(t *testing.T) { + queryClient := &fakeRoomQueryClient{} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, &fakeUserProfileClient{regionID: 1001}) + handler.SetRoomQueryClient(queryClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, "/api/v1/rooms?region_id=2002&country_code=BD", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "huwaa")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusBadRequest || queryClient.lastList != nil { + t.Fatalf("conflicting filters must fail before upstream calls: status=%d req=%+v body=%s", recorder.Code, queryClient.lastList, recorder.Body.String()) + } + }) + + t.Run("non_huwaa_region_filter", func(t *testing.T) { + profileClient := &fakeUserProfileClient{regionID: 1001} + regionClient := &fakeUserRegionClient{resp: &userv1.RegionResponse{Region: &userv1.Region{RegionId: 1001, Countries: []string{"US"}}}} + countryClient := &fakeUserCountryQueryClient{resp: &userv1.ListRegistrationCountriesResponse{Countries: []*userv1.Country{{CountryId: 1, CountryCode: "US"}}}} + queryClient := &fakeRoomQueryClient{} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetRoomQueryClient(queryClient) + handler.SetUserRegionClient(regionClient) + handler.SetUserCountryQueryClient(countryClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, "/api/v1/rooms?region_id=2002", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "lalu")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusBadRequest || queryClient.lastList != nil { + t.Fatalf("non-Huwaa region filter must not bypass current-region isolation: status=%d req=%+v body=%s", recorder.Code, queryClient.lastList, recorder.Body.String()) + } + }) + + t.Run("non_huwaa_missing_viewer_region", func(t *testing.T) { + profileClient := &fakeUserProfileClient{usersByID: map[int64]*userv1.User{ + 42: {UserId: 42, Country: "US", RegionId: 0}, + }} + regionClient := &fakeUserRegionClient{} + countryClient := &fakeUserCountryQueryClient{} + queryClient := &fakeRoomQueryClient{} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetRoomQueryClient(queryClient) + handler.SetUserRegionClient(regionClient) + handler.SetUserCountryQueryClient(countryClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, "/api/v1/rooms", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "lalu")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusBadRequest || queryClient.lastList != nil || regionClient.last != nil || countryClient.last != nil { + t.Fatalf("non-Huwaa missing region must keep the previous fail-closed behavior: status=%d req=%+v body=%s", recorder.Code, queryClient.lastList, recorder.Body.String()) + } + }) +} + func TestGetRoomRocketEmbedsRewardResourceGroups(t *testing.T) { queryClient := &fakeRoomQueryClient{rocketResp: &roomv1.GetRoomRocketResponse{ Rocket: &roomv1.RoomRocketInfo{ diff --git a/services/gateway-service/internal/transport/http/room_filter_handler_test.go b/services/gateway-service/internal/transport/http/room_filter_handler_test.go new file mode 100644 index 00000000..1efe9e8a --- /dev/null +++ b/services/gateway-service/internal/transport/http/room_filter_handler_test.go @@ -0,0 +1,148 @@ +package http + +import ( + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + userv1 "hyapp.local/api/proto/user/v1" + "hyapp/services/gateway-service/internal/auth" + "hyapp/services/gateway-service/internal/transport/http/httpkit" +) + +func TestListRoomFiltersReturnsAllAppScopedFiltersForHuwaa(t *testing.T) { + regionClient := &fakeUserRegionClient{listResp: &userv1.ListRegionsResponse{Regions: []*userv1.Region{ + {RegionId: 1001, RegionCode: "MIDDLE_EAST", Name: "Middle East", Status: "active", Countries: []string{"AE", "SA"}, SortOrder: 10}, + {RegionId: 1002, RegionCode: "SOUTH_ASIA", Name: "South Asia", Status: "active", Countries: []string{"PK"}, SortOrder: 20}, + // 即使上游违反 status 过滤契约返回禁用区域,gateway 也不能把不可用筛选值下发给 Flutter。 + {RegionId: 1003, RegionCode: "INDIA", Name: "India", Status: "disabled", Countries: []string{"IN"}, SortOrder: 30}, + }}} + countryClient := &fakeUserCountryQueryClient{resp: &userv1.ListRegistrationCountriesResponse{Countries: []*userv1.Country{ + {CountryId: 971, CountryCode: "ae", CountryName: "United Arab Emirates", CountryDisplayName: "UAE", Flag: "🇦🇪", SortOrder: 10}, + {CountryId: 966, CountryCode: "SA", CountryName: "Saudi Arabia", CountryDisplayName: "Saudi Arabia", SortOrder: 20}, + {CountryId: 92, CountryCode: "PK", CountryName: "Pakistan", CountryDisplayName: "Pakistan", Flag: "🇵🇰", SortOrder: 30}, + // Enabled 但未配置 active 业务区域的国家不能成为可回传筛选项。 + {CountryId: 95, CountryCode: "MM", CountryName: "Myanmar", CountryDisplayName: "Myanmar", Flag: "🇲🇲", SortOrder: 40}, + {CountryId: 91, CountryCode: "IN", CountryName: "India", CountryDisplayName: "India", Flag: "🇮🇳", SortOrder: 50}, + }}} + profileClient := &fakeUserProfileClient{} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetUserRegionClient(regionClient) + handler.SetUserCountryQueryClient(countryClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, "/api/v1/rooms/filters", nil) + request.Header.Set("X-App-Code", "huwaa") + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "huwaa")) + request.Header.Set("X-Request-ID", "req-room-filters") + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if regionClient.lastList == nil || regionClient.lastList.GetStatus() != "active" || regionClient.lastList.GetMeta().GetAppCode() != "huwaa" { + t.Fatalf("region query must be active and app-scoped: %+v", regionClient.lastList) + } + if countryClient.last == nil || countryClient.last.GetMeta().GetAppCode() != "huwaa" { + t.Fatalf("country query must use the same app scope: %+v", countryClient.last) + } + if profileClient.lastGet != nil || regionClient.last != nil { + t.Fatalf("Huwaa catalog must read all active regions without narrowing to the viewer: profile=%+v region=%+v", profileClient.lastGet, regionClient.last) + } + + var response httpkit.ResponseEnvelope + if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil { + t.Fatalf("decode room filter response failed: %v", err) + } + if response.Code != httpkit.CodeOK { + t.Fatalf("unexpected envelope: %+v", response) + } + data := response.Data.(map[string]any) + all := data["all"].(map[string]any) + if all["filter_type"] != "all" || all["query_key"] != "" || all["query_value"] != "" { + t.Fatalf("all filter mismatch: %+v", all) + } + regions := data["regions"].([]any) + if len(regions) != 2 || regions[0].(map[string]any)["region_id"] != float64(1001) || regions[0].(map[string]any)["query_key"] != "region_id" || regions[0].(map[string]any)["query_value"] != "1001" || regions[1].(map[string]any)["region_code"] != "SOUTH_ASIA" { + t.Fatalf("region filters mismatch: %+v", regions) + } + countries := data["countries"].([]any) + if len(countries) != 3 { + t.Fatalf("country filters mismatch: %+v", countries) + } + ae := countries[0].(map[string]any) + if ae["filter_type"] != "country" || ae["query_key"] != "country_code" || ae["query_value"] != "AE" || ae["country_code"] != "AE" || ae["parent_region_id"] != float64(1001) || ae["country_flag"] != "🇦🇪" { + t.Fatalf("mapped country filter mismatch: %+v", ae) + } + sa := countries[1].(map[string]any) + if sa["country_flag"] != "🇸🇦" { + t.Fatalf("empty upstream flag must use ISO flag fallback: %+v", sa) + } + for _, item := range countries { + if code := item.(map[string]any)["country_code"]; code == "MM" || code == "IN" { + t.Fatalf("country without an active region mapping must not become a filter: %+v", countries) + } + } +} + +func TestListRoomFiltersKeepsNonHuwaaInsideCurrentUserRegion(t *testing.T) { + profileClient := &fakeUserProfileClient{regionID: 1002} + regionClient := &fakeUserRegionClient{resp: &userv1.RegionResponse{Region: &userv1.Region{ + RegionId: 1002, RegionCode: "SOUTH_ASIA", Name: "South Asia", Status: "active", Countries: []string{"PK"}, SortOrder: 20, + }}} + countryClient := &fakeUserCountryQueryClient{resp: &userv1.ListRegistrationCountriesResponse{Countries: []*userv1.Country{ + {CountryId: 971, CountryCode: "AE", CountryName: "United Arab Emirates"}, + {CountryId: 92, CountryCode: "PK", CountryName: "Pakistan", Flag: "🇵🇰"}, + }}} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetUserRegionClient(regionClient) + handler.SetUserCountryQueryClient(countryClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, "/api/v1/rooms/filters", nil) + request.Header.Set("X-App-Code", "lalu") + request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if regionClient.lastList != nil || profileClient.lastGet == nil || profileClient.lastGet.GetUserId() != 42 || regionClient.last == nil || regionClient.last.GetRegionId() != 1002 { + t.Fatalf("non-Huwaa catalog must resolve only the viewer region: list=%+v user=%+v region=%+v", regionClient.lastList, profileClient.lastGet, regionClient.last) + } + var response httpkit.ResponseEnvelope + if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil { + t.Fatalf("decode room filter response failed: %v", err) + } + data := response.Data.(map[string]any) + regions := data["regions"].([]any) + countries := data["countries"].([]any) + if len(regions) != 1 || regions[0].(map[string]any)["region_id"] != float64(1002) || len(countries) != 1 || countries[0].(map[string]any)["country_code"] != "PK" { + t.Fatalf("non-Huwaa filter scope leaked another region or country: regions=%+v countries=%+v", regions, countries) + } +} + +func TestListRoomFiltersRejectsNonGETWithoutCallingUserService(t *testing.T) { + regionClient := &fakeUserRegionClient{} + countryClient := &fakeUserCountryQueryClient{} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, &fakeUserProfileClient{}) + handler.SetUserRegionClient(regionClient) + handler.SetUserCountryQueryClient(countryClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodPost, "/api/v1/rooms/filters", nil) + request.Header.Set("X-App-Code", "huwaa") + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "huwaa")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusMethodNotAllowed { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if regionClient.lastList != nil || countryClient.last != nil { + t.Fatalf("invalid method must not call user-service: region=%+v country=%+v", regionClient.lastList, countryClient.last) + } +} diff --git a/services/gateway-service/internal/transport/http/roomapi/handler.go b/services/gateway-service/internal/transport/http/roomapi/handler.go index de4f8e3d..d331202f 100644 --- a/services/gateway-service/internal/transport/http/roomapi/handler.go +++ b/services/gateway-service/internal/transport/http/roomapi/handler.go @@ -75,6 +75,7 @@ func (h *Handler) RoomHandlers() httproutes.RoomHandlers { return httproutes.RoomHandlers{ GetMyRoom: h.getMyRoom, ListRoomFeeds: h.listRoomFeeds, + ListRoomFilters: h.listRoomFilters, ListRooms: h.listRooms, GetCurrentRoom: h.getCurrentRoom, GetRoomSnapshot: h.getRoomSnapshot, diff --git a/services/gateway-service/internal/transport/http/roomapi/room_filter_handler.go b/services/gateway-service/internal/transport/http/roomapi/room_filter_handler.go new file mode 100644 index 00000000..00d4a7fd --- /dev/null +++ b/services/gateway-service/internal/transport/http/roomapi/room_filter_handler.go @@ -0,0 +1,186 @@ +package roomapi + +import ( + "net/http" + "strconv" + "strings" + + "hyapp/pkg/appcode" + "hyapp/services/gateway-service/internal/auth" + "hyapp/services/gateway-service/internal/transport/http/httpkit" + + userv1 "hyapp.local/api/proto/user/v1" +) + +const ( + roomFilterTypeAll = "all" + roomFilterTypeRegion = "region" + roomFilterTypeCountry = "country" + roomFilterAllRegionsAppCode = "huwaa" + + // 区域筛选目录只暴露当前可用的业务区域;禁用区域继续保留在后台治理面,不下发给客户端。 + roomFilterRegionStatusActive = "active" +) + +// roomFilterCatalogData 是首页筛选控件的稳定目录。 +// filter_type 告诉 Flutter 应读取哪个查询字段:region 使用 region_id,country 使用 country_code,all 不传两者。 +type roomFilterCatalogData struct { + All roomAllFilterData `json:"all"` + Regions []roomRegionFilterData `json:"regions"` + Countries []roomCountryFilterData `json:"countries"` +} + +type roomAllFilterData struct { + FilterType string `json:"filter_type"` + QueryKey string `json:"query_key"` + QueryValue string `json:"query_value"` +} + +type roomRegionFilterData struct { + FilterType string `json:"filter_type"` + QueryKey string `json:"query_key"` + QueryValue string `json:"query_value"` + RegionID int64 `json:"region_id"` + RegionCode string `json:"region_code"` + RegionName string `json:"region_name"` + SortOrder int32 `json:"sort_order"` +} + +type roomCountryFilterData struct { + FilterType string `json:"filter_type"` + QueryKey string `json:"query_key"` + QueryValue string `json:"query_value"` + ParentRegionID int64 `json:"parent_region_id,omitempty"` + CountryID int64 `json:"country_id"` + CountryCode string `json:"country_code"` + CountryName string `json:"country_name"` + CountryDisplayName string `json:"country_display_name"` + CountryFlag string `json:"country_flag"` + SortOrder int32 `json:"sort_order"` +} + +// listRoomFilters 返回当前 App 可用的首页区域/国家筛选目录。 +// Huwaa 已开放跨区域浏览,因此返回全部 active 区域;其他 App 继续只返回当前用户区域,避免下发不可用的跨区值。 +func (h *Handler) listRoomFilters(writer http.ResponseWriter, request *http.Request) { + if h.userRegionClient == nil || h.userCountryClient == nil || (appcode.FromContext(request.Context()) != roomFilterAllRegionsAppCode && h.userProfileClient == nil) { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + + regions, err := h.roomFilterRegions(request) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + countryResp, err := h.userCountryClient.ListRegistrationCountries(request.Context(), &userv1.ListRegistrationCountriesRequest{ + Meta: httpkit.UserMeta(request, ""), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + + httpkit.WriteOK(writer, request, roomFilterCatalogDataFromProto(regions, countryResp.GetCountries())) +} + +func (h *Handler) roomFilterRegions(request *http.Request) ([]*userv1.Region, error) { + if appcode.FromContext(request.Context()) == roomFilterAllRegionsAppCode { + resp, err := h.userRegionClient.ListRegions(request.Context(), &userv1.ListRegionsRequest{ + Meta: httpkit.UserMeta(request, ""), + Status: roomFilterRegionStatusActive, + }) + if err != nil { + return nil, err + } + return resp.GetRegions(), nil + } + userResp, err := h.userProfileClient.GetUser(request.Context(), &userv1.GetUserRequest{ + Meta: httpkit.UserMeta(request, ""), + UserId: auth.UserIDFromContext(request.Context()), + }) + if err != nil { + return nil, err + } + if userResp.GetUser().GetRegionId() <= 0 { + // GLOBAL 是内部兜底桶,不是客户端可选业务区域;All 仍表示该 App 原有的当前区域语义。 + return []*userv1.Region{}, nil + } + regionResp, err := h.userRegionClient.GetRegion(request.Context(), &userv1.GetRegionRequest{ + Meta: httpkit.UserMeta(request, ""), + RegionId: userResp.GetUser().GetRegionId(), + }) + if err != nil { + return nil, err + } + region := regionResp.GetRegion() + if region == nil || strings.TrimSpace(region.GetStatus()) != roomFilterRegionStatusActive { + return []*userv1.Region{}, nil + } + return []*userv1.Region{region}, nil +} + +func roomFilterCatalogDataFromProto(regions []*userv1.Region, countries []*userv1.Country) roomFilterCatalogData { + data := roomFilterCatalogData{ + // All 的 query_key/query_value 显式为空;Flutter 可用同一套 option 逻辑,并在 key 为空时不附加筛选参数。 + All: roomAllFilterData{FilterType: roomFilterTypeAll, QueryKey: "", QueryValue: ""}, + Regions: make([]roomRegionFilterData, 0, len(regions)), + Countries: make([]roomCountryFilterData, 0, len(countries)), + } + regionByCountry := make(map[string]int64) + for _, region := range regions { + if region == nil || region.GetRegionId() <= 0 || strings.TrimSpace(region.GetStatus()) != roomFilterRegionStatusActive { + continue + } + data.Regions = append(data.Regions, roomRegionFilterData{ + FilterType: roomFilterTypeRegion, + QueryKey: "region_id", + QueryValue: strconv.FormatInt(region.GetRegionId(), 10), + RegionID: region.GetRegionId(), + RegionCode: strings.TrimSpace(region.GetRegionCode()), + RegionName: strings.TrimSpace(region.GetName()), + SortOrder: region.GetSortOrder(), + }) + for _, rawCountryCode := range region.GetCountries() { + countryCode := normalizeRoomListCountryCode(rawCountryCode) + if countryCode == "" { + continue + } + if _, exists := regionByCountry[countryCode]; !exists { + // 正常数据中一个国家只能有一个 active 区域;若上游短暂异常,保留产品排序最靠前的区域以确保响应确定。 + regionByCountry[countryCode] = region.GetRegionId() + } + } + } + + for _, country := range countries { + if country == nil { + continue + } + countryCode := normalizeRoomListCountryCode(country.GetCountryCode()) + if countryCode == "" { + continue + } + parentRegionID, mapped := regionByCountry[countryCode] + if !mapped { + // 只有 enabled 国家与 active 区域映射同时成立时才是可回传筛选值,避免客户端提交无法归属业务区域的国家。 + continue + } + countryFlag := strings.TrimSpace(country.GetFlag()) + if countryFlag == "" { + countryFlag = roomProfileCountryFlag(countryCode) + } + data.Countries = append(data.Countries, roomCountryFilterData{ + FilterType: roomFilterTypeCountry, + QueryKey: "country_code", + QueryValue: countryCode, + ParentRegionID: parentRegionID, + CountryID: country.GetCountryId(), + CountryCode: countryCode, + CountryName: strings.TrimSpace(country.GetCountryName()), + CountryDisplayName: strings.TrimSpace(country.GetCountryDisplayName()), + CountryFlag: countryFlag, + SortOrder: country.GetSortOrder(), + }) + } + return data +} diff --git a/services/gateway-service/internal/transport/http/roomapi/room_handler.go b/services/gateway-service/internal/transport/http/roomapi/room_handler.go index 336d3ffa..a9e0a536 100644 --- a/services/gateway-service/internal/transport/http/roomapi/room_handler.go +++ b/services/gateway-service/internal/transport/http/roomapi/room_handler.go @@ -28,6 +28,8 @@ import ( const ( defaultRoomFeedRelationPageSize = 100 maxRoomFeedRelationScanCount = 500 + // Huwaa 首页的产品范围是全区;其他 App 继续沿用当前区域/白名单语义。 + huwaaRoomDiscoveryAppCode = "huwaa" // 房间展示资料只读取客户端能在首屏、公屏或资料卡直接渲染的当前佩戴资源。 roomAppearanceResourceAvatarFrame = "avatar_frame" @@ -80,7 +82,14 @@ type roomFeedRelationCursor struct { RoomID string `json:"room_id"` } -// listRooms 按当前登录用户的服务端 region_id 查询房间发现列表。 +// publicRoomListFilter 只表达 Flutter 从 /rooms/filters 原样回传的一种筛选。 +// RegionID 和 CountryCode 必须互斥;两者为空才表示 All。 +type publicRoomListFilter struct { + RegionID int64 + CountryCode string +} + +// listRooms 按 App 策略解析默认 All/当前区域,并校验 Flutter 回传的区域或国家筛选。 func (h *Handler) listRooms(writer http.ResponseWriter, request *http.Request) { limit, ok := parseRoomListLimit(request.URL.Query().Get("limit")) if !ok { @@ -92,6 +101,11 @@ func (h *Handler) listRooms(writer http.ResponseWriter, request *http.Request) { httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") return } + filter, ok := parsePublicRoomListFilter(request) + if !ok { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } if h.userProfileClient == nil || h.roomQueryClient == nil || h.userRegionClient == nil || h.userCountryClient == nil { // 列表入口必须同时依赖 user-service 用户区域、区域国家、国家主数据和 room-service 读模型。 httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") @@ -108,24 +122,70 @@ func (h *Handler) listRooms(writer http.ResponseWriter, request *http.Request) { httpkit.WriteRPCError(writer, request, err) return } - countries, err := h.roomListCountriesForUser(request, userResp.GetUser()) + appCode := appcode.FromContext(request.Context()) + if appCode != huwaaRoomDiscoveryAppCode && userResp.GetUser().GetRegionId() <= 0 { + // 非 Huwaa 仍以用户区域作为隔离边界;缺失时不能猜测或退化到 GLOBAL。 + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + countries, registrationCountries, err := h.roomListCountriesForUser(request, userResp.GetUser()) if err != nil { httpkit.WriteRPCError(writer, request, err) return } - countryCode, ok := roomListCountryQuery(request, countries) - if !ok { - httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") - return + allVisibleRegions := false + filterRegionID := int64(0) + countryCode := filter.CountryCode + if appCode == huwaaRoomDiscoveryAppCode { + switch { + case filter.RegionID > 0: + regions, err := h.roomListActiveRegions(request) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + if !roomListContainsActiveRegion(regions, filter.RegionID) { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + filterRegionID = filter.RegionID + case countryCode != "": + regions, err := h.roomListActiveRegions(request) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + if !roomListCatalogContainsCountry(regions, registrationCountries, countryCode) { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + // 国家项在 active 区域中有唯一归属,但查询按国家投影直接收敛,不再叠加区域条件。 + allVisibleRegions = true + default: + // Huwaa All 是产品默认页,不依赖运营白名单。 + allVisibleRegions = true + } + } else { + if filter.RegionID > 0 || !roomListCountryAllowed(countries, countryCode) { + // 非 Huwaa App 不开放客户端跨区筛选,国家也仍限当前用户区域。 + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + allVisibleRegions = h.roomRegionWhitelistAllows(request, viewerUserID) + } + queryRegionID := userResp.GetUser().GetRegionId() + if filterRegionID > 0 { + // 滚动发布期间旧 room-service 会忽略新 FilterRegionId;同时覆盖旧 VisibleRegionId 保证首页仍查选中区域。 + queryRegionID = filterRegionID } - allVisibleRegions := h.roomRegionWhitelistAllows(request, viewerUserID) resp, err := h.roomQueryClient.ListRooms(request.Context(), &roomv1.ListRoomsRequest{ Meta: httpkit.RoomMeta(request, "", ""), ViewerUserId: viewerUserID, - VisibleRegionId: userResp.GetUser().GetRegionId(), + VisibleRegionId: queryRegionID, ViewerCountryCode: userResp.GetUser().GetCountry(), AllVisibleRegions: allVisibleRegions, + FilterRegionId: filterRegionID, Tab: tab, Cursor: request.URL.Query().Get("cursor"), Limit: limit, @@ -342,25 +402,39 @@ func roomListQuery(request *http.Request) string { return strings.TrimSpace(request.URL.Query().Get("query")) } -func (h *Handler) roomListCountriesForUser(request *http.Request, user *userv1.User) ([]roomListCountryData, error) { - if user == nil || user.GetRegionId() <= 0 { - // 当前用户区域来自 user-service 主数据;缺失时不能猜测区域国家列表。 - return nil, xerr.New(xerr.InvalidArgument, "user region is required") +func (h *Handler) roomListCountriesForUser(request *http.Request, user *userv1.User) ([]roomListCountryData, []*userv1.Country, error) { + if user == nil { + return nil, nil, xerr.New(xerr.InvalidArgument, "user region is required") + } + countryResp, err := h.userCountryClient.ListRegistrationCountries(request.Context(), &userv1.ListRegistrationCountriesRequest{ + Meta: httpkit.UserMeta(request, ""), + }) + if err != nil { + return nil, nil, err + } + if user.GetRegionId() <= 0 { + // Huwaa All 不需要用户区域;旧 countries 字段留空,不用 IP/国家猜一个区域。 + return []roomListCountryData{}, countryResp.GetCountries(), nil } regionResp, err := h.userRegionClient.GetRegion(request.Context(), &userv1.GetRegionRequest{ Meta: httpkit.UserMeta(request, ""), RegionId: user.GetRegionId(), }) if err != nil { - return nil, err + return nil, nil, err } - countryResp, err := h.userCountryClient.ListRegistrationCountries(request.Context(), &userv1.ListRegistrationCountriesRequest{ - Meta: httpkit.UserMeta(request, ""), + return roomListCountriesFromProto(user, regionResp.GetRegion(), countryResp.GetCountries()), countryResp.GetCountries(), nil +} + +func (h *Handler) roomListActiveRegions(request *http.Request) ([]*userv1.Region, error) { + resp, err := h.userRegionClient.ListRegions(request.Context(), &userv1.ListRegionsRequest{ + Meta: httpkit.UserMeta(request, ""), + Status: roomFilterRegionStatusActive, }) if err != nil { return nil, err } - return roomListCountriesFromProto(user, regionResp.GetRegion(), countryResp.GetCountries()), nil + return resp.GetRegions(), nil } func roomListCountriesFromProto(user *userv1.User, region *userv1.Region, countries []*userv1.Country) []roomListCountryData { @@ -429,21 +503,74 @@ func roomListCountryDataFromProto(code string, country *userv1.Country) roomList return item } -func roomListCountryQuery(request *http.Request, countries []roomListCountryData) (string, bool) { - raw := strings.TrimSpace(request.URL.Query().Get("country")) - if raw == "" { - raw = strings.TrimSpace(request.URL.Query().Get("country_code")) - } - code := normalizeRoomListCountryCode(raw) +func roomListCountryAllowed(countries []roomListCountryData, code string) bool { + code = normalizeRoomListCountryCode(code) if code == "" { - return "", raw == "" + return true } for _, country := range countries { if normalizeRoomListCountryCode(country.CountryCode) == code { - return code, true + return true } } - return "", false + return false +} + +func roomListContainsActiveRegion(regions []*userv1.Region, regionID int64) bool { + if regionID <= 0 { + return false + } + for _, region := range regions { + if region != nil && region.GetRegionId() == regionID { + return true + } + } + return false +} + +func roomListCatalogContainsCountry(regions []*userv1.Region, countries []*userv1.Country, countryCode string) bool { + countryCode = normalizeRoomListCountryCode(countryCode) + if countryCode == "" { + return false + } + // 和 /rooms/filters 复用同一投影规则:只有 enabled 国家 + active 区域映射同时成立才能成为可查询值。 + for _, item := range roomFilterCatalogDataFromProto(regions, countries).Countries { + if item.CountryCode == countryCode { + return true + } + } + return false +} + +func parsePublicRoomListFilter(request *http.Request) (publicRoomListFilter, bool) { + if request == nil { + return publicRoomListFilter{}, false + } + rawRegionID := strings.TrimSpace(request.URL.Query().Get("region_id")) + rawCountryCode := strings.TrimSpace(request.URL.Query().Get("country_code")) + if rawCountryCode == "" { + // country 是既有客户端别名;新 Flutter 按目录下发的 country_code 回传。 + rawCountryCode = strings.TrimSpace(request.URL.Query().Get("country")) + } + if rawRegionID != "" && rawCountryCode != "" { + return publicRoomListFilter{}, false + } + filter := publicRoomListFilter{} + if rawRegionID != "" { + regionID, err := strconv.ParseInt(rawRegionID, 10, 64) + if err != nil || regionID <= 0 { + // All 必须不传筛选参数;region_id=0 不是目录下发的合法选项。 + return publicRoomListFilter{}, false + } + filter.RegionID = regionID + } + if rawCountryCode != "" { + filter.CountryCode = normalizeRoomListCountryCode(rawCountryCode) + if filter.CountryCode == "" { + return publicRoomListFilter{}, false + } + } + return filter, true } func normalizeRoomListCountryCode(countryCode string) string { @@ -1295,6 +1422,7 @@ func (h *Handler) joinRoomInitialData(request *http.Request, requestedRoomID str Profiles: h.roomInitialProfiles(request, snapshot, viewerUserID), IM: roomIMData{GroupID: roomIMGroupID(roomID), NeedJoinGroup: true}, RTC: h.joinRoomRTCData(roomID, viewerUserID), + EffectiveVIP: roomEffectiveVIPDataFromProto(resp.GetEffectiveVip()), ServerTimeMS: resp.GetResult().GetServerTimeMs(), } } @@ -1319,10 +1447,23 @@ func (h *Handler) joinRoomInitialLiteData(request *http.Request, requestedRoomID Profiles: h.roomInitialBasicProfiles(request, snapshot, viewerUserID), IM: roomIMData{GroupID: roomIMGroupID(roomID), NeedJoinGroup: true}, RTC: h.joinRoomRTCData(roomID, viewerUserID), + EffectiveVIP: roomEffectiveVIPDataFromProto(resp.GetEffectiveVip()), ServerTimeMS: resp.GetResult().GetServerTimeMs(), } } +func roomEffectiveVIPDataFromProto(snapshot *roomv1.RoomEffectiveVipSnapshot) roomEffectiveVIPData { + if snapshot == nil { + return roomEffectiveVIPData{} + } + return roomEffectiveVIPData{ + ProgramType: snapshot.GetProgramType(), + Level: snapshot.GetLevel(), + Name: snapshot.GetName(), + RoomEntryNoticeEnabled: snapshot.GetRoomEntryNoticeEnabled(), + } +} + func (h *Handler) joinRoomRTCData(roomID string, viewerUserID int64) roomRTCData { rtc := roomRTCData{NeedToken: true} token, err := h.generateTencentRTCToken(viewerUserID, roomID) diff --git a/services/gateway-service/internal/transport/http/roomapi/room_view.go b/services/gateway-service/internal/transport/http/roomapi/room_view.go index fb7972c6..6b049b72 100644 --- a/services/gateway-service/internal/transport/http/roomapi/room_view.go +++ b/services/gateway-service/internal/transport/http/roomapi/room_view.go @@ -70,6 +70,7 @@ type joinRoomData struct { Profiles []roomDisplayProfileData `json:"profiles"` IM roomIMData `json:"im"` RTC roomRTCData `json:"rtc"` + EffectiveVIP roomEffectiveVIPData `json:"effective_vip"` ServerTimeMS int64 `json:"server_time_ms"` } @@ -81,6 +82,7 @@ type joinRoomLiteData struct { Profiles []roomBasicProfileData `json:"profiles"` IM roomIMData `json:"im"` RTC roomRTCData `json:"rtc"` + EffectiveVIP roomEffectiveVIPData `json:"effective_vip"` ServerTimeMS int64 `json:"server_time_ms"` } @@ -98,6 +100,15 @@ type roomDetailData struct { ServerTimeMS int64 `json:"server_time_ms"` } +// roomEffectiveVIPData 是进房瞬间由 room-service 固化的轻量展示事实。 +// 完整权益仍以 wallet /vip/me 为准;这里仅用于当前用户首屏和房内进场效果立即渲染。 +type roomEffectiveVIPData struct { + ProgramType string `json:"program_type"` + Level int32 `json:"level"` + Name string `json:"name"` + RoomEntryNoticeEnabled bool `json:"room_entry_notice_enabled"` +} + type roomOnlineUsersData struct { Items []roomOnlineUserData `json:"items"` Total int64 `json:"total"` diff --git a/services/gateway-service/internal/transport/http/router.go b/services/gateway-service/internal/transport/http/router.go index ada28c23..f81fa723 100644 --- a/services/gateway-service/internal/transport/http/router.go +++ b/services/gateway-service/internal/transport/http/router.go @@ -51,6 +51,7 @@ func (h *Handler) Routes(jwtVerifier *auth.Verifier) http.Handler { UserIdentityClient: h.userIdentityClient, UserProfileClient: h.userProfileClient, UserHostClient: h.userHostClient, + BroadcastClient: h.broadcastClient, IMAccountImporter: h.tencentIMImporter, IMPublisher: h.tencentIMPublisher, IMGroupIDPrefix: h.tencentIM.GroupIDPrefix, diff --git a/services/gateway-service/internal/transport/http/vip_handler_test.go b/services/gateway-service/internal/transport/http/vip_handler_test.go new file mode 100644 index 00000000..06ed461b --- /dev/null +++ b/services/gateway-service/internal/transport/http/vip_handler_test.go @@ -0,0 +1,674 @@ +package http + +import ( + "bytes" + "encoding/json" + "errors" + "net/http" + "net/http/httptest" + "strings" + "testing" + + 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/transport/http/httpkit" +) + +func newVIPTestRouter(walletClient *fakeWalletClient) http.Handler { + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, &fakeUserProfileClient{}) + handler.SetWalletClient(walletClient) + return handler.Routes(auth.NewVerifier("secret")) +} + +func TestTriggerVIPOnlineNoticeChecksBenefitAndPublishesTrustedGlobalPayload(t *testing.T) { + walletClient := &fakeWalletClient{ + benefitCheckResp: &walletv1.CheckVipBenefitResponse{ + Allowed: true, + Benefit: &walletv1.VipBenefit{ + BenefitCode: "online_global_notice", + MetadataJson: `{"message":"欢迎进入Fami,祝你有美好的一天"}`, + }, + State: &walletv1.VipState{EffectiveVip: &walletv1.UserVip{ + UserId: 42, Level: 9, Name: "VIP9", Active: true, ProgramType: "tiered_privilege_v1", + }}, + EvaluatedAtMs: 1_800_000_000_000, + }, + batchEquippedResp: &walletv1.BatchGetUserEquippedResourcesResponse{Users: []*walletv1.UserEquippedResources{ + {UserId: 99, Resources: []*walletv1.UserResourceEntitlement{{Resource: &walletv1.Resource{ + ResourceId: 9000, ResourceCode: "other_user_frame", ResourceType: "avatar_frame", AssetUrl: "https://cdn.example/wrong-user.png", + }}}}, + {UserId: 42, Resources: []*walletv1.UserResourceEntitlement{ + {Resource: &walletv1.Resource{ResourceId: 7000, ResourceCode: "not_a_frame", ResourceType: "vehicle", AssetUrl: "https://cdn.example/car.svga"}}, + {Resource: &walletv1.Resource{ + ResourceId: 7001, ResourceCode: "vip9_gold_frame", ResourceType: "avatar_frame", + AssetUrl: "https://cdn.example/frame.svga", PreviewUrl: "https://cdn.example/frame.png", AnimationUrl: "https://cdn.example/frame.json", + }}, + }}, + }}, + } + profileClient := &fakeUserProfileClient{usersByID: map[int64]*userv1.User{42: { + UserId: 42, + Username: "I am a Rich", + Avatar: "https://cdn.example/vip9.png", + DisplayUserId: "100042", + PrettyDisplayUserId: "251145", + }}} + broadcastClient := &fakeBroadcastClient{} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetWalletClient(walletClient) + handler.SetBroadcastClient(broadcastClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodPost, "/api/v1/vip/online-notice", bytes.NewReader([]byte(`{"command_id":"process-launch-1"}`))) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "fami")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if req := walletClient.lastBenefitCheck; req == nil || req.GetAppCode() != "fami" || req.GetUserId() != 42 || req.GetBenefitCode() != "online_global_notice" || req.GetRequestId() != recorder.Header().Get("X-Request-ID") { + t.Fatalf("CheckVipBenefit request mismatch: %+v", req) + } + if req := walletClient.lastBatchEquipped; req == nil || req.GetAppCode() != "fami" || req.GetRequestId() != recorder.Header().Get("X-Request-ID") || len(req.GetUserIds()) != 1 || req.GetUserIds()[0] != 42 || len(req.GetResourceTypes()) != 1 || req.GetResourceTypes()[0] != "avatar_frame" { + t.Fatalf("BatchGetUserEquippedResources request mismatch: %+v", req) + } + if req := profileClient.lastGet; req == nil || req.GetUserId() != 42 || req.GetMeta().GetAppCode() != "fami" { + t.Fatalf("GetUser request mismatch: %+v", req) + } + publish := broadcastClient.lastGlobal + if publish == nil || publish.GetMeta().GetAppCode() != "fami" || publish.GetBroadcastType() != "vip_online_notice" || !strings.HasPrefix(publish.GetEventId(), "vip_online_notice:42:") { + t.Fatalf("PublishGlobalBroadcast request mismatch: %+v", publish) + } + var payload map[string]any + if err := json.Unmarshal([]byte(publish.GetPayloadJson()), &payload); err != nil { + t.Fatalf("decode broadcast payload: %v", err) + } + if payload["user_id"] != float64(42) || payload["nickname"] != "I am a Rich" || payload["avatar"] != "https://cdn.example/vip9.png" || payload["display_user_id"] != "251145" || payload["vip_level"] != float64(9) || payload["vip_name"] != "VIP9" || payload["message"] != "欢迎进入Fami,祝你有美好的一天" { + t.Fatalf("broadcast payload mismatch: %+v", payload) + } + if payload["avatar_frame_url"] != "https://cdn.example/frame.svga" || payload["avatar_frame_resource_id"] != float64(7001) || payload["avatar_frame_code"] != "vip9_gold_frame" || payload["avatar_frame_asset_url"] != "https://cdn.example/frame.svga" || payload["avatar_frame_preview_url"] != "https://cdn.example/frame.png" || payload["avatar_frame_animation_url"] != "https://cdn.example/frame.json" { + t.Fatalf("avatar frame payload mismatch: %+v", payload) + } + if _, leaked := payload["command_id"]; leaked || strings.Contains(publish.GetPayloadJson(), "process-launch-1") { + t.Fatalf("client command must not be broadcast: %s", publish.GetPayloadJson()) + } + var envelope struct { + Code string `json:"code"` + Data struct { + EventID string `json:"event_id"` + GroupID string `json:"group_id"` + Status string `json:"status"` + Created bool `json:"created"` + EvaluatedAtMS int64 `json:"evaluated_at_ms"` + } `json:"data"` + } + if err := json.NewDecoder(recorder.Body).Decode(&envelope); err != nil { + t.Fatalf("decode response failed: %v", err) + } + if envelope.Code != httpkit.CodeOK || envelope.Data.EventID != publish.GetEventId() || envelope.Data.GroupID != "hy_fami_bc_g_v2" || envelope.Data.Status != "pending" || !envelope.Data.Created || envelope.Data.EvaluatedAtMS != 1_800_000_000_000 { + t.Fatalf("response mismatch: %+v", envelope) + } +} + +func TestTriggerVIPOnlineNoticeWithoutEquippedFramePublishesExplicitEmptyFields(t *testing.T) { + walletClient := &fakeWalletClient{ + benefitCheckResp: &walletv1.CheckVipBenefitResponse{ + Allowed: true, + Benefit: &walletv1.VipBenefit{BenefitCode: "online_global_notice"}, + State: &walletv1.VipState{EffectiveVip: &walletv1.UserVip{UserId: 42, Level: 9, Name: "VIP9", Active: true}}, + }, + batchEquippedResp: &walletv1.BatchGetUserEquippedResourcesResponse{}, + } + profileClient := &fakeUserProfileClient{usersByID: map[int64]*userv1.User{42: {UserId: 42, Username: "No Frame"}}} + broadcastClient := &fakeBroadcastClient{} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetWalletClient(walletClient) + handler.SetBroadcastClient(broadcastClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodPost, "/api/v1/vip/online-notice", bytes.NewReader([]byte(`{"command_id":"process-launch-no-frame"}`))) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "fami")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK || broadcastClient.lastGlobal == nil { + t.Fatalf("no-frame request must still broadcast: status=%d body=%s", recorder.Code, recorder.Body.String()) + } + var payload map[string]any + if err := json.Unmarshal([]byte(broadcastClient.lastGlobal.GetPayloadJson()), &payload); err != nil { + t.Fatalf("decode broadcast payload: %v", err) + } + if payload["avatar_frame_resource_id"] != float64(0) || payload["avatar_frame_url"] != "" || payload["avatar_frame_code"] != "" || payload["avatar_frame_asset_url"] != "" || payload["avatar_frame_preview_url"] != "" || payload["avatar_frame_animation_url"] != "" { + t.Fatalf("empty avatar frame fields mismatch: %+v", payload) + } +} + +func TestTriggerVIPOnlineNoticeEquippedResourceFailureDoesNotBroadcast(t *testing.T) { + walletClient := &fakeWalletClient{ + benefitCheckResp: &walletv1.CheckVipBenefitResponse{Allowed: true}, + err: errors.New("wallet equipped resources unavailable"), + } + profileClient := &fakeUserProfileClient{} + broadcastClient := &fakeBroadcastClient{} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetWalletClient(walletClient) + handler.SetBroadcastClient(broadcastClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodPost, "/api/v1/vip/online-notice", bytes.NewReader([]byte(`{"command_id":"process-launch-frame-rpc-error"}`))) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "fami")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusBadGateway || walletClient.lastBatchEquipped == nil || profileClient.lastGet != nil || broadcastClient.lastGlobal != nil { + t.Fatalf("equipped-resource failure must stop before profile/broadcast: status=%d equipped=%+v profile=%+v broadcast=%+v body=%s", recorder.Code, walletClient.lastBatchEquipped, profileClient.lastGet, broadcastClient.lastGlobal, recorder.Body.String()) + } +} + +func TestTriggerVIPOnlineNoticeDenialDoesNotReadProfileOrBroadcast(t *testing.T) { + walletClient := &fakeWalletClient{benefitCheckResp: &walletv1.CheckVipBenefitResponse{Allowed: false, DenialReason: "benefit_not_enabled"}} + profileClient := &fakeUserProfileClient{} + broadcastClient := &fakeBroadcastClient{} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetWalletClient(walletClient) + handler.SetBroadcastClient(broadcastClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodPost, "/api/v1/vip/online-notice", bytes.NewReader([]byte(`{"command_id":"process-launch-denied"}`))) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "fami")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + 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()) + } +} + +func TestTriggerVIPOnlineNoticeUserSettingDenialDoesNotReadProfileOrBroadcast(t *testing.T) { + walletClient := &fakeWalletClient{benefitCheckResp: &walletv1.CheckVipBenefitResponse{ + Allowed: false, DenialReason: "user_setting_disabled", + }} + profileClient := &fakeUserProfileClient{} + broadcastClient := &fakeBroadcastClient{} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetWalletClient(walletClient) + handler.SetBroadcastClient(broadcastClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodPost, "/api/v1/vip/online-notice", bytes.NewReader([]byte(`{"command_id":"setting-disabled"}`))) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "fami")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusForbidden || profileClient.lastGet != nil || broadcastClient.lastGlobal != nil { + t.Fatalf("user setting denial leaked into downstream calls: status=%d profile=%+v broadcast=%+v body=%s", recorder.Code, profileClient.lastGet, broadcastClient.lastGlobal, recorder.Body.String()) + } +} + +func TestVIPSettingsHTTPContractPreservesExplicitFalseAndAuthScope(t *testing.T) { + walletClient := &fakeWalletClient{ + myVipResp: &walletv1.GetMyVipResponse{State: &walletv1.VipState{ + EvaluatedAtMs: 1_800_000_000_000, + UserSettings: &walletv1.VipUserSettings{ + AppCode: "fami", UserId: 42, RoomEntryNoticeEnabled: true, + OnlineGlobalNoticeEnabled: false, UpdatedAtMs: 1_799_999_999_000, + }, + }}, + updateVIPSettingsResp: &walletv1.UpdateMyVipSettingsResponse{ + Settings: &walletv1.VipUserSettings{ + AppCode: "fami", UserId: 42, RoomEntryNoticeEnabled: false, + OnlineGlobalNoticeEnabled: false, UpdatedAtMs: 1_800_000_000_100, + }, + ServerTimeMs: 1_800_000_000_200, + }, + } + router := newVIPTestRouter(walletClient) + token := "Bearer " + signGatewayTokenWithAppCode(t, "secret", 42, "fami") + + getRequest := httptest.NewRequest(http.MethodGet, "/api/v1/vip/settings", nil) + getRequest.Header.Set("Authorization", token) + getRecorder := httptest.NewRecorder() + router.ServeHTTP(getRecorder, getRequest) + if getRecorder.Code != http.StatusOK { + t.Fatalf("GET settings status mismatch: got=%d body=%s", getRecorder.Code, getRecorder.Body.String()) + } + if req := walletClient.lastMyVip; req == nil || req.GetAppCode() != "fami" || req.GetUserId() != 42 || req.GetRequestId() != getRecorder.Header().Get("X-Request-ID") { + t.Fatalf("GET settings must use authenticated scope: %+v", req) + } + 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"` + } `json:"settings"` + EvaluatedAtMS int64 `json:"evaluated_at_ms"` + } `json:"data"` + } + 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 { + 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.Header.Set("Authorization", token) + patchRecorder := httptest.NewRecorder() + router.ServeHTTP(patchRecorder, patchRequest) + if patchRecorder.Code != http.StatusOK { + 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") { + t.Fatalf("PATCH settings lost explicit false or auth scope: %+v", patch) + } + + // /vip/me 复用同一 DTO 转换,必须把 state.user_settings 一并透出。 + meRequest := httptest.NewRequest(http.MethodGet, "/api/v1/vip/me", nil) + meRequest.Header.Set("Authorization", token) + meRecorder := httptest.NewRecorder() + router.ServeHTTP(meRecorder, meRequest) + if meRecorder.Code != http.StatusOK || !strings.Contains(meRecorder.Body.String(), `"user_settings"`) || !strings.Contains(meRecorder.Body.String(), `"online_global_notice_enabled":false`) { + t.Fatalf("/vip/me missing user settings: status=%d body=%s", meRecorder.Code, meRecorder.Body.String()) + } +} + +func TestVIPSettingsEmptyPatchRejectedBeforeWallet(t *testing.T) { + walletClient := &fakeWalletClient{} + router := newVIPTestRouter(walletClient) + request := httptest.NewRequest(http.MethodPatch, "/api/v1/vip/settings", bytes.NewReader([]byte(`{}`))) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "fami")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusBadRequest || walletClient.lastUpdateVIPSettings != nil { + t.Fatalf("empty settings PATCH must fail before wallet: status=%d req=%+v body=%s", recorder.Code, walletClient.lastUpdateVIPSettings, recorder.Body.String()) + } +} + +func TestTriggerVIPOnlineNoticeValidatesCommandID(t *testing.T) { + walletClient := &fakeWalletClient{} + profileClient := &fakeUserProfileClient{} + broadcastClient := &fakeBroadcastClient{} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetWalletClient(walletClient) + handler.SetBroadcastClient(broadcastClient) + router := handler.Routes(auth.NewVerifier("secret")) + for name, body := range map[string]string{ + "empty": `{"command_id":""}`, + "too_long": `{"command_id":"` + strings.Repeat("x", 129) + `"}`, + } { + t.Run(name, func(t *testing.T) { + request := httptest.NewRequest(http.MethodPost, "/api/v1/vip/online-notice", bytes.NewReader([]byte(body))) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "fami")) + recorder := httptest.NewRecorder() + router.ServeHTTP(recorder, request) + if recorder.Code != http.StatusBadRequest { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + }) + } + if walletClient.lastBenefitCheck != nil || profileClient.lastGet != nil || broadcastClient.lastGlobal != nil { + t.Fatal("invalid command must be rejected before downstream calls") + } +} + +func TestVIPCoinRebateHTTPContractUsesAuthenticatedUser(t *testing.T) { + rebate := &walletv1.VipDailyCoinRebate{ + RebateId: "vip_rebate_01", UserId: 42, TaskDay: "2027-01-15", VipLevel: 9, VipName: "VIP9", + CoinAmount: 100000, Status: "claimable", AvailableAtMs: 1800000000000, ExpiresAtMs: 1800086400000, + ConfigVersion: 7, CreatedAtMs: 1800000000100, UpdatedAtMs: 1800000000100, + } + walletClient := &fakeWalletClient{ + currentVIPRebateResp: &walletv1.GetMyCurrentVipDailyCoinRebateResponse{Found: true, Rebate: rebate, ServerTimeMs: 1800000000200}, + vipRebateStatusesResp: &walletv1.ListMyVipDailyCoinRebateStatusesResponse{Rebates: []*walletv1.VipDailyCoinRebate{rebate}, Total: 1, ServerTimeMs: 1800000000300}, + claimVIPRebateResp: &walletv1.ClaimVipDailyCoinRebateResponse{ + Rebate: &walletv1.VipDailyCoinRebate{ + RebateId: rebate.GetRebateId(), UserId: 42, TaskDay: rebate.GetTaskDay(), VipLevel: 9, VipName: "VIP9", + CoinAmount: 100000, Status: "claimed", AvailableAtMs: rebate.GetAvailableAtMs(), ExpiresAtMs: rebate.GetExpiresAtMs(), + ConfigVersion: 7, ClaimedAtMs: 1800000000400, WalletTransactionId: "wtx-rebate-1", + }, + TransactionId: "wtx-rebate-1", + CoinBalance: &walletv1.AssetBalance{AssetType: "COIN", AvailableAmount: 500000, Version: 3}, + ServerTimeMs: 1800000000400, + }, + } + router := newVIPTestRouter(walletClient) + token := "Bearer " + signGatewayTokenWithAppCode(t, "secret", 42, "fami") + + currentRequest := httptest.NewRequest(http.MethodGet, "/api/v1/vip/coin-rebates/current", nil) + currentRequest.Header.Set("Authorization", token) + currentRecorder := httptest.NewRecorder() + router.ServeHTTP(currentRecorder, currentRequest) + if currentRecorder.Code != http.StatusOK { + t.Fatalf("current status mismatch: got %d body=%s", currentRecorder.Code, currentRecorder.Body.String()) + } + if req := walletClient.lastCurrentVIPRebate; req == nil || req.GetAppCode() != "fami" || req.GetUserId() != 42 || req.GetRequestId() != currentRecorder.Header().Get("X-Request-ID") { + t.Fatalf("current rebate request mismatch: %+v", req) + } + var currentEnvelope struct { + Data struct { + Found bool `json:"found"` + Rebate struct { + RebateID string `json:"rebate_id"` + UserID string `json:"user_id"` + CoinAmount int64 `json:"coin_amount"` + Status string `json:"status"` + } `json:"rebate"` + } `json:"data"` + } + if err := json.NewDecoder(currentRecorder.Body).Decode(¤tEnvelope); err != nil || !currentEnvelope.Data.Found || currentEnvelope.Data.Rebate.RebateID != rebate.GetRebateId() || currentEnvelope.Data.Rebate.UserID != "42" || currentEnvelope.Data.Rebate.CoinAmount != 100000 || currentEnvelope.Data.Rebate.Status != "claimable" { + t.Fatalf("current rebate response mismatch: envelope=%+v err=%v", currentEnvelope, err) + } + + statusesRequest := httptest.NewRequest(http.MethodPost, "/api/v1/vip/coin-rebates/statuses", bytes.NewReader([]byte(`{"rebate_ids":["vip_rebate_01"]}`))) + statusesRequest.Header.Set("Authorization", token) + statusesRecorder := httptest.NewRecorder() + router.ServeHTTP(statusesRecorder, statusesRequest) + if statusesRecorder.Code != http.StatusOK { + t.Fatalf("statuses mismatch: got %d body=%s", statusesRecorder.Code, statusesRecorder.Body.String()) + } + if req := walletClient.lastVIPRebateStatuses; req == nil || req.GetAppCode() != "fami" || req.GetUserId() != 42 || len(req.GetRebateIds()) != 1 || req.GetRebateIds()[0] != "vip_rebate_01" { + t.Fatalf("rebate statuses request mismatch: %+v", req) + } + + claimRequest := httptest.NewRequest(http.MethodPost, "/api/v1/vip/coin-rebates/vip_rebate_01/claim", bytes.NewReader([]byte(`{"command_id":"claim-rebate-01"}`))) + claimRequest.Header.Set("Authorization", token) + claimRecorder := httptest.NewRecorder() + router.ServeHTTP(claimRecorder, claimRequest) + if claimRecorder.Code != http.StatusOK { + t.Fatalf("claim mismatch: got %d body=%s", claimRecorder.Code, claimRecorder.Body.String()) + } + if req := walletClient.lastClaimVIPRebate; req == nil || req.GetAppCode() != "fami" || req.GetUserId() != 42 || req.GetRebateId() != "vip_rebate_01" || req.GetCommandId() != "claim-rebate-01" { + t.Fatalf("claim rebate request mismatch: %+v", req) + } + var claimEnvelope struct { + Data struct { + TransactionID string `json:"transaction_id"` + Rebate struct { + Status string `json:"status"` + } `json:"rebate"` + CoinBalance struct { + AvailableAmount int64 `json:"available_amount"` + } `json:"coin_balance"` + } `json:"data"` + } + if err := json.NewDecoder(claimRecorder.Body).Decode(&claimEnvelope); err != nil || claimEnvelope.Data.TransactionID != "wtx-rebate-1" || claimEnvelope.Data.Rebate.Status != "claimed" || claimEnvelope.Data.CoinBalance.AvailableAmount != 500000 { + t.Fatalf("claim response mismatch: envelope=%+v err=%v", claimEnvelope, err) + } +} + +func TestVIPCoinRebateClaimRejectsClientControlledInvalidKeys(t *testing.T) { + walletClient := &fakeWalletClient{} + router := newVIPTestRouter(walletClient) + request := httptest.NewRequest(http.MethodPost, "/api/v1/vip/coin-rebates/rebate-1/claim", bytes.NewReader([]byte(`{"command_id":""}`))) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "fami")) + recorder := httptest.NewRecorder() + router.ServeHTTP(recorder, request) + if recorder.Code != http.StatusBadRequest || walletClient.lastClaimVIPRebate != nil { + t.Fatalf("invalid claim must stop before wallet: status=%d req=%+v body=%s", recorder.Code, walletClient.lastClaimVIPRebate, recorder.Body.String()) + } +} + +func TestGetMyVIPKeepsLegacyFieldsAndAddsEffectiveState(t *testing.T) { + config := &walletv1.VipProgramConfig{ + AppCode: "fami", + ProgramType: "tiered_privilege_v1", + LevelCount: 9, + SameLevelExpiryPolicy: "extend_remaining", + UpgradeExpiryPolicy: "replace_from_now", + DowngradePurchasePolicy: "reject", + BenefitInheritancePolicy: "target_only", + GrantMode: "trial_card", + TrialCardEnabled: true, + Status: "active", + ConfigVersion: 3, + } + state := &walletv1.VipState{ + PaidVip: &walletv1.UserVip{UserId: 42, Level: 3, Name: "VIP3", Active: true, ExpiresAtMs: 2_000, ProgramType: config.GetProgramType(), ConfigVersion: 3}, + EquippedTrialCard: &walletv1.VipTrialCard{ + TrialCardId: "card-4", EntitlementId: "ent-4", UserId: 42, Level: 4, Name: "VIP4体验卡", Equipped: true, ExpiresAtMs: 3_000, + }, + EffectiveVip: &walletv1.UserVip{UserId: 42, Level: 4, Name: "VIP4", Active: true, ExpiresAtMs: 3_000, ProgramType: config.GetProgramType(), ConfigVersion: 3}, + EffectiveSource: "trial", + EffectiveBenefits: []*walletv1.VipBenefit{{BenefitCode: "room_entry_notice", Name: "进房通知", TrialEnabled: true, Status: "active"}}, + EvaluatedAtMs: 1_500, + ProgramConfig: config, + } + walletClient := &fakeWalletClient{myVipResp: &walletv1.GetMyVipResponse{Vip: state.GetEffectiveVip(), State: state}} + router := newVIPTestRouter(walletClient) + request := httptest.NewRequest(http.MethodGet, "/api/v1/vip/me", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "fami")) + request.Header.Set("X-Request-ID", "req-vip-me") + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + generatedRequestID := recorder.Header().Get("X-Request-ID") + if req := walletClient.lastMyVip; req == nil || req.GetAppCode() != "fami" || req.GetUserId() != 42 || req.GetRequestId() != generatedRequestID { + t.Fatalf("GetMyVip request mismatch: %+v", req) + } + var envelope struct { + Code string `json:"code"` + Data struct { + Level int32 `json:"level"` + ConfigVersion int64 `json:"config_version"` + ProgramConfig struct { + ProgramType string `json:"program_type"` + TrialCardEnabled bool `json:"trial_card_enabled"` + } `json:"program_config"` + State struct { + EffectiveSource string `json:"effective_source"` + PaidVIP struct { + Level int32 `json:"level"` + } `json:"paid_vip"` + EffectiveVIP struct { + Level int32 `json:"level"` + } `json:"effective_vip"` + EquippedTrialCard struct { + EntitlementID string `json:"entitlement_id"` + } `json:"equipped_trial_card"` + EffectiveBenefits []struct { + BenefitCode string `json:"benefit_code"` + } `json:"effective_benefits"` + } `json:"state"` + } `json:"data"` + } + if err := json.NewDecoder(recorder.Body).Decode(&envelope); err != nil { + t.Fatalf("decode response failed: %v", err) + } + if envelope.Code != httpkit.CodeOK || envelope.Data.Level != 4 || envelope.Data.ConfigVersion != 3 { + t.Fatalf("legacy VIP fields mismatch: %+v", envelope.Data) + } + if envelope.Data.ProgramConfig.ProgramType != "tiered_privilege_v1" || !envelope.Data.ProgramConfig.TrialCardEnabled { + t.Fatalf("program config mismatch: %+v", envelope.Data.ProgramConfig) + } + if envelope.Data.State.PaidVIP.Level != 3 || envelope.Data.State.EffectiveVIP.Level != 4 || envelope.Data.State.EffectiveSource != "trial" || envelope.Data.State.EquippedTrialCard.EntitlementID != "ent-4" { + t.Fatalf("effective state mismatch: %+v", envelope.Data.State) + } + if len(envelope.Data.State.EffectiveBenefits) != 1 || envelope.Data.State.EffectiveBenefits[0].BenefitCode != "room_entry_notice" { + t.Fatalf("effective benefits mismatch: %+v", envelope.Data.State.EffectiveBenefits) + } +} + +func TestListVIPPackagesAddsProgramStateAndLevelBenefits(t *testing.T) { + config := &walletv1.VipProgramConfig{AppCode: "fami", ProgramType: "tiered_privilege_v1", LevelCount: 9, ConfigVersion: 7, TrialCardEnabled: true} + walletClient := &fakeWalletClient{vipPackagesResp: &walletv1.ListVipPackagesResponse{ + 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}}, + }}, + State: &walletv1.VipState{EffectiveVip: &walletv1.UserVip{UserId: 42, Level: 2, Active: true}, EffectiveSource: "paid", ProgramConfig: config}, + ProgramConfig: config, + }} + router := newVIPTestRouter(walletClient) + request := httptest.NewRequest(http.MethodGet, "/api/v1/vip/packages", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "fami")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if req := walletClient.lastVipPackages; req == nil || req.GetAppCode() != "fami" || req.GetUserId() != 42 || req.GetRequestId() != recorder.Header().Get("X-Request-ID") { + t.Fatalf("ListVipPackages request mismatch: %+v", req) + } + var envelope struct { + Data struct { + CurrentVIP struct { + Level int32 `json:"level"` + } `json:"current_vip"` + ProgramConfig struct { + LevelCount int32 `json:"level_count"` + } `json:"program_config"` + State struct { + EffectiveSource string `json:"effective_source"` + } `json:"state"` + Packages []struct { + ConfigVersion int64 `json:"config_version"` + Benefits []struct { + BenefitCode string `json:"benefit_code"` + } `json:"benefits"` + } `json:"packages"` + } `json:"data"` + } + if err := json.NewDecoder(recorder.Body).Decode(&envelope); err != nil { + t.Fatalf("decode response failed: %v", err) + } + if envelope.Data.CurrentVIP.Level != 2 || envelope.Data.ProgramConfig.LevelCount != 9 || envelope.Data.State.EffectiveSource != "paid" || len(envelope.Data.Packages) != 1 { + t.Fatalf("packages response mismatch: %+v", envelope.Data) + } + 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) + } +} + +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}, + }} + router := newVIPTestRouter(walletClient) + request := httptest.NewRequest(http.MethodPost, "/api/v1/vip/purchase", bytes.NewReader([]byte(`{"command_id":"vip-buy-4","level":4}`))) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "fami")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if 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) + } + var envelope struct { + Data struct { + OrderID string `json:"order_id"` + TransactionID string `json:"transaction_id"` + VIP struct { + Level int32 `json:"level"` + } `json:"vip"` + ProgramConfig struct { + UpgradeExpiryPolicy string `json:"upgrade_expiry_policy"` + } `json:"program_config"` + State struct { + EffectiveSource string `json:"effective_source"` + } `json:"state"` + } `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" { + t.Fatalf("purchase response mismatch: %+v", envelope.Data) + } +} + +func TestEquipVIPTrialCardUsesAuthenticatedEntitlement(t *testing.T) { + config := &walletv1.VipProgramConfig{AppCode: "fami", ProgramType: "tiered_privilege_v1", TrialCardEnabled: true} + walletClient := &fakeWalletClient{trialEquipResp: &walletv1.EquipVipTrialCardResponse{ + TrialCard: &walletv1.VipTrialCard{TrialCardId: "card-9", EntitlementId: "ent-card-9", UserId: 42, Level: 9, Equipped: true, ExpiresAtMs: 9_000}, + State: &walletv1.VipState{EquippedTrialCard: &walletv1.VipTrialCard{EntitlementId: "ent-card-9", Level: 9, Equipped: true}, EffectiveVip: &walletv1.UserVip{UserId: 42, Level: 9, Active: true}, EffectiveSource: "trial", ProgramConfig: config}, + ServerTimeMs: 1_800, + }} + router := newVIPTestRouter(walletClient) + request := httptest.NewRequest(http.MethodPost, "/api/v1/vip/trial-cards/ent-card-9/equip", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "fami")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if 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) + } + var envelope struct { + Data struct { + TrialCard struct { + EntitlementID string `json:"entitlement_id"` + } `json:"trial_card"` + State struct { + EffectiveSource string `json:"effective_source"` + } `json:"state"` + ServerTimeMS int64 `json:"server_time_ms"` + } `json:"data"` + } + if err := json.NewDecoder(recorder.Body).Decode(&envelope); err != nil { + t.Fatalf("decode response failed: %v", err) + } + if envelope.Data.TrialCard.EntitlementID != "ent-card-9" || envelope.Data.State.EffectiveSource != "trial" || envelope.Data.ServerTimeMS != 1_800 { + t.Fatalf("equip response mismatch: %+v", envelope.Data) + } +} + +func TestUnequipVIPTrialCardRestoresPaidState(t *testing.T) { + config := &walletv1.VipProgramConfig{AppCode: "fami", ProgramType: "tiered_privilege_v1", TrialCardEnabled: true} + walletClient := &fakeWalletClient{trialUnequipResp: &walletv1.UnequipVipTrialCardResponse{ + Unequipped: true, + State: &walletv1.VipState{PaidVip: &walletv1.UserVip{UserId: 42, Level: 3, Active: true}, EffectiveVip: &walletv1.UserVip{UserId: 42, Level: 3, Active: true}, EffectiveSource: "paid", ProgramConfig: config}, + ServerTimeMs: 1_900, + }} + router := newVIPTestRouter(walletClient) + request := httptest.NewRequest(http.MethodDelete, "/api/v1/vip/trial-cards/equipped", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayTokenWithAppCode(t, "secret", 42, "fami")) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if 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) + } + var envelope struct { + Data struct { + Unequipped bool `json:"unequipped"` + State struct { + EffectiveSource string `json:"effective_source"` + EffectiveVIP struct { + Level int32 `json:"level"` + } `json:"effective_vip"` + } `json:"state"` + } `json:"data"` + } + if err := json.NewDecoder(recorder.Body).Decode(&envelope); err != nil { + t.Fatalf("decode response failed: %v", err) + } + if !envelope.Data.Unequipped || envelope.Data.State.EffectiveSource != "paid" || envelope.Data.State.EffectiveVIP.Level != 3 { + t.Fatalf("unequip response mismatch: %+v", envelope.Data) + } +} 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 54a43df8..12a595e1 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 @@ -1,6 +1,7 @@ package walletapi import ( + "encoding/json" "hyapp/services/gateway-service/internal/transport/http/httpkit" "net/http" "strings" @@ -137,6 +138,43 @@ type vipPurchaseRequestBody struct { Level int32 `json:"level"` } +// vipMeData 匿名嵌入旧 DTO 以保留 data.level/name/active 等历史字段,新增结构化 +// state 后客户端可以逐版本迁移,不会因一次协议升级失去当前会员展示。 +type vipMeData struct { + OverviewVIPData overviewVIPData `json:"-"` + ProgramConfig vipProgramConfigData `json:"program_config"` + State vipStateData `json:"state"` +} + +// MarshalJSON 明确把旧字段保持在 data 根层,避免嵌套成 overview_vip_data 而破坏 +// 已发布 Flutter 解析;新字段只做向后兼容的追加。 +func (data vipMeData) MarshalJSON() ([]byte, error) { + type wire struct { + Level int32 `json:"level"` + Name string `json:"name"` + Active bool `json:"active"` + StartedAtMS int64 `json:"started_at_ms"` + ExpiresAtMS int64 `json:"expires_at_ms"` + ProgramType string `json:"program_type,omitempty"` + ConfigVersion int64 `json:"config_version,omitempty"` + Unavailable bool `json:"unavailable,omitempty"` + ProgramConfig vipProgramConfigData `json:"program_config"` + State vipStateData `json:"state"` + } + return json.Marshal(wire{ + Level: data.OverviewVIPData.Level, + Name: data.OverviewVIPData.Name, + Active: data.OverviewVIPData.Active, + StartedAtMS: data.OverviewVIPData.StartedAtMS, + ExpiresAtMS: data.OverviewVIPData.ExpiresAtMS, + ProgramType: data.OverviewVIPData.ProgramType, + ConfigVersion: data.OverviewVIPData.ConfigVersion, + Unavailable: data.OverviewVIPData.Unavailable, + ProgramConfig: data.ProgramConfig, + State: data.State, + }) +} + type vipPackageData struct { Level int32 `json:"level"` Name string `json:"name"` @@ -151,6 +189,84 @@ type vipPackageData struct { RequiredRechargeCoinAmount int64 `json:"required_recharge_coin_amount"` UserRechargeCoinAmount int64 `json:"user_recharge_coin_amount"` PurchaseLockedReason string `json:"purchase_locked_reason"` + Benefits []vipBenefitData `json:"benefits"` + ConfigVersion int64 `json:"config_version"` +} + +// vipProgramConfigData 原样暴露 wallet-service 已判定的 App 级策略;客户端只据此展示, +// 购买有效期、降级限制和体验卡开关始终由 wallet-service 在事务内执行。 +type vipProgramConfigData struct { + AppCode string `json:"app_code"` + ProgramType string `json:"program_type"` + LevelCount int32 `json:"level_count"` + SameLevelExpiryPolicy string `json:"same_level_expiry_policy"` + UpgradeExpiryPolicy string `json:"upgrade_expiry_policy"` + DowngradePurchasePolicy string `json:"downgrade_purchase_policy"` + BenefitInheritancePolicy string `json:"benefit_inheritance_policy"` + GrantMode string `json:"grant_mode"` + TrialCardEnabled bool `json:"trial_card_enabled"` + Status string `json:"status"` + ConfigVersion int64 `json:"config_version"` + UpdatedByAdminID int64 `json:"updated_by_admin_id"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +// 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"` +} + +type vipTrialCardData struct { + TrialCardID string `json:"trial_card_id"` + EntitlementID string `json:"entitlement_id"` + ResourceID int64 `json:"resource_id"` + UserID int64 `json:"user_id"` + Level int32 `json:"level"` + Name string `json:"name"` + Status string `json:"status"` + Equipped bool `json:"equipped"` + DurationMS int64 `json:"duration_ms"` + EffectiveAtMS int64 `json:"effective_at_ms"` + ExpiresAtMS int64 `json:"expires_at_ms"` + RemainingDurationMS int64 `json:"remaining_duration_ms"` + GrantSource string `json:"grant_source"` + SourceGrantID string `json:"source_grant_id"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +type vipStateData struct { + PaidVIP overviewVIPData `json:"paid_vip"` + EquippedTrialCard *vipTrialCardData `json:"equipped_trial_card"` + EffectiveVIP overviewVIPData `json:"effective_vip"` + EffectiveSource string `json:"effective_source"` + EffectiveBenefits []vipBenefitData `json:"effective_benefits"` + EvaluatedAtMS int64 `json:"evaluated_at_ms"` + ProgramConfig vipProgramConfigData `json:"program_config"` + UserSettings vipUserSettingsData `json:"user_settings"` +} + +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"` } type vipRewardItemData struct { diff --git a/services/gateway-service/internal/transport/http/walletapi/handler.go b/services/gateway-service/internal/transport/http/walletapi/handler.go index d2656228..c6da6eb5 100644 --- a/services/gateway-service/internal/transport/http/walletapi/handler.go +++ b/services/gateway-service/internal/transport/http/walletapi/handler.go @@ -20,6 +20,7 @@ type Handler struct { userIdentityClient client.UserIdentityClient userProfileClient client.UserProfileClient userHostClient client.UserHostClient + broadcastClient client.BroadcastClient imAccountImporter TencentIMAccountImporter imPublisher TencentIMUserMessagePublisher imGroupIDPrefix string @@ -50,6 +51,7 @@ type Config struct { UserIdentityClient client.UserIdentityClient UserProfileClient client.UserProfileClient UserHostClient client.UserHostClient + BroadcastClient client.BroadcastClient IMAccountImporter TencentIMAccountImporter IMPublisher TencentIMUserMessagePublisher IMGroupIDPrefix string @@ -66,6 +68,7 @@ func New(config Config) *Handler { userIdentityClient: config.UserIdentityClient, userProfileClient: config.UserProfileClient, userHostClient: config.UserHostClient, + broadcastClient: config.BroadcastClient, imAccountImporter: config.IMAccountImporter, imPublisher: config.IMPublisher, imGroupIDPrefix: config.IMGroupIDPrefix, @@ -133,9 +136,16 @@ func (h *Handler) WalletHandlers() httproutes.WalletHandlers { func (h *Handler) VIPHandlers() httproutes.VIPHandlers { return httproutes.VIPHandlers{ - GetMyVIP: h.getMyVIP, - ListVIPPackages: h.listVIPPackages, - PurchaseVIP: h.purchaseVIP, + GetMyVIP: h.getMyVIP, + ListVIPPackages: h.listVIPPackages, + PurchaseVIP: h.purchaseVIP, + EquipVIPTrialCard: h.equipVIPTrialCard, + UnequipVIPTrialCard: h.unequipVIPTrialCard, + TriggerOnlineNotice: h.triggerVIPOnlineNotice, + HandleVIPSettings: h.handleVIPSettings, + GetCurrentCoinRebate: h.getCurrentVIPCoinRebate, + ListCoinRebateStatuses: h.listVIPCoinRebateStatuses, + ClaimCoinRebate: h.claimVIPCoinRebate, } } diff --git a/services/gateway-service/internal/transport/http/walletapi/view_shared.go b/services/gateway-service/internal/transport/http/walletapi/view_shared.go index d0d7d6f9..8d05b218 100644 --- a/services/gateway-service/internal/transport/http/walletapi/view_shared.go +++ b/services/gateway-service/internal/transport/http/walletapi/view_shared.go @@ -3,12 +3,14 @@ package walletapi import walletv1 "hyapp.local/api/proto/wallet/v1" type overviewVIPData struct { - Level int32 `json:"level"` - Name string `json:"name"` - Active bool `json:"active"` - StartedAtMS int64 `json:"started_at_ms"` - ExpiresAtMS int64 `json:"expires_at_ms"` - Unavailable bool `json:"unavailable,omitempty"` + Level int32 `json:"level"` + Name string `json:"name"` + Active bool `json:"active"` + StartedAtMS int64 `json:"started_at_ms"` + ExpiresAtMS int64 `json:"expires_at_ms"` + ProgramType string `json:"program_type,omitempty"` + ConfigVersion int64 `json:"config_version,omitempty"` + Unavailable bool `json:"unavailable,omitempty"` } type resourceData struct { 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 86dd03e5..587aecef 100644 --- a/services/gateway-service/internal/transport/http/walletapi/vip_handler.go +++ b/services/gateway-service/internal/transport/http/walletapi/vip_handler.go @@ -1,17 +1,48 @@ package walletapi import ( - "hyapp/services/gateway-service/internal/transport/http/httpkit" + "crypto/sha256" + "encoding/json" + "fmt" "net/http" "strings" + activityv1 "hyapp.local/api/proto/activity/v1" + userv1 "hyapp.local/api/proto/user/v1" + walletv1 "hyapp.local/api/proto/wallet/v1" "hyapp/pkg/appcode" "hyapp/services/gateway-service/internal/auth" - - walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/services/gateway-service/internal/transport/http/httpkit" ) -// getMyVIP 返回当前用户 VIP 状态。 +const ( + vipOnlineNoticeBenefitCode = "online_global_notice" + vipOnlineNoticeBroadcastType = "vip_online_notice" + vipOnlineNoticeAvatarFrame = "avatar_frame" + vipOnlineNoticeCommandMaxLen = 128 + vipOnlineNoticeMessageMaxLen = 256 +) + +type vipOnlineNoticeRequestBody struct { + // CommandID 是单次 App 进程启动的业务幂等键;request_id 只用于链路追踪,不能替代它。 + CommandID string `json:"command_id"` + CommandIDAlt string `json:"commandId"` +} + +type vipOnlineNoticeMetadata struct { + Message string `json:"message"` +} + +type vipOnlineNoticeAvatarFrameData struct { + ResourceID int64 + Code string + AssetURL string + PreviewURL string + AnimationURL string +} + +// getMyVIP 同时返回旧版扁平 VIP 字段和新的 paid/trial/effective 状态。 +// 扁平字段继续取 GetMyVipResponse.vip,保证旧客户端升级期间无需同时切换解析路径。 func (h *Handler) getMyVIP(writer http.ResponseWriter, request *http.Request) { if h.walletClient == nil { httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") @@ -26,7 +57,12 @@ func (h *Handler) getMyVIP(writer http.ResponseWriter, request *http.Request) { httpkit.WriteRPCError(writer, request, err) return } - httpkit.WriteOK(writer, request, vipFromProto(resp.GetVip())) + state := vipStateFromProto(resp.GetState()) + httpkit.WriteOK(writer, request, vipMeData{ + OverviewVIPData: vipFromProto(resp.GetVip()), + ProgramConfig: state.ProgramConfig, + State: state, + }) } // listVIPPackages 返回可购买 VIP 包和当前会员状态。 @@ -48,7 +84,17 @@ func (h *Handler) listVIPPackages(writer http.ResponseWriter, request *http.Requ for _, item := range resp.GetPackages() { packages = append(packages, vipPackageFromProto(item)) } - httpkit.WriteOK(writer, request, map[string]any{"current_vip": vipFromProto(resp.GetCurrentVip()), "packages": packages}) + state := vipStateFromProto(resp.GetState()) + programConfig := vipProgramConfigFromProto(resp.GetProgramConfig()) + if resp.GetProgramConfig() == nil { + programConfig = state.ProgramConfig + } + httpkit.WriteOK(writer, request, map[string]any{ + "current_vip": vipFromProto(resp.GetCurrentVip()), + "packages": packages, + "program_config": programConfig, + "state": state, + }) } // purchaseVIP 购买、续期或升级 VIP。 @@ -86,19 +132,239 @@ func (h *Handler) purchaseVIP(writer http.ResponseWriter, request *http.Request) "coin_spent": resp.GetCoinSpent(), "coin_balance_after": resp.GetCoinBalanceAfter(), "reward_items": vipRewardItemsFromProto(resp.GetRewardItems()), + "program_config": vipProgramConfigFromProto(resp.GetState().GetProgramConfig()), + "state": vipStateFromProto(resp.GetState()), }) } +// equipVIPTrialCard 只接受背包实例 entitlement_id;同资源的多张卡不能用 resource_id +// 代替,否则切换时会误改另一张卡的独立到期时间。 +func (h *Handler) equipVIPTrialCard(writer http.ResponseWriter, request *http.Request) { + if h.walletClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + entitlementID := strings.TrimSpace(request.PathValue("entitlement_id")) + if entitlementID == "" { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + resp, err := h.walletClient.EquipVipTrialCard(request.Context(), &walletv1.EquipVipTrialCardRequest{ + RequestId: httpkit.RequestIDFromContext(request.Context()), + AppCode: appcode.FromContext(request.Context()), + UserId: auth.UserIDFromContext(request.Context()), + EntitlementId: entitlementID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + state := vipStateFromProto(resp.GetState()) + httpkit.WriteOK(writer, request, map[string]any{ + "trial_card": vipTrialCardFromProto(resp.GetTrialCard()), + "program_config": state.ProgramConfig, + "state": state, + "server_time_ms": resp.GetServerTimeMs(), + }) +} + +// unequipVIPTrialCard 只解除当前装备关系;体验卡实例和其绝对过期时间仍保留在背包, +// 因而客户端可以随后重新佩戴尚未过期的任意等级体验卡。 +func (h *Handler) unequipVIPTrialCard(writer http.ResponseWriter, request *http.Request) { + if h.walletClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + resp, err := h.walletClient.UnequipVipTrialCard(request.Context(), &walletv1.UnequipVipTrialCardRequest{ + RequestId: httpkit.RequestIDFromContext(request.Context()), + AppCode: appcode.FromContext(request.Context()), + UserId: auth.UserIDFromContext(request.Context()), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + state := vipStateFromProto(resp.GetState()) + httpkit.WriteOK(writer, request, map[string]any{ + "unequipped": resp.GetUnequipped(), + "program_config": state.ProgramConfig, + "state": state, + "server_time_ms": resp.GetServerTimeMs(), + }) +} + +// triggerVIPOnlineNotice 是 VIP 上线全服飘屏的唯一 App HTTP 入口。 +// Flutter 负责进程内“UTC 当日只请求一次”的展示策略;服务端不做按日持久化去重,因而杀进程 +// 后的新进程可以再次请求。单次请求重试仍通过 command_id 映射为稳定 event_id,避免网络重试重复播报。 +func (h *Handler) triggerVIPOnlineNotice(writer http.ResponseWriter, request *http.Request) { + if h.walletClient == nil || h.userProfileClient == nil || h.broadcastClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + var body vipOnlineNoticeRequestBody + if !httpkit.Decode(writer, request, &body) { + return + } + commandID := strings.TrimSpace(body.CommandID) + if commandID == "" { + commandID = strings.TrimSpace(body.CommandIDAlt) + } + if commandID == "" || len(commandID) > vipOnlineNoticeCommandMaxLen { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + + ctx := request.Context() + userID := auth.UserIDFromContext(ctx) + appCode := appcode.FromContext(ctx) + benefitResp, err := h.walletClient.CheckVipBenefit(ctx, &walletv1.CheckVipBenefitRequest{ + RequestId: httpkit.RequestIDFromContext(ctx), + AppCode: appCode, + UserId: userID, + BenefitCode: vipOnlineNoticeBenefitCode, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + if !benefitResp.GetAllowed() { + // 客户端展示态可能滞后,执行前必须重新查 effective benefit;体验卡排除、过期和后台停用 + // 都以 wallet-service 此刻的判定为准,不能仅比较 VIP9 等级。 + httpkit.WriteError(writer, request, http.StatusForbidden, httpkit.CodePermissionDenied, "permission denied") + return + } + equippedResp, err := h.walletClient.BatchGetUserEquippedResources(ctx, &walletv1.BatchGetUserEquippedResourcesRequest{ + RequestId: httpkit.RequestIDFromContext(ctx), + AppCode: appCode, + UserIds: []int64{userID}, + ResourceTypes: []string{vipOnlineNoticeAvatarFrame}, + }) + if err != nil { + // 头像框是全服消息的一部分,不能在 wallet 查询失败时把“无头像框”当成真实佩戴态广播。 + // 失败请求由客户端复用同一 command_id 重试,成功后仍只会写入同一条 activity outbox。 + httpkit.WriteRPCError(writer, request, err) + return + } + avatarFrame := vipOnlineNoticeAvatarFrameFromResponse(equippedResp, userID) + profileResp, err := h.userProfileClient.GetUser(ctx, &userv1.GetUserRequest{ + Meta: httpkit.UserMeta(request, ""), + UserId: userID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + profile := profileResp.GetUser() + if profile == nil || profile.GetUserId() != userID { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + + effectiveVIP := benefitResp.GetState().GetEffectiveVip() + displayID := strings.TrimSpace(profile.GetPrettyDisplayUserId()) + if displayID == "" { + displayID = strings.TrimSpace(profile.GetDisplayUserId()) + } + payload, err := json.Marshal(map[string]any{ + "user_id": userID, + "sender_user_id": userID, + "nickname": profile.GetUsername(), + "avatar": profile.GetAvatar(), + "display_user_id": displayID, + "raw_display_user_id": profile.GetDisplayUserId(), + "pretty_display_user_id": profile.GetPrettyDisplayUserId(), + // avatar_frame_url 是客户端高频兼容字段,固定等同资源 asset_url;其余字段保留完整素材信息, + // 让静态、预览和动画渲染都只消费 wallet 返回的当前佩戴事实。 + "avatar_frame_url": avatarFrame.AssetURL, + "avatar_frame_resource_id": avatarFrame.ResourceID, + "avatar_frame_code": avatarFrame.Code, + "avatar_frame_asset_url": avatarFrame.AssetURL, + "avatar_frame_preview_url": avatarFrame.PreviewURL, + "avatar_frame_animation_url": avatarFrame.AnimationURL, + "vip_program_type": effectiveVIP.GetProgramType(), + "vip_level": effectiveVIP.GetLevel(), + "vip_name": effectiveVIP.GetName(), + "message": vipOnlineNoticeMessage(appCode, benefitResp.GetBenefit().GetMetadataJson()), + "action": map[string]string{"type": "none"}, + }) + if err != nil { + httpkit.WriteError(writer, request, http.StatusInternalServerError, httpkit.CodeInternalError, "internal error") + return + } + // event_id 使用 user_id + command_id 摘要,既隔离不同用户,又避免客户端长命令超过 + // activity outbox 的 VARCHAR(128) 主键;相同 command_id 的 HTTP 重试会命中同一条 outbox。 + commandDigest := sha256.Sum256([]byte(commandID)) + eventID := fmt.Sprintf("vip_online_notice:%d:%x", userID, commandDigest) + broadcastResp, err := h.broadcastClient.PublishGlobalBroadcast(ctx, &activityv1.PublishGlobalBroadcastRequest{ + Meta: httpkit.ActivityMeta(request), + EventId: eventID, + BroadcastType: vipOnlineNoticeBroadcastType, + PayloadJson: string(payload), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + httpkit.WriteOK(writer, request, map[string]any{ + "event_id": broadcastResp.GetEventId(), + "group_id": broadcastResp.GetGroupId(), + "status": broadcastResp.GetStatus(), + "created": broadcastResp.GetCreated(), + "evaluated_at_ms": benefitResp.GetEvaluatedAtMs(), + }) +} + +// vipOnlineNoticeAvatarFrameFromResponse 只接受目标用户下的 avatar_frame。 +// wallet 的 batch RPC 已负责过滤过期佩戴,这里仍防御错误分组、错误资源类型和空资源,避免串用户素材。 +func vipOnlineNoticeAvatarFrameFromResponse(resp *walletv1.BatchGetUserEquippedResourcesResponse, userID int64) vipOnlineNoticeAvatarFrameData { + for _, user := range resp.GetUsers() { + if user.GetUserId() != userID { + continue + } + for _, item := range user.GetResources() { + resource := item.GetResource() + if resource.GetResourceType() != vipOnlineNoticeAvatarFrame || resource.GetResourceId() <= 0 { + continue + } + return vipOnlineNoticeAvatarFrameData{ + ResourceID: resource.GetResourceId(), + Code: resource.GetResourceCode(), + AssetURL: resource.GetAssetUrl(), + PreviewURL: resource.GetPreviewUrl(), + AnimationURL: resource.GetAnimationUrl(), + } + } + } + return vipOnlineNoticeAvatarFrameData{} +} + +// vipOnlineNoticeMessage 从每级权益 metadata_json 读取 App 独立文案。 +// Fami 旧配置没有 metadata 时保留产品确认的默认文案;其他 App 使用中性兜底,避免把 Fami 名称串到 Lalu。 +func vipOnlineNoticeMessage(appCode string, metadataJSON string) string { + var metadata vipOnlineNoticeMetadata + if json.Unmarshal([]byte(strings.TrimSpace(metadataJSON)), &metadata) == nil { + if message := strings.TrimSpace(metadata.Message); message != "" && len(message) <= vipOnlineNoticeMessageMaxLen { + return message + } + } + if strings.EqualFold(strings.TrimSpace(appCode), "fami") { + return "欢迎进入Fami,祝你有美好的一天" + } + return "欢迎进入,祝你有美好的一天" +} + func vipFromProto(vip *walletv1.UserVip) overviewVIPData { if vip == nil { return overviewVIPData{} } return overviewVIPData{ - Level: vip.GetLevel(), - Name: vip.GetName(), - Active: vip.GetActive(), - StartedAtMS: vip.GetStartedAtMs(), - ExpiresAtMS: vip.GetExpiresAtMs(), + Level: vip.GetLevel(), + Name: vip.GetName(), + Active: vip.GetActive(), + StartedAtMS: vip.GetStartedAtMs(), + ExpiresAtMS: vip.GetExpiresAtMs(), + ProgramType: vip.GetProgramType(), + ConfigVersion: vip.GetConfigVersion(), } } @@ -120,6 +386,114 @@ func vipPackageFromProto(item *walletv1.VipLevel) vipPackageData { RequiredRechargeCoinAmount: item.GetRequiredRechargeCoinAmount(), UserRechargeCoinAmount: item.GetUserRechargeCoinAmount(), PurchaseLockedReason: item.GetPurchaseLockedReason(), + Benefits: vipBenefitsFromProto(item.GetBenefits()), + ConfigVersion: item.GetConfigVersion(), + } +} + +func vipProgramConfigFromProto(config *walletv1.VipProgramConfig) vipProgramConfigData { + if config == nil { + return vipProgramConfigData{} + } + return vipProgramConfigData{ + AppCode: config.GetAppCode(), + ProgramType: config.GetProgramType(), + LevelCount: config.GetLevelCount(), + SameLevelExpiryPolicy: config.GetSameLevelExpiryPolicy(), + UpgradeExpiryPolicy: config.GetUpgradeExpiryPolicy(), + DowngradePurchasePolicy: config.GetDowngradePurchasePolicy(), + BenefitInheritancePolicy: config.GetBenefitInheritancePolicy(), + GrantMode: config.GetGrantMode(), + TrialCardEnabled: config.GetTrialCardEnabled(), + Status: config.GetStatus(), + ConfigVersion: config.GetConfigVersion(), + UpdatedByAdminID: config.GetUpdatedByAdminId(), + CreatedAtMS: config.GetCreatedAtMs(), + UpdatedAtMS: config.GetUpdatedAtMs(), + } +} + +func vipBenefitsFromProto(items []*walletv1.VipBenefit) []vipBenefitData { + result := make([]vipBenefitData, 0, len(items)) + for _, item := range items { + if item == nil { + continue + } + result = append(result, vipBenefitData{ + BenefitCode: item.GetBenefitCode(), + Name: item.GetName(), + BenefitType: item.GetBenefitType(), + UnlockLevel: item.GetUnlockLevel(), + Status: item.GetStatus(), + TrialEnabled: item.GetTrialEnabled(), + ResourceID: item.GetResourceId(), + ResourceType: item.GetResourceType(), + ExecutionScope: item.GetExecutionScope(), + AutoEquip: item.GetAutoEquip(), + SortOrder: item.GetSortOrder(), + MetadataJSON: item.GetMetadataJson(), + CreatedAtMS: item.GetCreatedAtMs(), + UpdatedAtMS: item.GetUpdatedAtMs(), + }) + } + return result +} + +func vipTrialCardFromProto(card *walletv1.VipTrialCard) *vipTrialCardData { + if card == nil { + return nil + } + return &vipTrialCardData{ + TrialCardID: card.GetTrialCardId(), + EntitlementID: card.GetEntitlementId(), + ResourceID: card.GetResourceId(), + UserID: card.GetUserId(), + Level: card.GetLevel(), + Name: card.GetName(), + Status: card.GetStatus(), + Equipped: card.GetEquipped(), + DurationMS: card.GetDurationMs(), + EffectiveAtMS: card.GetEffectiveAtMs(), + ExpiresAtMS: card.GetExpiresAtMs(), + RemainingDurationMS: card.GetRemainingDurationMs(), + GrantSource: card.GetGrantSource(), + SourceGrantID: card.GetSourceGrantId(), + CreatedAtMS: card.GetCreatedAtMs(), + UpdatedAtMS: card.GetUpdatedAtMs(), + } +} + +func vipStateFromProto(state *walletv1.VipState) vipStateData { + if state == nil { + return vipStateData{ + EffectiveBenefits: []vipBenefitData{}, + UserSettings: vipUserSettingsData{ + RoomEntryNoticeEnabled: true, OnlineGlobalNoticeEnabled: true, + }, + } + } + return vipStateData{ + PaidVIP: vipFromProto(state.GetPaidVip()), + EquippedTrialCard: vipTrialCardFromProto(state.GetEquippedTrialCard()), + EffectiveVIP: vipFromProto(state.GetEffectiveVip()), + EffectiveSource: state.GetEffectiveSource(), + EffectiveBenefits: vipBenefitsFromProto(state.GetEffectiveBenefits()), + EvaluatedAtMS: state.GetEvaluatedAtMs(), + ProgramConfig: vipProgramConfigFromProto(state.GetProgramConfig()), + UserSettings: vipUserSettingsFromProto(state.GetUserSettings()), + } +} + +func vipUserSettingsFromProto(settings *walletv1.VipUserSettings) vipUserSettingsData { + if settings == nil { + // wallet 滚动升级期间旧实例没有 tag 8;与 wallet owner 的缺行语义一致,按默认开启兼容。 + return vipUserSettingsData{RoomEntryNoticeEnabled: true, OnlineGlobalNoticeEnabled: true} + } + return vipUserSettingsData{ + AppCode: settings.GetAppCode(), UserID: settings.GetUserId(), + RoomEntryNoticeEnabled: settings.GetRoomEntryNoticeEnabled(), + OnlineGlobalNoticeEnabled: settings.GetOnlineGlobalNoticeEnabled(), + UpdatedAtMS: settings.GetUpdatedAtMs(), } } diff --git a/services/gateway-service/internal/transport/http/walletapi/vip_notice_test.go b/services/gateway-service/internal/transport/http/walletapi/vip_notice_test.go new file mode 100644 index 00000000..383f69d1 --- /dev/null +++ b/services/gateway-service/internal/transport/http/walletapi/vip_notice_test.go @@ -0,0 +1,18 @@ +package walletapi + +import ( + "strings" + "testing" +) + +func TestVIPOnlineNoticeMessageUsesConfiguredValueAndSafeFallbacks(t *testing.T) { + if got := vipOnlineNoticeMessage("fami", "{"); got != "欢迎进入Fami,祝你有美好的一天" { + t.Fatalf("Fami fallback mismatch: %q", got) + } + if got := vipOnlineNoticeMessage("lalu", `{"message":" Lalu VIP online "}`); got != "Lalu VIP online" { + t.Fatalf("configured message mismatch: %q", got) + } + if got := vipOnlineNoticeMessage("lalu", `{"message":"`+strings.Repeat("x", 257)+`"}`); got != "欢迎进入,祝你有美好的一天" { + t.Fatalf("oversized message fallback mismatch: %q", got) + } +} diff --git a/services/gateway-service/internal/transport/http/walletapi/vip_rebate_handler.go b/services/gateway-service/internal/transport/http/walletapi/vip_rebate_handler.go new file mode 100644 index 00000000..695a3d84 --- /dev/null +++ b/services/gateway-service/internal/transport/http/walletapi/vip_rebate_handler.go @@ -0,0 +1,165 @@ +package walletapi + +import ( + "net/http" + "strings" + + walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/pkg/appcode" + "hyapp/services/gateway-service/internal/auth" + "hyapp/services/gateway-service/internal/transport/http/httpkit" +) + +type vipCoinRebateStatusesRequestBody struct { + RebateIDs []string `json:"rebate_ids"` + Page int32 `json:"page"` + PageSize int32 `json:"page_size"` +} + +type vipCoinRebateClaimRequestBody struct { + CommandID string `json:"command_id"` + CommandIDAlt string `json:"commandId"` +} + +type vipDailyCoinRebateData struct { + RebateID string `json:"rebate_id"` + UserID string `json:"user_id"` + TaskDay string `json:"task_day"` + VIPLevel int32 `json:"vip_level"` + VIPName string `json:"vip_name"` + CoinAmount int64 `json:"coin_amount"` + Status string `json:"status"` + AvailableAtMS int64 `json:"available_at_ms"` + ExpiresAtMS int64 `json:"expires_at_ms"` + ConfigVersion int64 `json:"config_version"` + ClaimedAtMS int64 `json:"claimed_at_ms"` + WalletTransactionID string `json:"wallet_transaction_id"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +// getCurrentVIPCoinRebate 返回当前 UTC 自然日的领取事实。found=false 是用户当日无资格或 +// cron 尚未生成的正常状态,客户端不能据 VIP 等级自行补算金额。 +func (h *Handler) getCurrentVIPCoinRebate(writer http.ResponseWriter, request *http.Request) { + if h.walletClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + resp, err := h.walletClient.GetMyCurrentVipDailyCoinRebate(request.Context(), &walletv1.GetMyCurrentVipDailyCoinRebateRequest{ + RequestId: httpkit.RequestIDFromContext(request.Context()), + AppCode: appcode.FromContext(request.Context()), + UserId: auth.UserIDFromContext(request.Context()), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + var rebate *vipDailyCoinRebateData + if resp.GetFound() && resp.GetRebate() != nil { + item := vipDailyCoinRebateFromProto(resp.GetRebate()) + rebate = &item + } + httpkit.WriteOK(writer, request, map[string]any{ + "found": resp.GetFound(), + "rebate": rebate, + "server_time_ms": resp.GetServerTimeMs(), + }) +} + +// listVIPCoinRebateStatuses 为系统通知恢复真实领取状态。rebate_ids 非空时 wallet 只返回 +// 当前用户拥有的指定记录;为空时提供受限历史分页,不能接受客户端 user_id/app_code。 +func (h *Handler) listVIPCoinRebateStatuses(writer http.ResponseWriter, request *http.Request) { + if h.walletClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + var body vipCoinRebateStatusesRequestBody + if !httpkit.Decode(writer, request, &body) { + return + } + if len(body.RebateIDs) > 100 || body.Page < 0 || body.PageSize < 0 || body.PageSize > 100 { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + resp, err := h.walletClient.ListMyVipDailyCoinRebateStatuses(request.Context(), &walletv1.ListMyVipDailyCoinRebateStatusesRequest{ + RequestId: httpkit.RequestIDFromContext(request.Context()), + AppCode: appcode.FromContext(request.Context()), + UserId: auth.UserIDFromContext(request.Context()), + Page: body.Page, + PageSize: body.PageSize, + RebateIds: body.RebateIDs, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + items := make([]vipDailyCoinRebateData, 0, len(resp.GetRebates())) + for _, rebate := range resp.GetRebates() { + items = append(items, vipDailyCoinRebateFromProto(rebate)) + } + httpkit.WriteOK(writer, request, map[string]any{ + "rebates": items, + "total": resp.GetTotal(), + "server_time_ms": resp.GetServerTimeMs(), + }) +} + +// claimVIPCoinRebate 只接收返现 ID 和业务幂等键;金额、等级、归属和 [UTC 0点,次日0点) +// 领取窗口全部由 wallet 锁内事实决定,避免客户端篡改金额或跨用户领取。 +func (h *Handler) claimVIPCoinRebate(writer http.ResponseWriter, request *http.Request) { + if h.walletClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + rebateID := strings.TrimSpace(request.PathValue("rebate_id")) + var body vipCoinRebateClaimRequestBody + if !httpkit.Decode(writer, request, &body) { + return + } + commandID := strings.TrimSpace(body.CommandID) + if commandID == "" { + commandID = strings.TrimSpace(body.CommandIDAlt) + } + if rebateID == "" || len(rebateID) > 96 || commandID == "" || len(commandID) > 128 { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + resp, err := h.walletClient.ClaimVipDailyCoinRebate(request.Context(), &walletv1.ClaimVipDailyCoinRebateRequest{ + CommandId: commandID, + AppCode: appcode.FromContext(request.Context()), + UserId: auth.UserIDFromContext(request.Context()), + RebateId: rebateID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + httpkit.WriteOK(writer, request, map[string]any{ + "rebate": vipDailyCoinRebateFromProto(resp.GetRebate()), + "transaction_id": resp.GetTransactionId(), + "coin_balance": balanceFromProto(resp.GetCoinBalance()), + "server_time_ms": resp.GetServerTimeMs(), + }) +} + +func vipDailyCoinRebateFromProto(rebate *walletv1.VipDailyCoinRebate) vipDailyCoinRebateData { + if rebate == nil { + return vipDailyCoinRebateData{} + } + return vipDailyCoinRebateData{ + RebateID: rebate.GetRebateId(), + UserID: httpkit.UserIDString(rebate.GetUserId()), + TaskDay: rebate.GetTaskDay(), + VIPLevel: rebate.GetVipLevel(), + VIPName: rebate.GetVipName(), + CoinAmount: rebate.GetCoinAmount(), + Status: rebate.GetStatus(), + AvailableAtMS: rebate.GetAvailableAtMs(), + ExpiresAtMS: rebate.GetExpiresAtMs(), + ConfigVersion: rebate.GetConfigVersion(), + ClaimedAtMS: rebate.GetClaimedAtMs(), + WalletTransactionID: rebate.GetWalletTransactionId(), + CreatedAtMS: rebate.GetCreatedAtMs(), + UpdatedAtMS: rebate.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 new file mode 100644 index 00000000..dddbc381 --- /dev/null +++ b/services/gateway-service/internal/transport/http/walletapi/vip_settings_handler.go @@ -0,0 +1,94 @@ +package walletapi + +import ( + "net/http" + + walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/pkg/appcode" + "hyapp/services/gateway-service/internal/auth" + "hyapp/services/gateway-service/internal/transport/http/httpkit" +) + +type vipSettingsPatchBody struct { + // 指针保留 PATCH 的三态:未提交、显式 true、显式 false。 + RoomEntryNoticeEnabled *bool `json:"room_entry_notice_enabled"` + OnlineGlobalNoticeEnabled *bool `json:"online_global_notice_enabled"` +} + +// handleVIPSettings 在同一路径分发 GET/PATCH,避免向当前 ServeMux 重复注册相同 pattern。 +func (h *Handler) handleVIPSettings(writer http.ResponseWriter, request *http.Request) { + switch request.Method { + case http.MethodGet: + h.getVIPSettings(writer, request) + case http.MethodPatch: + h.patchVIPSettings(writer, request) + default: + httpkit.WriteError(writer, request, http.StatusMethodNotAllowed, httpkit.CodeInvalidArgument, "invalid argument") + } +} + +// getVIPSettings 复用 GetMyVip 的同一状态快照,不为 room/online 开关再发第二个 wallet RPC。 +func (h *Handler) getVIPSettings(writer http.ResponseWriter, request *http.Request) { + if h.walletClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + ctx := request.Context() + appCode := appcode.FromContext(ctx) + userID := auth.UserIDFromContext(ctx) + resp, err := h.walletClient.GetMyVip(ctx, &walletv1.GetMyVipRequest{ + RequestId: httpkit.RequestIDFromContext(ctx), AppCode: appCode, UserId: userID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + if resp == nil || resp.GetState() == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + settings := vipUserSettingsFromProto(resp.GetState().GetUserSettings()) + // 兼容滚动升级期间旧 wallet 未返回 settings 标识字段;默认布尔值仍由 converter 保持开启。 + if settings.AppCode == "" { + settings.AppCode = appCode + } + if settings.UserID == 0 { + settings.UserID = userID + } + httpkit.WriteOK(writer, request, map[string]any{ + "settings": settings, "evaluated_at_ms": resp.GetState().GetEvaluatedAtMs(), + }) +} + +// patchVIPSettings 只从鉴权上下文取 app/user,客户端不能替他人或跨 App 改设置。 +func (h *Handler) patchVIPSettings(writer http.ResponseWriter, request *http.Request) { + if h.walletClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + var body vipSettingsPatchBody + if !httpkit.Decode(writer, request, &body) { + return + } + if body.RoomEntryNoticeEnabled == nil && body.OnlineGlobalNoticeEnabled == nil { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + ctx := request.Context() + 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, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + if resp == nil || resp.GetSettings() == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + httpkit.WriteOK(writer, request, map[string]any{ + "settings": vipUserSettingsFromProto(resp.GetSettings()), "server_time_ms": resp.GetServerTimeMs(), + }) +} diff --git a/services/room-service/internal/integration/clients.go b/services/room-service/internal/integration/clients.go index 0c11ac15..d3f4920c 100644 --- a/services/room-service/internal/integration/clients.go +++ b/services/room-service/internal/integration/clients.go @@ -10,7 +10,7 @@ import ( "hyapp/pkg/tencentim" ) -// WalletClient 抽象 room-service 对 wallet-service 的同步扣费依赖。 +// WalletClient 抽象 room-service 对 wallet-service 的同步账务和 VIP 权限事实依赖。 type WalletClient interface { // DebitGift 执行送礼扣费;失败时 room-service 不进入 Room Cell 状态提交。 DebitGift(ctx context.Context, req *walletv1.DebitGiftRequest) (*walletv1.DebitGiftResponse, error) @@ -20,6 +20,9 @@ type WalletClient interface { DebitRobotGift(ctx context.Context, req *walletv1.DebitRobotGiftRequest) (*walletv1.DebitGiftResponse, error) // GrantResourceGroup 发放火箭奖励资源组;命令 ID 必须由 room-service 按火箭结算事实生成。 GrantResourceGroup(ctx context.Context, req *walletv1.GrantResourceGroupRequest) (*walletv1.ResourceGrantResponse, error) + // GetMyVip 读取 wallet-service 已合并付费 VIP 与当前佩戴体验卡后的唯一 effective state。 + // room-service 只消费 effective_benefits,不自行按等级或 app_code 推导房间权限。 + GetMyVip(ctx context.Context, req *walletv1.GetMyVipRequest) (*walletv1.GetMyVipResponse, error) } // LuckyGiftClient 抽象 room-service 对 lucky-gift-service 幸运礼物抽奖边界的同步依赖。 diff --git a/services/room-service/internal/integration/clients_grpc.go b/services/room-service/internal/integration/clients_grpc.go index e64ebcf8..014f6a1f 100644 --- a/services/room-service/internal/integration/clients_grpc.go +++ b/services/room-service/internal/integration/clients_grpc.go @@ -45,6 +45,11 @@ func (c *grpcWalletClient) GrantResourceGroup(ctx context.Context, req *walletv1 return c.client.GrantResourceGroup(ctx, req) } +// GetMyVip 直接读取钱包已经求值后的 VIP 状态;房间侧不能复制付费 VIP、体验卡和权益继承算法。 +func (c *grpcWalletClient) GetMyVip(ctx context.Context, req *walletv1.GetMyVipRequest) (*walletv1.GetMyVipResponse, error) { + return c.client.GetMyVip(ctx, req) +} + type grpcLuckyGiftClient struct { client luckygiftv1.LuckyGiftServiceClient } diff --git a/services/room-service/internal/integration/tencent_im.go b/services/room-service/internal/integration/tencent_im.go index 5c235068..c8b0ccb2 100644 --- a/services/room-service/internal/integration/tencent_im.go +++ b/services/room-service/internal/integration/tencent_im.go @@ -541,6 +541,12 @@ func roomUserJoinedAttributesFromEvent(body *roomeventsv1.RoomUserJoined) map[st delete(values, key) } } + // VIP 入场开关必须显式传 false;否则 Flutter 无法区分“普通进房”与旧消息缺字段。 + // 这些值都来自 RoomUserJoined 固化事实,补偿投递不能按用户当前 VIP 重新计算历史进房表现。 + values["vip_program_type"] = strings.TrimSpace(body.GetVipProgramType()) + values["effective_vip_level"] = fmt.Sprintf("%d", body.GetEffectiveVipLevel()) + values["effective_vip_name"] = strings.TrimSpace(body.GetEffectiveVipName()) + values["room_entry_notice_enabled"] = fmt.Sprintf("%t", body.GetRoomEntryNoticeEnabled()) return values } diff --git a/services/room-service/internal/integration/tencent_im_test.go b/services/room-service/internal/integration/tencent_im_test.go index 9d69d9eb..6dd04d0b 100644 --- a/services/room-service/internal/integration/tencent_im_test.go +++ b/services/room-service/internal/integration/tencent_im_test.go @@ -35,13 +35,17 @@ func TestRoomEventFromEnvelopeSkipsNonIMEvents(t *testing.T) { func TestRoomUserJoinedCarriesEntryVehicleSnapshot(t *testing.T) { record, err := outbox.Build("room-vehicle", "RoomUserJoined", 9, time.Now(), &roomeventsv1.RoomUserJoined{ - UserId: 42, - Role: "audience", - VisibleRegionId: 86, - Nickname: "Join Nina", - Avatar: "https://cdn.example.com/nina.png", - DisplayUserId: "100042", - PrettyDisplayUserId: "888042", + UserId: 42, + Role: "audience", + VisibleRegionId: 86, + Nickname: "Join Nina", + Avatar: "https://cdn.example.com/nina.png", + DisplayUserId: "100042", + PrettyDisplayUserId: "888042", + VipProgramType: "tiered_privilege_v1", + EffectiveVipLevel: 4, + EffectiveVipName: "VIP4", + RoomEntryNoticeEnabled: true, EntryVehicle: &roomeventsv1.RoomEntryVehicleSnapshot{ ResourceId: 7001, ResourceCode: "vehicle_gold", @@ -71,6 +75,9 @@ func TestRoomUserJoinedCarriesEntryVehicleSnapshot(t *testing.T) { if event.Attributes["nickname"] != "Join Nina" || event.Attributes["avatar"] != "https://cdn.example.com/nina.png" || event.Attributes["display_user_id"] != "100042" || event.Attributes["pretty_display_user_id"] != "888042" { t.Fatalf("joined display profile attributes mismatch: %+v", event.Attributes) } + if event.Attributes["vip_program_type"] != "tiered_privilege_v1" || event.Attributes["effective_vip_level"] != "4" || event.Attributes["effective_vip_name"] != "VIP4" || event.Attributes["room_entry_notice_enabled"] != "true" { + t.Fatalf("joined vip attributes mismatch: %+v", event.Attributes) + } } func TestRoomBackgroundChangedPublishesDedicatedIMEvent(t *testing.T) { diff --git a/services/room-service/internal/room/service/background.go b/services/room-service/internal/room/service/background.go index fbbf3585..643d4335 100644 --- a/services/room-service/internal/room/service/background.go +++ b/services/room-service/internal/room/service/background.go @@ -28,6 +28,10 @@ func (s *Service) SaveRoomBackground(ctx context.Context, req *roomv1.SaveRoomBa if err := s.requireRoomOwnerMeta(ctx, roomID, actorUserID); err != nil { return nil, err } + if err := s.requireCustomRoomBackgroundBenefit(ctx, req.GetMeta().GetRequestId(), actorUserID); err != nil { + // 保存素材本身就会形成持久数据,P1 App 必须在写库前校验当前 effective benefit。 + return nil, err + } nowMS := s.clock.Now().UnixMilli() background, err := s.repository.SaveRoomBackground(ctx, RoomBackgroundImage{ @@ -107,6 +111,10 @@ func (s *Service) SetRoomBackground(ctx context.Context, req *roomv1.SetRoomBack if current.OwnerUserID != cmd.ActorUserID() { return mutationResult{}, nil, xerr.New(xerr.PermissionDenied, "permission denied") } + if err := s.requireCustomRoomBackgroundBenefit(ctx, req.GetMeta().GetRequestId(), cmd.ActorUserID()); err != nil { + // 放在 mutate 回调内可让同一 command_id 的已提交重试先命中幂等,不会因 VIP 后续到期改写旧命令结果。 + return mutationResult{}, nil, err + } if current.RoomExt == nil { current.RoomExt = make(map[string]string) } diff --git a/services/room-service/internal/room/service/follow_test.go b/services/room-service/internal/room/service/follow_test.go index 9e1e3012..22994159 100644 --- a/services/room-service/internal/room/service/follow_test.go +++ b/services/room-service/internal/room/service/follow_test.go @@ -32,6 +32,20 @@ func (followTestWallet) GrantResourceGroup(context.Context, *walletv1.GrantResou return &walletv1.ResourceGrantResponse{Grant: &walletv1.ResourceGrant{GrantId: "grant-follow-test"}}, nil } +func (followTestWallet) GetMyVip(_ context.Context, req *walletv1.GetMyVipRequest) (*walletv1.GetMyVipResponse, error) { + return legacyVIPResponse(req.GetUserId()), nil +} + +func legacyVIPResponse(userID int64) *walletv1.GetMyVipResponse { + // 大多数既有 room-service 测试运行在 Lalu;显式返回 legacy program,验证新增门禁不会暗改旧 App 行为。 + return &walletv1.GetMyVipResponse{ + State: &walletv1.VipState{ + ProgramConfig: &walletv1.VipProgramConfig{AppCode: appcode.Default, ProgramType: "legacy_timed", Status: "active"}, + EffectiveVip: &walletv1.UserVip{UserId: userID}, + }, + } +} + func TestRoomFollowAffectsSnapshotAndFollowedFeed(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) diff --git a/services/room-service/internal/room/service/list.go b/services/room-service/internal/room/service/list.go index 328749d1..57239330 100644 --- a/services/room-service/internal/room/service/list.go +++ b/services/room-service/internal/room/service/list.go @@ -40,6 +40,7 @@ type roomListCursor struct { CountryCode string `json:"country_code,omitempty"` ViewerCountry string `json:"viewer_country,omitempty"` AllRegions bool `json:"all_regions,omitempty"` + FilterRegion int64 `json:"filter_region_id,omitempty"` SortScore int64 `json:"sort_score,omitempty"` CreatedAtMS int64 `json:"created_at_ms,omitempty"` UpdatedAtMS int64 `json:"updated_at_ms,omitempty"` @@ -73,14 +74,25 @@ func (s *Service) ListRooms(ctx context.Context, req *roomv1.ListRoomsRequest) ( countryCode := normalizeRoomCountryCode(req.GetCountryCode()) viewerCountryCode := normalizeRoomCountryCode(req.GetViewerCountryCode()) allVisibleRegions := req.GetAllVisibleRegions() - cursor, err := decodeRoomListCursor(tab, query, countryCode, viewerCountryCode, allVisibleRegions, req.GetCursor()) + filterRegionID := req.GetFilterRegionId() + if filterRegionID < 0 || (filterRegionID > 0 && (allVisibleRegions || countryCode != "")) { + // 区域、国家和 All 是三种互斥的公共列表范围;拒绝混合语义避免游标跨范围漏数。 + return nil, xerr.New(xerr.InvalidArgument, "room list filter is invalid") + } + cursor, err := decodeRoomListCursor(tab, query, countryCode, viewerCountryCode, allVisibleRegions, filterRegionID, req.GetCursor()) if err != nil { return nil, err } + effectiveRegionID := normalizeVisibleRegionID(req.GetVisibleRegionId()) + if filterRegionID > 0 { + // 缓存和 MySQL 读模型共用 VisibleRegionID 作为实际查询桶;游标仍单独保存 FilterRegionID 区分客户筛选。 + effectiveRegionID = filterRegionID + } entries, err := s.listRoomListEntries(ctx, RoomListQuery{ AppCode: appcode.FromContext(ctx), - VisibleRegionID: normalizeVisibleRegionID(req.GetVisibleRegionId()), + VisibleRegionID: effectiveRegionID, + FilterRegionID: filterRegionID, AllVisibleRegions: allVisibleRegions, Tab: tab, Query: query, @@ -100,7 +112,7 @@ func (s *Service) ListRooms(ctx context.Context, req *roomv1.ListRoomsRequest) ( return nil, err } - return roomListResponseFromEntries(tab, query, countryCode, viewerCountryCode, allVisibleRegions, entries, limit), nil + return roomListResponseFromEntries(tab, query, countryCode, viewerCountryCode, allVisibleRegions, filterRegionID, entries, limit), nil } func (s *Service) ListRoomsByOwners(ctx context.Context, req *roomv1.ListRoomsByOwnersRequest) (*roomv1.ListRoomsResponse, error) { @@ -115,14 +127,14 @@ func (s *Service) ListRoomsByOwners(ctx context.Context, req *roomv1.ListRoomsBy } ownerUserIDs := normalizeRoomOwnerFilters(req.GetOwnerUserIds()) if len(ownerUserIDs) == 0 { - return roomListResponseFromEntries(tab, "", "", "", false, nil, normalizeRoomListLimit(req.GetLimit())), nil + return roomListResponseFromEntries(tab, "", "", "", false, 0, nil, normalizeRoomListLimit(req.GetLimit())), nil } limit := normalizeRoomListLimit(req.GetLimit()) query, err := normalizeRoomListQuery(req.GetQuery()) if err != nil { return nil, err } - cursor, err := decodeRoomListCursor(tab, query, "", "", false, req.GetCursor()) + cursor, err := decodeRoomListCursor(tab, query, "", "", false, 0, req.GetCursor()) if err != nil { return nil, err } @@ -139,7 +151,7 @@ func (s *Service) ListRoomsByOwners(ctx context.Context, req *roomv1.ListRoomsBy if err != nil { return nil, err } - return roomListResponseFromEntries(tab, query, "", "", false, entries, limit), nil + return roomListResponseFromEntries(tab, query, "", "", false, 0, entries, limit), nil } func (s *Service) listRoomListEntries(ctx context.Context, query RoomListQuery) ([]RoomListEntry, error) { @@ -157,8 +169,8 @@ func (s *Service) listRoomListEntries(ctx context.Context, query RoomListQuery) } func roomListCacheEligible(query RoomListQuery) bool { - // 搜索、全区白名单和内部定向查询仍走 MySQL,避免为了低频条件维护过宽的 Redis 索引。 - if strings.TrimSpace(query.Query) != "" || query.AllVisibleRegions || query.OwnerUserID > 0 || len(query.OwnerUserIDs) > 0 { + // 搜索和内部定向查询仍走 MySQL;All/region/country 则都有可重建的 Redis 桶,可以承载首页高频读。 + if strings.TrimSpace(query.Query) != "" || query.OwnerUserID > 0 || len(query.OwnerUserIDs) > 0 { return false } return query.Tab == roomListTabHot || query.Tab == roomListTabNew @@ -183,7 +195,7 @@ func (s *Service) ListRoomFeeds(ctx context.Context, req *roomv1.ListRoomFeedsRe if err != nil { return nil, err } - cursor, err := decodeRoomListCursor(tab, query, "", "", false, req.GetCursor()) + cursor, err := decodeRoomListCursor(tab, query, "", "", false, 0, req.GetCursor()) if err != nil { return nil, err } @@ -231,7 +243,7 @@ func (s *Service) ListRoomFeeds(ctx context.Context, req *roomv1.ListRoomFeedsRe return nil, err } - return roomListResponseFromEntries(tab, query, "", "", false, entries, limit), nil + return roomListResponseFromEntries(tab, query, "", "", false, 0, entries, limit), nil } // GetMyRoom 查询当前用户自己创建的房间,不依赖 room_list_entries 投影命中。 @@ -264,12 +276,12 @@ func (s *Service) GetMyRoom(ctx context.Context, req *roomv1.GetMyRoomRequest) ( }, nil } -func roomListResponseFromEntries(tab string, query string, countryCode string, viewerCountryCode string, allRegions bool, entries []RoomListEntry, limit int) *roomv1.ListRoomsResponse { +func roomListResponseFromEntries(tab string, query string, countryCode string, viewerCountryCode string, allRegions bool, filterRegionID int64, entries []RoomListEntry, limit int) *roomv1.ListRoomsResponse { nextCursor := "" if len(entries) > limit { // 多查一条用于判断是否存在下一页;返回数据只包含请求的 limit 条。 last := entries[limit-1] - nextCursor = encodeRoomListCursor(tab, query, countryCode, viewerCountryCode, allRegions, last) + nextCursor = encodeRoomListCursor(tab, query, countryCode, viewerCountryCode, allRegions, filterRegionID, last) entries = entries[:limit] } @@ -521,10 +533,10 @@ func normalizeRoomCountryCode(countryCode string) string { } // decodeRoomListCursor 校验不透明 cursor 和当前 tab 一致,禁止客户端跨排序维度复用游标。 -func decodeRoomListCursor(tab string, query string, countryCode string, viewerCountryCode string, allRegions bool, encoded string) (roomListCursor, error) { +func decodeRoomListCursor(tab string, query string, countryCode string, viewerCountryCode string, allRegions bool, filterRegionID int64, encoded string) (roomListCursor, error) { encoded = strings.TrimSpace(encoded) if encoded == "" { - return roomListCursor{Tab: tab, Query: query, CountryCode: countryCode, ViewerCountry: viewerCountryCode, AllRegions: allRegions}, nil + return roomListCursor{Tab: tab, Query: query, CountryCode: countryCode, ViewerCountry: viewerCountryCode, AllRegions: allRegions, FilterRegion: filterRegionID}, nil } payload, err := base64.RawURLEncoding.DecodeString(encoded) @@ -536,7 +548,7 @@ func decodeRoomListCursor(tab string, query string, countryCode string, viewerCo if err := json.Unmarshal(payload, &cursor); err != nil { return roomListCursor{}, xerr.New(xerr.InvalidArgument, "cursor is invalid") } - if cursor.Tab != tab || cursor.Query != query || cursor.CountryCode != countryCode || cursor.ViewerCountry != viewerCountryCode || cursor.AllRegions != allRegions || cursor.RoomID == "" { + if cursor.Tab != tab || cursor.Query != query || cursor.CountryCode != countryCode || cursor.ViewerCountry != viewerCountryCode || cursor.AllRegions != allRegions || cursor.FilterRegion != filterRegionID || cursor.RoomID == "" { return roomListCursor{}, xerr.New(xerr.InvalidArgument, "cursor is invalid") } @@ -545,13 +557,14 @@ func decodeRoomListCursor(tab string, query string, countryCode string, viewerCo // encodeRoomListCursor 把最后一条列表记录编码成下一页边界。 // cursor 不暴露契约语义,后续调整排序字段时可以只兼容服务端解析逻辑。 -func encodeRoomListCursor(tab string, query string, countryCode string, viewerCountryCode string, allRegions bool, entry RoomListEntry) string { +func encodeRoomListCursor(tab string, query string, countryCode string, viewerCountryCode string, allRegions bool, filterRegionID int64, entry RoomListEntry) string { cursor := roomListCursor{ Tab: tab, Query: query, CountryCode: countryCode, ViewerCountry: viewerCountryCode, AllRegions: allRegions, + FilterRegion: filterRegionID, SortScore: entry.SortScore, CreatedAtMS: entry.CreatedAtMS, UpdatedAtMS: entry.UpdatedAtMS, diff --git a/services/room-service/internal/room/service/moderation.go b/services/room-service/internal/room/service/moderation.go index b93e1894..d222eaa0 100644 --- a/services/room-service/internal/room/service/moderation.go +++ b/services/room-service/internal/room/service/moderation.go @@ -40,6 +40,12 @@ func (s *Service) MuteUser(ctx context.Context, req *roomv1.MuteUserRequest) (*r if err := canManageTarget(current, cmd.ActorUserID(), cmd.TargetUserID); err != nil { return mutationResult{}, nil, err } + if cmd.Muted { + if err := s.requireTargetWithoutVIPBenefit(ctx, req.GetMeta().GetRequestId(), cmd.TargetUserID, vipBenefitAntiMute); err != nil { + // anti_mute 只阻止普通房主/管理员新增禁言;解除既有禁言必须始终允许。 + return mutationResult{}, nil, err + } + } if current.MuteUsers[cmd.TargetUserID] == cmd.Muted { // 重复设置同一禁言状态是业务 no-op,仍由 pipeline 写 command log 做幂等保护。 return mutationResult{snapshot: current.ToProto()}, nil, nil @@ -117,6 +123,10 @@ func (s *Service) KickUser(ctx context.Context, req *roomv1.KickUserRequest) (*r if err := canManageTarget(current, cmd.ActorUserID(), cmd.TargetUserID); err != nil { return mutationResult{}, nil, err } + if err := s.requireTargetWithoutVIPBenefit(ctx, req.GetMeta().GetRequestId(), cmd.TargetUserID, vipBenefitAntiKick); err != nil { + // 平台封禁、风控和后台治理使用独立 SystemEvictUser;只有普通房间治理受 anti_kick 保护。 + return mutationResult{}, nil, err + } _, inRoom := current.OnlineUsers[cmd.TargetUserID] _, onSeat := current.SeatByUser(cmd.TargetUserID) diff --git a/services/room-service/internal/room/service/pin_test.go b/services/room-service/internal/room/service/pin_test.go index ef761441..39e333fa 100644 --- a/services/room-service/internal/room/service/pin_test.go +++ b/services/room-service/internal/room/service/pin_test.go @@ -155,6 +155,169 @@ func TestPinnedRoomListOrdersRegionCountryThenCountryBucketsForNew(t *testing.T) } } +func TestAllRegionRoomListKeepsPinsThenCountryPresenceBuckets(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + svc := roomservice.New(roomservice.Config{ + NodeID: "node-all-region-order-test", + LeaseTTL: 10 * time.Second, + RankLimit: 20, + SnapshotEveryN: 1, + }, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher()) + + createPinnedListRoom(t, ctx, svc, "room-global-pin", "global-pin", 3221, 9002, "AE") + createPinnedListRoom(t, ctx, svc, "room-region-pin-all", "region-pin-all", 3222, 9002, "AE") + createPinnedListRoom(t, ctx, svc, "room-country-pin-all", "country-pin-all", 3223, 9001, "US") + createPinnedListRoom(t, ctx, svc, "room-viewer-online-all", "viewer-online-all", 3224, 9001, "US") + createPinnedListRoom(t, ctx, svc, "room-other-online-all", "other-online-all", 3225, 9002, "AE") + createPinnedListRoom(t, ctx, svc, "room-viewer-empty-all", "viewer-empty-all", 3226, 9002, "US") + createPinnedListRoom(t, ctx, svc, "room-other-empty-all", "other-empty-all", 3227, 9001, "AE") + for index, roomID := range []string{ + "room-global-pin", + "room-region-pin-all", + "room-country-pin-all", + "room-viewer-online-all", + "room-other-online-all", + "room-viewer-empty-all", + "room-other-empty-all", + } { + repository.SetRoomSortScore(roomID, int64(1000-index)) + } + repository.SetRoomPresence("room-viewer-online-all", 1, 0) + repository.SetRoomPresence("room-other-online-all", 1, 0) + repository.SetRoomPresence("room-viewer-empty-all", 0, 0) + repository.SetRoomPresence("room-other-empty-all", 0, 0) + expiresAtMS := time.Now().UTC().Add(24 * time.Hour).UnixMilli() + repository.PinRoomWithType("room-global-pin", "global", 0, 100, expiresAtMS) + repository.PinRoomWithType("room-region-pin-all", "region", 9002, 90, expiresAtMS) + repository.PinRoomWithType("room-country-pin-all", "country", 9001, 80, expiresAtMS) + + page, err := svc.ListRooms(ctx, &roomv1.ListRoomsRequest{ + Meta: &roomv1.RequestMeta{AppCode: appcode.Default}, + ViewerUserId: 4001, + VisibleRegionId: 9001, + ViewerCountryCode: "US", + AllVisibleRegions: true, + Tab: "hot", + Limit: 10, + }) + if err != nil { + t.Fatalf("list all-region rooms failed: %v", err) + } + want := []string{ + "room-global-pin", + "room-region-pin-all", + "room-country-pin-all", + "room-viewer-online-all", + "room-other-online-all", + "room-viewer-empty-all", + "room-other-empty-all", + } + if got := roomIDs(page.GetRooms()); len(got) != len(want) { + t.Fatalf("all-region room count mismatch: got=%v want=%v", got, want) + } else { + for index := range want { + if got[index] != want[index] { + t.Fatalf("all-region order mismatch: got=%v want=%v", got, want) + } + } + } +} + +func TestAllRegionPinTypePrecedenceMatchesRedisFallbackOrder(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + svc := roomservice.New(roomservice.Config{ + NodeID: "node-pin-type-precedence-test", + LeaseTTL: 10 * time.Second, + RankLimit: 20, + SnapshotEveryN: 1, + }, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher()) + + createPinnedListRoom(t, ctx, svc, "room-pin-a", "pin-a", 3241, 9001, "US") + createPinnedListRoom(t, ctx, svc, "room-pin-b", "pin-b", 3242, 9001, "US") + expiresAtMS := time.Now().UTC().Add(24 * time.Hour).UnixMilli() + // MySQL CASE 对同房间固定先选 global=10,不会让 region=100 覆盖;因此 B(region=50) 必须排在 A 前。 + repository.PinRoomWithType("room-pin-a", "global", 0, 10, expiresAtMS) + repository.PinRoomWithType("room-pin-a", "region", 9001, 100, expiresAtMS) + repository.PinRoomWithType("room-pin-b", "region", 9001, 50, expiresAtMS) + + page, err := svc.ListRooms(ctx, &roomv1.ListRoomsRequest{ + Meta: &roomv1.RequestMeta{AppCode: appcode.Default}, + ViewerUserId: 4001, + VisibleRegionId: 9001, + AllVisibleRegions: true, + Tab: "hot", + Limit: 10, + }) + if err != nil { + t.Fatalf("list fallback pin precedence failed: %v", err) + } + if got := roomIDs(page.GetRooms()); len(got) != 2 || got[0] != "room-pin-b" || got[1] != "room-pin-a" { + t.Fatalf("MySQL fallback must order B(region=50) before A(global=10 suppressing region=100), got=%v", got) + } +} + +func TestRoomListRegionFilterBindsCursorAndCountryFilterSpansRegions(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + svc := roomservice.New(roomservice.Config{ + NodeID: "node-room-filter-test", + LeaseTTL: 10 * time.Second, + RankLimit: 20, + SnapshotEveryN: 1, + }, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher()) + + createPinnedListRoom(t, ctx, svc, "room-region-2-newer", "region-2-newer", 3231, 9002, "AE") + createPinnedListRoom(t, ctx, svc, "room-region-2-older", "region-2-older", 3232, 9002, "AE") + createPinnedListRoom(t, ctx, svc, "room-region-3-ae", "region-3-ae", 3233, 9003, "AE") + repository.SetRoomSortScore("room-region-2-newer", 300) + repository.SetRoomSortScore("room-region-2-older", 200) + repository.SetRoomSortScore("room-region-3-ae", 100) + + firstPage, err := svc.ListRooms(ctx, &roomv1.ListRoomsRequest{ + Meta: &roomv1.RequestMeta{AppCode: appcode.Default}, + ViewerUserId: 4001, + VisibleRegionId: 9001, + FilterRegionId: 9002, + Tab: "hot", + Limit: 1, + }) + if err != nil { + t.Fatalf("list region-filtered first page failed: %v", err) + } + if got := roomIDs(firstPage.GetRooms()); len(got) != 1 || got[0] != "room-region-2-newer" || firstPage.GetNextCursor() == "" { + t.Fatalf("region-filtered first page mismatch: rooms=%v cursor=%q", got, firstPage.GetNextCursor()) + } + if _, err := svc.ListRooms(ctx, &roomv1.ListRoomsRequest{ + Meta: &roomv1.RequestMeta{AppCode: appcode.Default}, + ViewerUserId: 4001, + VisibleRegionId: 9001, + FilterRegionId: 9003, + Tab: "hot", + Limit: 1, + Cursor: firstPage.GetNextCursor(), + }); err == nil { + t.Fatal("region cursor must not be reusable for another explicit region") + } + + countryPage, err := svc.ListRooms(ctx, &roomv1.ListRoomsRequest{ + Meta: &roomv1.RequestMeta{AppCode: appcode.Default}, + ViewerUserId: 4001, + VisibleRegionId: 9001, + AllVisibleRegions: true, + CountryCode: "AE", + Tab: "hot", + Limit: 10, + }) + if err != nil { + t.Fatalf("list all-region country rooms failed: %v", err) + } + if got := roomIDs(countryPage.GetRooms()); len(got) != 3 { + t.Fatalf("country filter must span all mapped room regions, got=%v", got) + } +} + func TestCountryPinOnlyAppliesToSelectedCountryTab(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) diff --git a/services/room-service/internal/room/service/presence.go b/services/room-service/internal/room/service/presence.go index b475ac33..bbe7286a 100644 --- a/services/room-service/internal/room/service/presence.go +++ b/services/room-service/internal/room/service/presence.go @@ -45,6 +45,20 @@ func (s *Service) JoinRoom(ctx context.Context, req *roomv1.JoinRoomRequest) (*r // 客户端不传角色时按普通观众进入房间。 cmd.Role = "audience" } + // 进房展示只查询一次 wallet effective state,并在响应、首次 outbox 与重复进房 direct IM 之间复用。 + // 查询失败不阻断核心 presence:VIP 入场表现可以降级,但房间可用性不能被纯展示依赖拖垮。 + joinVIP := effectiveVIPAccess{} + if !cmd.ActorIsRobot && cmd.ActorUserID() > 0 && cmd.RoomID() != "" && cmd.ID() != "" { + if loadedVIP, lookupErr := s.loadEffectiveVIPAccess(ctx, cmd.RequestID, cmd.ActorUserID()); lookupErr != nil { + logx.Warn(ctx, "room_join_vip_lookup_failed", + slog.String("room_id", cmd.RoomID()), + slog.Int64("user_id", cmd.ActorUserID()), + slog.String("error", lookupErr.Error()), + ) + } else { + joinVIP = loadedVIP + } + } reactivateClosedRoom, err := s.roomEntryPolicy(ctx, cmd.RoomID(), cmd.ActorUserID()) if err != nil { return nil, err @@ -90,7 +104,7 @@ func (s *Service) JoinRoom(ctx context.Context, req *roomv1.JoinRoomRequest) (*r existing.LastSeenAtMS = now.UnixMilli() current.Version++ - joinedDisplayEvent, err := outbox.Build(current.RoomID, "RoomUserJoined", current.Version, now, roomUserJoinedEventFromCommand(cmd, firstNonEmpty(existing.Role, cmd.Role), current.VisibleRegionID)) + joinedDisplayEvent, err := outbox.Build(current.RoomID, "RoomUserJoined", current.Version, now, roomUserJoinedEventFromCommand(cmd, firstNonEmpty(existing.Role, cmd.Role), current.VisibleRegionID, joinVIP)) if err != nil { return mutationResult{}, nil, err } @@ -109,7 +123,7 @@ func (s *Service) JoinRoom(ctx context.Context, req *roomv1.JoinRoomRequest) (*r current.Version++ // JoinRoom 成功需要 outbox 事件,腾讯云 IM 房间系统消息由 worker 异步投递。 - joinedEvent, err := outbox.Build(current.RoomID, "RoomUserJoined", current.Version, now, roomUserJoinedEventFromCommand(cmd, joinRole, current.VisibleRegionID)) + joinedEvent, err := outbox.Build(current.RoomID, "RoomUserJoined", current.Version, now, roomUserJoinedEventFromCommand(cmd, joinRole, current.VisibleRegionID, joinVIP)) if err != nil { return mutationResult{}, nil, err } @@ -127,7 +141,7 @@ func (s *Service) JoinRoom(ctx context.Context, req *roomv1.JoinRoomRequest) (*r RoomVersion: current.Version, // syncEvent 与 outbox 事件保持同一份快照,避免低延迟路径和补偿路径 payload 不一致。 EntryVehicle: imEntryVehicleFromCommand(cmd.EntryVehicle), - Attributes: roomUserJoinedIMAttributes(joinRole, cmd.ActorDisplayProfile), + Attributes: roomUserJoinedIMAttributes(joinRole, cmd.ActorDisplayProfile, joinVIP), } return result, []outbox.Record{joinedEvent}, nil }) @@ -137,9 +151,10 @@ func (s *Service) JoinRoom(ctx context.Context, req *roomv1.JoinRoomRequest) (*r s.projectRoomVisitBestEffort(ctx, cmd.ActorUserID(), cmd.RoomID()) return &roomv1.JoinRoomResponse{ - Result: commandResult(result.applied, result.snapshot.GetVersion(), s.clock.Now()), - User: result.user, - Room: joinRoomResponseSnapshot(result.snapshot, req.GetResponseMode()), + Result: commandResult(result.applied, result.snapshot.GetVersion(), s.clock.Now()), + User: result.user, + Room: joinRoomResponseSnapshot(result.snapshot, req.GetResponseMode()), + EffectiveVip: joinVIP.roomSnapshot(), }, nil } @@ -185,35 +200,43 @@ func userDisplayProfileFromProto(item *roomv1.RoomUserDisplayProfile) command.Us } } -func roomUserJoinedEventFromCommand(cmd command.JoinRoom, role string, visibleRegionID int64) *roomeventsv1.RoomUserJoined { +func roomUserJoinedEventFromCommand(cmd command.JoinRoom, role string, visibleRegionID int64, vip effectiveVIPAccess) *roomeventsv1.RoomUserJoined { profile := cmd.ActorDisplayProfile // 事件 body 是 direct IM 和 outbox 补偿的共同来源,展示字段必须和统计字段一起固定在命令提交时刻。 return &roomeventsv1.RoomUserJoined{ - UserId: cmd.ActorUserID(), - Role: role, - VisibleRegionId: visibleRegionID, - CountryId: cmd.ActorCountryID, - RegionId: firstNonZeroInt64(cmd.ActorRegionID, visibleRegionID), - IsRobot: cmd.ActorIsRobot, - EntryVehicle: eventEntryVehicleFromCommand(cmd.EntryVehicle), - Nickname: strings.TrimSpace(profile.Nickname), - Avatar: strings.TrimSpace(profile.Avatar), - DisplayUserId: strings.TrimSpace(profile.DisplayUserID), - PrettyDisplayUserId: strings.TrimSpace(profile.PrettyDisplayUserID), + UserId: cmd.ActorUserID(), + Role: role, + VisibleRegionId: visibleRegionID, + CountryId: cmd.ActorCountryID, + RegionId: firstNonZeroInt64(cmd.ActorRegionID, visibleRegionID), + IsRobot: cmd.ActorIsRobot, + EntryVehicle: eventEntryVehicleFromCommand(cmd.EntryVehicle), + Nickname: strings.TrimSpace(profile.Nickname), + Avatar: strings.TrimSpace(profile.Avatar), + DisplayUserId: strings.TrimSpace(profile.DisplayUserID), + PrettyDisplayUserId: strings.TrimSpace(profile.PrettyDisplayUserID), + VipProgramType: vip.programType, + EffectiveVipLevel: vip.level, + EffectiveVipName: vip.name, + RoomEntryNoticeEnabled: vip.roomEntryNoticeEnabled(), } } -func roomUserJoinedIMAttributes(role string, profile command.UserDisplayProfile) map[string]string { +func roomUserJoinedIMAttributes(role string, profile command.UserDisplayProfile, vip effectiveVIPAccess) map[string]string { values := map[string]string{ - "role": strings.TrimSpace(role), - "nickname": strings.TrimSpace(profile.Nickname), - "avatar": strings.TrimSpace(profile.Avatar), - "display_user_id": strings.TrimSpace(profile.DisplayUserID), - "pretty_display_user_id": strings.TrimSpace(profile.PrettyDisplayUserID), + "role": strings.TrimSpace(role), + "nickname": strings.TrimSpace(profile.Nickname), + "avatar": strings.TrimSpace(profile.Avatar), + "display_user_id": strings.TrimSpace(profile.DisplayUserID), + "pretty_display_user_id": strings.TrimSpace(profile.PrettyDisplayUserID), + "vip_program_type": vip.programType, + "effective_vip_level": int32String(vip.level), + "effective_vip_name": vip.name, + "room_entry_notice_enabled": boolString(vip.roomEntryNoticeEnabled()), } - // 空字段不进 IM payload,避免客户端把空字符串误判为后端明确清空资料。 + // 资料空字段不进 IM payload;VIP level/notice 即使为零值也必须保留,客户端据此明确关闭 VIP 入场表现。 for key, value := range values { - if value == "" { + if value == "" && key != "effective_vip_name" { delete(values, key) } } diff --git a/services/room-service/internal/room/service/repository.go b/services/room-service/internal/room/service/repository.go index 4770f424..532ed4fb 100644 --- a/services/room-service/internal/room/service/repository.go +++ b/services/room-service/internal/room/service/repository.go @@ -516,9 +516,11 @@ type RoomContributionRankStore interface { type RoomListQuery struct { // AppCode 是列表查询所属 App,通常来自 gateway RequestMeta。 AppCode string - // VisibleRegionID 是服务端解析出的用户区域,客户端不能伪造。 + // VisibleRegionID 是服务端解析出的用户区域,用于未显式筛选时的默认范围。 VisibleRegionID int64 - // AllVisibleRegions 只服务后台白名单用户;为 true 时列表读模型不再按 VisibleRegionID 收敛。 + // FilterRegionID 是 gateway 校验过的客户端区域筛选;非零时覆盖默认 VisibleRegionID。 + FilterRegionID int64 + // AllVisibleRegions 由 gateway 根据 App 策略或白名单注入;为 true 时列表读模型不再按 VisibleRegionID 收敛。 AllVisibleRegions bool // Tab 只允许 hot/new,决定公共发现列表排序字段。 Tab string @@ -528,9 +530,9 @@ type RoomListQuery struct { OwnerUserIDs []int64 // Query 非空时按 room_id 或 title 做包含匹配。 Query string - // CountryCode 非空时只返回房主国家命中的房间;gateway 必须先校验它属于当前用户区域。 + // CountryCode 非空时只返回房主国家命中的房间;gateway 必须先校验它属于 active 区域。 CountryCode string - // ViewerCountryCode 是当前用户国家;公共列表不按它过滤,只用它在区域内把本国家房间排到同状态房间前。 + // ViewerCountryCode 是当前用户国家;公共列表不按它过滤,只用它在 All/区域列表中把本国家房间排到同在线状态的其他房间前。 ViewerCountryCode string // Limit 是实际查询数量,service 层会限制最大值。 Limit int diff --git a/services/room-service/internal/room/service/room_list_cache.go b/services/room-service/internal/room/service/room_list_cache.go index 6094afdb..70ef6121 100644 --- a/services/room-service/internal/room/service/room_list_cache.go +++ b/services/room-service/internal/room/service/room_list_cache.go @@ -13,8 +13,10 @@ import ( ) const ( - roomListCacheReadyValue = "1" + // v2 表示独立 namespace 已同时重建区域桶和全区桶;ready 之前一律回退 MySQL。 + roomListCacheReadyValue = "2" roomListCacheCountryAll = "_" + roomListCacheAllRegionsScope = "all" roomListCacheBucketOnline = "online" roomListCacheBucketEmpty = "empty" roomListCacheDefaultScanSize = 128 @@ -43,6 +45,8 @@ type roomListCachePinRow struct { type roomListCacheCandidate struct { Entry RoomListEntry SortValue int64 + // PinType 只用于同一房间命中多种置顶时复刻 MySQL CASE 的 global > region > country 选择优先级。 + PinType string } // NewRedisRoomListCacheStore 创建公共发现页 Redis 展示读模型。 @@ -65,10 +69,16 @@ func (s *RedisRoomListCacheStore) ListRoomListEntries(ctx context.Context, query if query.NowMS <= 0 { return nil, false, nil } - ready, err := s.client.Exists(ctx, roomListCacheReadyKey(query.AppCode)).Result() - if err != nil || ready == 0 { + ready, err := s.client.Get(ctx, roomListCacheReadyKey(query.AppCode)).Result() + if err == redis.Nil { + return nil, false, nil + } + if err != nil { return nil, false, err } + if ready != roomListCacheReadyValue { + return nil, false, nil + } scanSize := roomListCacheScanSize(query.Limit) candidates := make(map[string]roomListCacheCandidate, scanSize) @@ -100,7 +110,7 @@ func (s *RedisRoomListCacheStore) ListRoomListEntries(ctx context.Context, query card.PinListRank = rank card.PinWeight = row.Pin.Weight card.PinnedUntilMS = row.Pin.ExpiresAtMS - roomListCacheKeepBest(candidates, roomListCacheCandidate{Entry: card, SortValue: roomListCacheSortValue(query.Tab, card)}) + roomListCacheKeepBest(candidates, roomListCacheCandidate{Entry: card, SortValue: roomListCacheSortValue(query.Tab, card), PinType: row.Pin.PinType}) } normalIDs, normalTruncated, err := s.listRoomListCacheNormalRoomIDs(ctx, query, scanSize) @@ -241,16 +251,18 @@ func (s *RedisRoomListCacheStore) UpsertRoomPin(ctx context.Context, pin RoomLis if err != nil { return err } - ref := roomListCachePinRef(app, pin) - rawRefs, err := json.Marshal([]roomListCacheMemberRef{ref}) + refs := roomListCachePinRefs(app, pin) + rawRefs, err := json.Marshal(refs) if err != nil { return err } pipe := s.client.Pipeline() - pipe.SAdd(ctx, roomListCacheKnownKeysKey(app), ref.Key) pipe.HSet(ctx, roomListCachePinPayloadKey(app), strconv.FormatInt(pin.ID, 10), payload) pipe.HSet(ctx, roomListCachePinIndexKey(app), strconv.FormatInt(pin.ID, 10), rawRefs) - pipe.ZAdd(ctx, ref.Key, redis.Z{Score: -float64(pin.Weight), Member: ref.Member}) + for _, ref := range refs { + pipe.SAdd(ctx, roomListCacheKnownKeysKey(app), ref.Key) + pipe.ZAdd(ctx, ref.Key, redis.Z{Score: -float64(pin.Weight), Member: ref.Member}) + } _, err = pipe.Exec(ctx) return err } @@ -350,12 +362,18 @@ func (s *RedisRoomListCacheStore) removeRoomListPinIndexes(ctx context.Context, } func (s *RedisRoomListCacheStore) listRoomListCachePins(ctx context.Context, query RoomListQuery, scanSize int) ([]roomListCachePinRow, bool, error) { - keys := []string{ - roomListCachePinKey(query.AppCode, roomPinTypeGlobal, 0), - roomListCachePinKey(query.AppCode, roomPinTypeRegion, normalizeVisibleRegionID(query.VisibleRegionID)), - } - if roomListCacheSortCountry(query) != "" { - keys = append(keys, roomListCachePinKey(query.AppCode, roomPinTypeCountry, normalizeVisibleRegionID(query.VisibleRegionID))) + keys := []string{roomListCachePinKey(query.AppCode, roomPinTypeGlobal, 0)} + if query.AllVisibleRegions { + // All 列表不能复用 region=0;0 是真实 GLOBAL 桶,独立 all key 才能合并每个区域的置顶事实。 + keys = append(keys, roomListCacheAllRegionsPinKey(query.AppCode, roomPinTypeRegion)) + if roomListCacheSortCountry(query) != "" { + keys = append(keys, roomListCacheAllRegionsPinKey(query.AppCode, roomPinTypeCountry)) + } + } else { + keys = append(keys, roomListCachePinKey(query.AppCode, roomPinTypeRegion, normalizeVisibleRegionID(query.VisibleRegionID))) + if roomListCacheSortCountry(query) != "" { + keys = append(keys, roomListCachePinKey(query.AppCode, roomPinTypeCountry, normalizeVisibleRegionID(query.VisibleRegionID))) + } } pinIDs := make([]string, 0, len(keys)*scanSize) @@ -487,8 +505,36 @@ func uniqueRoomListCacheIDs(values []string) []string { func roomListCacheKeepBest(candidates map[string]roomListCacheCandidate, candidate roomListCacheCandidate) { current, exists := candidates[candidate.Entry.RoomID] - if !exists || roomListCacheCandidateBefore(candidate, current) { + if !exists { candidates[candidate.Entry.RoomID] = candidate + return + } + if candidate.Entry.IsPinned && current.Entry.IsPinned { + candidatePrecedence := roomListCachePinTypePrecedence(candidate.PinType) + currentPrecedence := roomListCachePinTypePrecedence(current.PinType) + if candidatePrecedence != currentPrecedence { + // MySQL 对同房间先选 global,其次 region,最后 country;不允许次级类型用更高 weight 反超。 + if candidatePrecedence < currentPrecedence { + candidates[candidate.Entry.RoomID] = candidate + } + return + } + } + if roomListCacheCandidateBefore(candidate, current) { + candidates[candidate.Entry.RoomID] = candidate + } +} + +func roomListCachePinTypePrecedence(pinType string) int { + switch roomListCacheNormalizePinType(pinType) { + case roomPinTypeGlobal: + return 0 + case roomPinTypeRegion: + return 1 + case roomPinTypeCountry: + return 2 + default: + return 3 } } @@ -535,7 +581,7 @@ func roomListCacheCardMatches(query RoomListQuery, entry RoomListEntry) bool { if appcode.Normalize(entry.AppCode) != appcode.Normalize(query.AppCode) || entry.Status != "active" { return false } - if normalizeVisibleRegionID(entry.VisibleRegionID) != normalizeVisibleRegionID(query.VisibleRegionID) { + if !query.AllVisibleRegions && normalizeVisibleRegionID(entry.VisibleRegionID) != normalizeVisibleRegionID(query.VisibleRegionID) { return false } if country := normalizeRoomCountryCode(query.CountryCode); country != "" && normalizeRoomCountryCode(entry.OwnerCountryCode) != country { @@ -549,9 +595,16 @@ func roomListCachePinApplies(query RoomListQuery, pin RoomListPinEntry, entry Ro case roomPinTypeGlobal: return pin.VisibleRegionID == 0 case roomPinTypeRegion: + if query.AllVisibleRegions { + return normalizeVisibleRegionID(pin.VisibleRegionID) == normalizeVisibleRegionID(entry.VisibleRegionID) + } return normalizeVisibleRegionID(pin.VisibleRegionID) == normalizeVisibleRegionID(query.VisibleRegionID) case roomPinTypeCountry: - return normalizeVisibleRegionID(pin.VisibleRegionID) == normalizeVisibleRegionID(query.VisibleRegionID) && normalizeRoomCountryCode(entry.OwnerCountryCode) == roomListCacheSortCountry(query) + pinRegionID := normalizeVisibleRegionID(query.VisibleRegionID) + if query.AllVisibleRegions { + pinRegionID = normalizeVisibleRegionID(entry.VisibleRegionID) + } + return normalizeVisibleRegionID(pin.VisibleRegionID) == pinRegionID && normalizeRoomCountryCode(entry.OwnerCountryCode) == roomListCacheSortCountry(query) default: return false } @@ -611,16 +664,22 @@ func roomListCacheEntryRefs(app string, entry RoomListEntry) []roomListCacheMemb if entry.OnlineCount > 0 { bucket = roomListCacheBucketOnline } - refs := make([]roomListCacheMemberRef, 0, 4) + refs := make([]roomListCacheMemberRef, 0, 8) for _, tab := range []string{roomListTabHot, roomListTabNew} { refs = append(refs, roomListCacheMemberRef{ Key: roomListCacheBaseKey(app, tab, entry.VisibleRegionID, roomListCacheCountryAll, bucket), Member: entry.RoomID, + }, roomListCacheMemberRef{ + Key: roomListCacheAllRegionsBaseKey(app, tab, roomListCacheCountryAll, bucket), + Member: entry.RoomID, }) if country := normalizeRoomCountryCode(entry.OwnerCountryCode); country != "" { refs = append(refs, roomListCacheMemberRef{ Key: roomListCacheBaseKey(app, tab, entry.VisibleRegionID, country, bucket), Member: entry.RoomID, + }, roomListCacheMemberRef{ + Key: roomListCacheAllRegionsBaseKey(app, tab, country, bucket), + Member: entry.RoomID, }) } } @@ -638,31 +697,44 @@ func roomListCacheNormalKeys(query RoomListQuery) []string { app := appcode.Normalize(query.AppCode) regionID := normalizeVisibleRegionID(query.VisibleRegionID) sortCountry := roomListCacheSortCountry(query) + key := func(country string, bucket string) string { + if query.AllVisibleRegions { + return roomListCacheAllRegionsBaseKey(app, query.Tab, country, bucket) + } + return roomListCacheBaseKey(app, query.Tab, regionID, country, bucket) + } if filterCountry := normalizeRoomCountryCode(query.CountryCode); filterCountry != "" { return []string{ - roomListCacheBaseKey(app, query.Tab, regionID, filterCountry, roomListCacheBucketOnline), - roomListCacheBaseKey(app, query.Tab, regionID, filterCountry, roomListCacheBucketEmpty), + key(filterCountry, roomListCacheBucketOnline), + key(filterCountry, roomListCacheBucketEmpty), } } if sortCountry != "" { return []string{ - roomListCacheBaseKey(app, query.Tab, regionID, sortCountry, roomListCacheBucketOnline), - roomListCacheBaseKey(app, query.Tab, regionID, roomListCacheCountryAll, roomListCacheBucketOnline), - roomListCacheBaseKey(app, query.Tab, regionID, sortCountry, roomListCacheBucketEmpty), - roomListCacheBaseKey(app, query.Tab, regionID, roomListCacheCountryAll, roomListCacheBucketEmpty), + key(sortCountry, roomListCacheBucketOnline), + key(roomListCacheCountryAll, roomListCacheBucketOnline), + key(sortCountry, roomListCacheBucketEmpty), + key(roomListCacheCountryAll, roomListCacheBucketEmpty), } } return []string{ - roomListCacheBaseKey(app, query.Tab, regionID, roomListCacheCountryAll, roomListCacheBucketOnline), - roomListCacheBaseKey(app, query.Tab, regionID, roomListCacheCountryAll, roomListCacheBucketEmpty), + key(roomListCacheCountryAll, roomListCacheBucketOnline), + key(roomListCacheCountryAll, roomListCacheBucketEmpty), } } -func roomListCachePinRef(app string, pin RoomListPinEntry) roomListCacheMemberRef { - return roomListCacheMemberRef{ +func roomListCachePinRefs(app string, pin RoomListPinEntry) []roomListCacheMemberRef { + refs := []roomListCacheMemberRef{{ Key: roomListCachePinKey(app, pin.PinType, pin.VisibleRegionID), Member: roomListCachePinMember(pin), + }} + if pin.PinType == roomPinTypeRegion || pin.PinType == roomPinTypeCountry { + refs = append(refs, roomListCacheMemberRef{ + Key: roomListCacheAllRegionsPinKey(app, pin.PinType), + Member: roomListCachePinMember(pin), + }) } + return refs } func roomListCachePinMember(pin RoomListPinEntry) string { @@ -697,7 +769,8 @@ func roomListCacheNormalizePinType(pinType string) string { } func roomListCachePrefix(app string) string { - return "room:list_cache:" + appcode.Normalize(app) + // v2 使用独立 namespace:滚动发布期间旧进程仍会按 v1 的 4-ref 索引删改,绝不能触碰新进程的 8-ref All 索引。 + return "room:list_cache:v2:" + appcode.Normalize(app) } func roomListCacheReadyKey(app string) string { @@ -732,9 +805,22 @@ func roomListCacheBaseKey(app string, tab string, regionID int64, country string return fmt.Sprintf("%s:base:%s:%d:%s:%s", roomListCachePrefix(app), tab, normalizeVisibleRegionID(regionID), country, bucket) } +func roomListCacheAllRegionsBaseKey(app string, tab string, country string, bucket string) string { + country = normalizeRoomCountryCode(country) + if country == "" { + country = roomListCacheCountryAll + } + // all 使用文本 scope,不和业务上的 visible_region_id=0 GLOBAL 桶共用任何 key。 + return fmt.Sprintf("%s:base:%s:%s:%s:%s", roomListCachePrefix(app), roomListCacheAllRegionsScope, tab, country, bucket) +} + func roomListCachePinKey(app string, pinType string, regionID int64) string { if pinType == roomPinTypeGlobal { regionID = 0 } return fmt.Sprintf("%s:pin:%s:%d", roomListCachePrefix(app), pinType, normalizeVisibleRegionID(regionID)) } + +func roomListCacheAllRegionsPinKey(app string, pinType string) string { + return fmt.Sprintf("%s:pin:%s:%s", roomListCachePrefix(app), roomListCacheAllRegionsScope, pinType) +} diff --git a/services/room-service/internal/room/service/room_list_cache_test.go b/services/room-service/internal/room/service/room_list_cache_test.go index 3c062549..0d533a75 100644 --- a/services/room-service/internal/room/service/room_list_cache_test.go +++ b/services/room-service/internal/room/service/room_list_cache_test.go @@ -2,6 +2,7 @@ package service import ( "sort" + "strings" "testing" ) @@ -71,6 +72,91 @@ func TestRoomListCacheCountryPinOnlyAppliesToSelectedCountry(t *testing.T) { } } +func TestRoomListCacheAllRegionsUsesDedicatedIndexesWithoutReusingGlobalRegion(t *testing.T) { + query := RoomListQuery{ + AppCode: "huwaa", + VisibleRegionID: 9001, + AllVisibleRegions: true, + ViewerCountryCode: "US", + Tab: roomListTabHot, + } + if !roomListCacheEligible(query) { + t.Fatal("all-region hot/new homepage queries must be cache eligible") + } + legacyPrefix := "room:list_cache:huwaa" + if got := roomListCachePrefix("huwaa"); got == legacyPrefix || !strings.HasPrefix(got, "room:list_cache:v2:") { + t.Fatalf("v2 cache must use a namespace isolated from rolling v1 writers: got=%q legacy=%q", got, legacyPrefix) + } + if got := roomListCacheReadyKey("huwaa"); strings.HasPrefix(got, legacyPrefix+":") { + t.Fatalf("v1 ready=1 must not make the v2 cache readable: %q", got) + } + keys := roomListCacheNormalKeys(query) + if len(keys) != 4 { + t.Fatalf("all-region viewer-country query keys mismatch: %v", keys) + } + for _, key := range keys { + if !strings.Contains(key, ":base:all:hot:") { + t.Fatalf("all-region query must use dedicated all scope, got %q", key) + } + if key == roomListCacheBaseKey("huwaa", roomListTabHot, 0, roomListCacheCountryAll, roomListCacheBucketOnline) { + t.Fatalf("all-region key must not alias visible_region_id=0 GLOBAL bucket: %q", key) + } + } + + entry := roomListCacheTestEntry("other-region", "AE", 1, 100, 0) + entry.AppCode = "huwaa" + entry.VisibleRegionID = 9002 + if !roomListCacheCardMatches(query, entry) { + t.Fatal("all-region query must accept a card from another region") + } + refs := roomListCacheEntryRefs("huwaa", entry) + hasRegionalIndex := false + hasAllIndex := false + for _, ref := range refs { + hasRegionalIndex = hasRegionalIndex || strings.Contains(ref.Key, ":base:hot:9002:") + hasAllIndex = hasAllIndex || strings.Contains(ref.Key, ":base:all:hot:") + } + if !hasRegionalIndex || !hasAllIndex { + t.Fatalf("each cache card must update regional and all-region indexes: %+v", refs) + } + + regionPin := RoomListPinEntry{ID: 1, PinType: roomPinTypeRegion, VisibleRegionID: 9002, RoomID: entry.RoomID} + if !roomListCachePinApplies(query, regionPin, entry) { + t.Fatal("all-region list must retain the room's own regional pin") + } + pinRefs := roomListCachePinRefs("huwaa", regionPin) + if len(pinRefs) != 2 || pinRefs[0].Key == pinRefs[1].Key || !strings.Contains(pinRefs[1].Key, ":pin:all:region") { + t.Fatalf("regional pin must update regional and all-region indexes: %+v", pinRefs) + } +} + +func TestRoomListCachePinTypePrecedenceMatchesMySQLCaseOrder(t *testing.T) { + candidates := make(map[string]roomListCacheCandidate) + roomARegion := roomListCachePinnedTestEntry("room-a", 0, 100, 10000, 1) + roomAGlobal := roomListCachePinnedTestEntry("room-a", 0, 10, 10000, 1) + roomBRegion := roomListCachePinnedTestEntry("room-b", 0, 50, 10000, 1) + + // 先放入高权重 region,再放入低权重 global,确认同房间先选 pin type 而不是 weight。 + roomListCacheKeepBest(candidates, roomListCacheCandidate{Entry: roomARegion, SortValue: roomARegion.SortScore, PinType: roomPinTypeRegion}) + roomListCacheKeepBest(candidates, roomListCacheCandidate{Entry: roomAGlobal, SortValue: roomAGlobal.SortScore, PinType: roomPinTypeGlobal}) + roomListCacheKeepBest(candidates, roomListCacheCandidate{Entry: roomBRegion, SortValue: roomBRegion.SortScore, PinType: roomPinTypeRegion}) + + selectedA := candidates["room-a"] + if selectedA.PinType != roomPinTypeGlobal || selectedA.Entry.PinWeight != 10 { + t.Fatalf("same-room global pin must suppress higher-weight region pin exactly like MySQL CASE: %+v", selectedA) + } + ordered := make([]roomListCacheCandidate, 0, len(candidates)) + for _, candidate := range candidates { + ordered = append(ordered, candidate) + } + sort.SliceStable(ordered, func(i, j int) bool { + return roomListCacheCandidateBefore(ordered[i], ordered[j]) + }) + if len(ordered) != 2 || ordered[0].Entry.RoomID != "room-b" || ordered[1].Entry.RoomID != "room-a" { + t.Fatalf("cache order must match MySQL fallback B(region=50), A(global=10): %+v", ordered) + } +} + func roomListCacheTestEntry(roomID string, country string, online int32, sortScore int64, createdAtMS int64) RoomListEntry { return RoomListEntry{ AppCode: "lalu", diff --git a/services/room-service/internal/room/service/room_rocket_test.go b/services/room-service/internal/room/service/room_rocket_test.go index 105c5865..9c19411b 100644 --- a/services/room-service/internal/room/service/room_rocket_test.go +++ b/services/room-service/internal/room/service/room_rocket_test.go @@ -40,6 +40,9 @@ type rocketTestWallet struct { lastBatch *walletv1.BatchDebitGiftRequest balanceResponses []*walletv1.GetBalancesResponse balanceRequests []*walletv1.GetBalancesRequest + vipResponses map[int64]*walletv1.GetMyVipResponse + vipRequests []*walletv1.GetMyVipRequest + vipError error } type recordingRoomDirectIMPublisher struct { @@ -989,6 +992,17 @@ func (w *rocketTestWallet) GrantResourceGroup(_ context.Context, req *walletv1.G }, nil } +func (w *rocketTestWallet) GetMyVip(_ context.Context, req *walletv1.GetMyVipRequest) (*walletv1.GetMyVipResponse, error) { + w.vipRequests = append(w.vipRequests, proto.Clone(req).(*walletv1.GetMyVipRequest)) + if w.vipError != nil { + return nil, w.vipError + } + if response := w.vipResponses[req.GetUserId()]; response != nil { + return proto.Clone(response).(*walletv1.GetMyVipResponse), nil + } + return legacyVIPResponse(req.GetUserId()), nil +} + func (w *rocketTestWallet) GetBalances(_ context.Context, req *walletv1.GetBalancesRequest) (*walletv1.GetBalancesResponse, error) { w.balanceRequests = append(w.balanceRequests, req) if len(w.balanceResponses) == 0 { diff --git a/services/room-service/internal/room/service/vip.go b/services/room-service/internal/room/service/vip.go new file mode 100644 index 00000000..1c37eff5 --- /dev/null +++ b/services/room-service/internal/room/service/vip.go @@ -0,0 +1,141 @@ +package service + +import ( + "context" + "fmt" + "strings" + "time" + + roomv1 "hyapp.local/api/proto/room/v1" + walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" +) + +const ( + // tieredPrivilegeVIPProgram 是 P1 权益制 VIP 的稳定策略名。App 选择哪套体系由 wallet 配置决定, + // room-service 禁止再按 fami/lalu 写死分支,否则后续 App 无法复用同一房间权限实现。 + tieredPrivilegeVIPProgram = "tiered_privilege_v1" + + vipBenefitCustomRoomBackground = "custom_room_background" + vipBenefitAntiKick = "anti_kick" + vipBenefitAntiMute = "anti_mute" + vipBenefitRoomEntryNotice = "room_entry_notice" + + // VIP 查询会进入进房展示或低频房管动作,必须给同步依赖设置短上限,避免 wallet 抖动长期占住房间请求。 + roomVIPLookupTimeout = time.Second +) + +// effectiveVIPAccess 是 room-service 从 wallet effective state 裁剪出的房间权限快照。 +// paid/trial 合并、等级继承和体验卡过滤都已经由 wallet 完成,这里只做精确 benefit_code membership 判断。 +type effectiveVIPAccess struct { + programType string + level int32 + name string + benefits map[string]struct{} + roomEntryNoticeSettingEnabled bool +} + +func (access effectiveVIPAccess) hasBenefit(code string) bool { + _, exists := access.benefits[normalizeVIPCode(code)] + return exists +} + +func (access effectiveVIPAccess) roomEntryNoticeEnabled() bool { + return access.roomEntryNoticeSettingEnabled && access.hasBenefit(vipBenefitRoomEntryNotice) +} + +func (access effectiveVIPAccess) roomSnapshot() *roomv1.RoomEffectiveVipSnapshot { + return &roomv1.RoomEffectiveVipSnapshot{ + ProgramType: access.programType, + Level: access.level, + Name: access.name, + RoomEntryNoticeEnabled: access.roomEntryNoticeEnabled(), + } +} + +// loadEffectiveVIPAccess 调 wallet GetMyVip 一次并只接受完整 effective state。 +// 空 VIP 是合法结果,但 program_config 不能为空;缺配置时无法判断当前 App 是否应执行 P1 权限,必须按上游失败处理。 +func (s *Service) loadEffectiveVIPAccess(ctx context.Context, requestID string, userID int64) (effectiveVIPAccess, error) { + if s == nil || s.wallet == nil { + return effectiveVIPAccess{}, xerr.New(xerr.Unavailable, "wallet vip client is unavailable") + } + if userID <= 0 { + return effectiveVIPAccess{}, xerr.New(xerr.InvalidArgument, "vip user_id is required") + } + + lookupCtx, cancel := context.WithTimeout(ctx, roomVIPLookupTimeout) + defer cancel() + response, err := s.wallet.GetMyVip(lookupCtx, &walletv1.GetMyVipRequest{ + RequestId: strings.TrimSpace(requestID), + AppCode: appcode.FromContext(ctx), + UserId: userID, + }) + if err != nil { + return effectiveVIPAccess{}, xerr.New(xerr.Unavailable, fmt.Sprintf("get effective vip failed: %v", err)) + } + if response == nil || response.GetState() == nil || response.GetState().GetProgramConfig() == nil { + return effectiveVIPAccess{}, xerr.New(xerr.Unavailable, "wallet vip state is incomplete") + } + + state := response.GetState() + access := effectiveVIPAccess{ + programType: normalizeVIPCode(state.GetProgramConfig().GetProgramType()), + benefits: make(map[string]struct{}, len(state.GetEffectiveBenefits())), + roomEntryNoticeSettingEnabled: true, + } + // 旧 wallet 在滚动升级期间没有 user_settings tag;nil 必须兼容为产品默认开启。 + if settings := state.GetUserSettings(); settings != nil { + access.roomEntryNoticeSettingEnabled = settings.GetRoomEntryNoticeEnabled() + } + if access.programType == "" { + return effectiveVIPAccess{}, xerr.New(xerr.Unavailable, "wallet vip program is missing") + } + if effective := state.GetEffectiveVip(); effective != nil && effective.GetActive() { + access.level = effective.GetLevel() + access.name = strings.TrimSpace(effective.GetName()) + } + for _, benefit := range state.GetEffectiveBenefits() { + if benefit == nil { + continue + } + if code := normalizeVIPCode(benefit.GetBenefitCode()); code != "" { + access.benefits[code] = struct{}{} + } + } + return access, nil +} + +// requireCustomRoomBackgroundBenefit 只对配置为 P1 权益制的 App 执行自定义背景门禁。 +// legacy_timed 保持 Lalu 原行为;新 App 只需在 wallet 切换 program_type,无需再修改 room-service。 +func (s *Service) requireCustomRoomBackgroundBenefit(ctx context.Context, requestID string, ownerUserID int64) error { + access, err := s.loadEffectiveVIPAccess(ctx, requestID, ownerUserID) + if err != nil { + // 权限事实不可用时必须失败关闭;放行会让无权益用户在 wallet 故障窗口获得可持久化背景权限。 + return err + } + if access.programType != tieredPrivilegeVIPProgram { + return nil + } + if !access.hasBenefit(vipBenefitCustomRoomBackground) { + return xerr.New(xerr.PermissionDenied, "custom room background vip benefit is required") + } + return nil +} + +// requireTargetWithoutVIPBenefit 保护普通房主/管理员治理入口;平台治理必须继续走 SystemEvictUser,不能复用该守卫。 +func (s *Service) requireTargetWithoutVIPBenefit(ctx context.Context, requestID string, targetUserID int64, benefitCode string) error { + access, err := s.loadEffectiveVIPAccess(ctx, requestID, targetUserID) + if err != nil { + // anti_kick/anti_mute 属于付费保护,wallet 不可判定时宁可拒绝普通房管动作,也不能错误剥夺已生效权益。 + return err + } + if access.hasBenefit(benefitCode) { + return xerr.New(xerr.PermissionDenied, "target vip benefit prevents this room moderation action") + } + return nil +} + +func normalizeVIPCode(value string) string { + return strings.ToLower(strings.TrimSpace(value)) +} diff --git a/services/room-service/internal/room/service/vip_test.go b/services/room-service/internal/room/service/vip_test.go new file mode 100644 index 00000000..b280e93b --- /dev/null +++ b/services/room-service/internal/room/service/vip_test.go @@ -0,0 +1,266 @@ +package service_test + +import ( + "context" + "fmt" + "testing" + "time" + + "google.golang.org/protobuf/proto" + roomeventsv1 "hyapp.local/api/proto/events/room/v1" + roomv1 "hyapp.local/api/proto/room/v1" + walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/pkg/xerr" + roomservice "hyapp/services/room-service/internal/room/service" + "hyapp/services/room-service/internal/testutil/mysqltest" +) + +const vipTestAppCode = "fami" + +func TestJoinRoomCarriesEffectiveVIPAndQueriesWalletOnce(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + wallet := &rocketTestWallet{vipResponses: map[int64]*walletv1.GetMyVipResponse{ + 8202: tieredVIPResponse(8202, 4, "VIP4", "room_entry_notice"), + }} + directIM := newRecordingRoomDirectIMPublisher() + now := &fixedRoomRocketClock{now: time.Date(2026, 7, 10, 8, 0, 0, 0, time.UTC)} + svc := newRocketTestServiceWithDirectIM(t, repository, wallet, now, nil, directIM) + + roomID := "fami-vip-join-room" + createVIPRoom(t, ctx, svc, roomID, 8201) + response, err := svc.JoinRoom(ctx, &roomv1.JoinRoomRequest{ + Meta: vipRoomMeta(roomID, 8202, "join"), + Role: "audience", + }) + if err != nil { + t.Fatalf("join room failed: %v", err) + } + if response.GetEffectiveVip().GetProgramType() != "tiered_privilege_v1" || response.GetEffectiveVip().GetLevel() != 4 || response.GetEffectiveVip().GetName() != "VIP4" || !response.GetEffectiveVip().GetRoomEntryNoticeEnabled() { + t.Fatalf("join effective vip mismatch: %+v", response.GetEffectiveVip()) + } + if len(wallet.vipRequests) != 1 || wallet.vipRequests[0].GetAppCode() != vipTestAppCode || wallet.vipRequests[0].GetUserId() != 8202 { + t.Fatalf("join must query exactly one scoped effective vip state: %+v", wallet.vipRequests) + } + + waitForRoomDirectIMCounts(t, directIM, map[string]int{"RoomUserJoined": 1}) + records := directIM.recordsByType("RoomUserJoined") + if len(records) != 1 { + t.Fatalf("joined direct IM record mismatch: %+v", records) + } + var joined roomeventsv1.RoomUserJoined + if err := proto.Unmarshal(records[0].GetBody(), &joined); err != nil { + t.Fatalf("decode joined event failed: %v", err) + } + if joined.GetVipProgramType() != "tiered_privilege_v1" || joined.GetEffectiveVipLevel() != 4 || joined.GetEffectiveVipName() != "VIP4" || !joined.GetRoomEntryNoticeEnabled() { + t.Fatalf("joined event vip mismatch: %+v", &joined) + } +} + +func TestRoomEntryNoticeRequiresBenefitAndUserSetting(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + wallet := &rocketTestWallet{vipResponses: map[int64]*walletv1.GetMyVipResponse{ + 8502: tieredVIPResponseWithRoomNoticeSetting(8502, 8, "VIP8", true, true), + 8503: tieredVIPResponseWithRoomNoticeSetting(8503, 8, "VIP8", true, false), + 8504: tieredVIPResponseWithRoomNoticeSetting(8504, 8, "VIP8", false, true), + // nil user_settings 模拟滚动升级期间旧 wallet,必须按默认开启兼容。 + 8505: tieredVIPResponse(8505, 8, "VIP8", "room_entry_notice"), + }} + directIM := newRecordingRoomDirectIMPublisher() + now := &fixedRoomRocketClock{now: time.Date(2026, 7, 10, 8, 30, 0, 0, time.UTC)} + svc := newRocketTestServiceWithDirectIM(t, repository, wallet, now, nil, directIM) + roomID := "fami-vip-setting-room" + createVIPRoom(t, ctx, svc, roomID, 8501) + + wants := map[int64]bool{8502: true, 8503: false, 8504: false, 8505: true} + for userID, want := range wants { + response, err := svc.JoinRoom(ctx, &roomv1.JoinRoomRequest{ + Meta: vipRoomMeta(roomID, userID, fmt.Sprintf("settings-%d", userID)), Role: "audience", + }) + if err != nil { + t.Fatalf("join user %d failed: %v", userID, err) + } + if got := response.GetEffectiveVip().GetRoomEntryNoticeEnabled(); got != want { + t.Fatalf("room snapshot setting mismatch user=%d got=%v want=%v snapshot=%+v", userID, got, want, response.GetEffectiveVip()) + } + } + + waitForRoomDirectIMCounts(t, directIM, map[string]int{"RoomUserJoined": len(wants)}) + seen := make(map[int64]bool, len(wants)) + for _, record := range directIM.recordsByType("RoomUserJoined") { + var joined roomeventsv1.RoomUserJoined + if err := proto.Unmarshal(record.GetBody(), &joined); err != nil { + t.Fatalf("decode joined event failed: %v", err) + } + seen[joined.GetUserId()] = joined.GetRoomEntryNoticeEnabled() + } + for userID, want := range wants { + if got, exists := seen[userID]; !exists || got != want { + t.Fatalf("joined event/IM setting mismatch user=%d exists=%v got=%v want=%v", userID, exists, got, want) + } + } +} + +func TestTieredVIPCustomRoomBackgroundRequiresEffectiveBenefit(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + ownerID := int64(8301) + wallet := &rocketTestWallet{vipResponses: map[int64]*walletv1.GetMyVipResponse{ + ownerID: tieredVIPResponse(ownerID, 3, "VIP3"), + }} + now := &fixedRoomRocketClock{now: time.Date(2026, 7, 10, 9, 0, 0, 0, time.UTC)} + svc := newRocketTestServiceWithDirectIM(t, repository, wallet, now, nil, newRecordingRoomDirectIMPublisher()) + roomID := "fami-vip-background-room" + createVIPRoom(t, ctx, svc, roomID, ownerID) + + if _, err := svc.SaveRoomBackground(ctx, &roomv1.SaveRoomBackgroundRequest{ + Meta: vipRoomMeta(roomID, ownerID, "save-denied"), + RoomId: roomID, + ImageUrl: "https://cdn.example.com/fami-vip-denied.png", + }); !xerr.IsCode(err, xerr.PermissionDenied) { + t.Fatalf("tiered app without custom_room_background must be denied: %v", err) + } + + wallet.vipResponses[ownerID] = tieredVIPResponse(ownerID, 3, "VIP3", "custom_room_background") + first := saveVIPRoomBackground(t, ctx, svc, roomID, ownerID, "first", "https://cdn.example.com/fami-vip-first.png") + second := saveVIPRoomBackground(t, ctx, svc, roomID, ownerID, "second", "https://cdn.example.com/fami-vip-second.png") + if _, err := svc.SetRoomBackground(ctx, &roomv1.SetRoomBackgroundRequest{ + Meta: vipRoomMeta(roomID, ownerID, "set-allowed"), + BackgroundId: first.GetBackgroundId(), + }); err != nil { + t.Fatalf("effective custom_room_background benefit must allow set: %v", err) + } + + wallet.vipResponses[ownerID] = tieredVIPResponse(ownerID, 3, "VIP3") + if _, err := svc.SetRoomBackground(ctx, &roomv1.SetRoomBackgroundRequest{ + Meta: vipRoomMeta(roomID, ownerID, "set-denied"), + BackgroundId: second.GetBackgroundId(), + }); !xerr.IsCode(err, xerr.PermissionDenied) { + t.Fatalf("expired custom_room_background benefit must block later set: %v", err) + } +} + +func TestVIPModerationProtectionBlocksRoomManagersButNotSystemEvict(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + targetID := int64(8402) + wallet := &rocketTestWallet{vipResponses: map[int64]*walletv1.GetMyVipResponse{ + targetID: tieredVIPResponse(targetID, 9, "VIP9", "anti_kick", "anti_mute"), + }} + now := &fixedRoomRocketClock{now: time.Date(2026, 7, 10, 10, 0, 0, 0, time.UTC)} + svc := newRocketTestServiceWithDirectIM(t, repository, wallet, now, nil, newRecordingRoomDirectIMPublisher()) + roomID := "fami-vip-moderation-room" + ownerID := int64(8401) + createVIPRoom(t, ctx, svc, roomID, ownerID) + if _, err := svc.JoinRoom(ctx, &roomv1.JoinRoomRequest{Meta: vipRoomMeta(roomID, targetID, "target-join"), Role: "audience"}); err != nil { + t.Fatalf("join protected target failed: %v", err) + } + + if _, err := svc.MuteUser(ctx, &roomv1.MuteUserRequest{ + Meta: vipRoomMeta(roomID, ownerID, "mute"), + TargetUserId: targetID, + Muted: true, + }); !xerr.IsCode(err, xerr.PermissionDenied) { + 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) { + t.Fatalf("anti_kick must block ordinary room owner: %v", err) + } + + vipCallsBeforeSystemEvict := len(wallet.vipRequests) + evict, err := svc.SystemEvictUser(ctx, &roomv1.SystemEvictUserRequest{ + Meta: vipRoomMeta(roomID, 9901, "system-evict"), + TargetUserId: targetID, + OperatorUserId: 9901, + Reason: "platform_moderation", + BanFromRoom: true, + }) + if err != nil { + t.Fatalf("system evict must bypass anti_kick: %v", err) + } + if !evict.GetResult().GetApplied() || findRoomUser(evict.GetRoom(), targetID) != nil || !containsInt64(evict.GetRoom().GetBanUserIds(), targetID) { + t.Fatalf("system evict must remove and ban protected target: %+v", evict) + } + if len(wallet.vipRequests) != vipCallsBeforeSystemEvict { + t.Fatalf("SystemEvictUser must not query or enforce ordinary VIP moderation benefits: before=%d after=%d", vipCallsBeforeSystemEvict, len(wallet.vipRequests)) + } +} + +func tieredVIPResponse(userID int64, level int32, name string, benefitCodes ...string) *walletv1.GetMyVipResponse { + benefits := make([]*walletv1.VipBenefit, 0, len(benefitCodes)) + for index, code := range benefitCodes { + benefits = append(benefits, &walletv1.VipBenefit{ + BenefitCode: code, + Name: code, + Status: "active", + SortOrder: int32(index + 1), + }) + } + return &walletv1.GetMyVipResponse{State: &walletv1.VipState{ + ProgramConfig: &walletv1.VipProgramConfig{AppCode: vipTestAppCode, ProgramType: "tiered_privilege_v1", Status: "active", LevelCount: 9}, + EffectiveVip: &walletv1.UserVip{ + UserId: userID, + Level: level, + Name: name, + Active: level > 0, + ProgramType: "tiered_privilege_v1", + }, + EffectiveBenefits: benefits, + }} +} + +func tieredVIPResponseWithRoomNoticeSetting(userID int64, level int32, name string, hasBenefit bool, enabled bool) *walletv1.GetMyVipResponse { + codes := []string{} + if hasBenefit { + codes = append(codes, "room_entry_notice") + } + response := tieredVIPResponse(userID, level, name, codes...) + response.GetState().UserSettings = &walletv1.VipUserSettings{ + AppCode: vipTestAppCode, UserId: userID, + RoomEntryNoticeEnabled: enabled, OnlineGlobalNoticeEnabled: true, + } + return response +} + +func createVIPRoom(t *testing.T, ctx context.Context, svc *roomservice.Service, roomID string, ownerID int64) { + t.Helper() + if _, err := svc.CreateRoom(ctx, &roomv1.CreateRoomRequest{ + Meta: vipRoomMeta(roomID, ownerID, "create"), + SeatCount: 10, + Mode: "voice", + VisibleRegionId: 1001, + RoomName: roomID, + RoomAvatar: testRoomCoverURL, + RoomShortId: roomID, + }); err != nil { + t.Fatalf("create vip room failed: %v", err) + } +} + +func saveVIPRoomBackground(t *testing.T, ctx context.Context, svc *roomservice.Service, roomID string, ownerID int64, suffix string, imageURL string) *roomv1.RoomBackgroundImage { + t.Helper() + response, err := svc.SaveRoomBackground(ctx, &roomv1.SaveRoomBackgroundRequest{ + Meta: vipRoomMeta(roomID, ownerID, "save-"+suffix), + RoomId: roomID, + ImageUrl: imageURL, + }) + if err != nil { + t.Fatalf("save vip room background failed: %v", err) + } + return response.GetBackground() +} + +func vipRoomMeta(roomID string, actorUserID int64, suffix string) *roomv1.RequestMeta { + return &roomv1.RequestMeta{ + RequestId: fmt.Sprintf("req-vip-%s", suffix), + CommandId: fmt.Sprintf("cmd-vip-%s", suffix), + ActorUserId: actorUserID, + RoomId: roomID, + AppCode: vipTestAppCode, + SentAtMs: time.Date(2026, 7, 10, 8, 0, 0, 0, time.UTC).UnixMilli(), + } +} diff --git a/services/room-service/internal/storage/mysql/room_list.go b/services/room-service/internal/storage/mysql/room_list.go index e57ee680..77358b80 100644 --- a/services/room-service/internal/storage/mysql/room_list.go +++ b/services/room-service/internal/storage/mysql/room_list.go @@ -583,6 +583,10 @@ func buildRoomListQuerySQL(query roomservice.RoomListQuery) (string, []any) { return buildRoomListByOwnersQuerySQL(query) } regionID := query.VisibleRegionID + if query.FilterRegionID > 0 { + // 直接 repository 调用也必须尊重已校验的区域筛选,不依赖 service 预先覆盖默认区域。 + regionID = query.FilterRegionID + } if regionID < 0 { regionID = 0 } diff --git a/services/room-service/internal/transport/grpc/server_test.go b/services/room-service/internal/transport/grpc/server_test.go index b99dcbd9..ecc47486 100644 --- a/services/room-service/internal/transport/grpc/server_test.go +++ b/services/room-service/internal/transport/grpc/server_test.go @@ -45,6 +45,14 @@ func (fakeWallet) GrantResourceGroup(context.Context, *walletv1.GrantResourceGro return &walletv1.ResourceGrantResponse{Grant: &walletv1.ResourceGrant{GrantId: "grant-test"}}, nil } +// GetMyVip 返回显式 legacy program,避免 transport 测试把 VIP 配置缺失误判成房间协议错误。 +func (fakeWallet) GetMyVip(_ context.Context, req *walletv1.GetMyVipRequest) (*walletv1.GetMyVipResponse, error) { + return &walletv1.GetMyVipResponse{State: &walletv1.VipState{ + ProgramConfig: &walletv1.VipProgramConfig{AppCode: appcode.Default, ProgramType: "legacy_timed", Status: "active"}, + EffectiveVip: &walletv1.UserVip{UserId: req.GetUserId()}, + }}, nil +} + // newTransportTestServer 构造完整领域服务,确保测试覆盖真实 service -> transport 错误边界。 func newTransportTestServer(t *testing.T) *Server { t.Helper() diff --git a/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql b/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql index 591b8f1d..6a3749ca 100644 --- a/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql +++ b/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql @@ -174,7 +174,8 @@ CREATE TABLE IF NOT EXISTS stat_social_user_day ( gift_panel_open TINYINT(1) NOT NULL DEFAULT 0 COMMENT '礼物面板打开去重标记', probability_game_panel_open TINYINT(1) NOT NULL DEFAULT 0 COMMENT '概率游戏面板打开去重标记', app_stay_ms BIGINT NOT NULL DEFAULT 0 COMMENT 'App 停留时长毫秒', - room_stay_ms BIGINT NOT NULL DEFAULT 0 COMMENT '房间停留时长毫秒', + room_stay_ms BIGINT NOT NULL DEFAULT 0 COMMENT '房间停留时长毫秒,客户端 room_stay 埋点口径', + room_online_ms BIGINT NOT NULL DEFAULT 0 COMMENT '房间在线时长毫秒,服务端进退房事实口径', mic_stay_ms BIGINT NOT NULL DEFAULT 0 COMMENT '麦上停留时长毫秒', recharge_count BIGINT NOT NULL DEFAULT 0 COMMENT '充值次数', recharge_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '总充值 USD 最小单位', diff --git a/services/statistics-service/internal/app/app.go b/services/statistics-service/internal/app/app.go index 058ed454..7dd67fdd 100644 --- a/services/statistics-service/internal/app/app.go +++ b/services/statistics-service/internal/app/app.go @@ -180,11 +180,17 @@ func ConsumeUserOutboxBody(ctx context.Context, repo *mysqlstorage.Repository, b } return repo.ConsumeUserRegionChanged(appcode.WithContext(ctx, event.AppCode), event) } - event, ok, err := userMicDailyStatsUpdatedEvent(body) + if event, ok, err := userMicDailyStatsUpdatedEvent(body); err != nil || ok { + if err != nil || !ok { + return err + } + return repo.ConsumeUserMicDailyStatsUpdated(appcode.WithContext(ctx, event.AppCode), event) + } + event, ok, err := userRoomDailyStatsUpdatedEvent(body) if err != nil || !ok { return err } - return repo.ConsumeUserMicDailyStatsUpdated(appcode.WithContext(ctx, event.AppCode), event) + return repo.ConsumeUserRoomDailyStatsUpdated(appcode.WithContext(ctx, event.AppCode), event) } // ConsumeWalletOutboxBody 按钱包事实类型分派充值、币商补货、奖励和余额变动;未知事件只提交消费位点,不写统计读模型。 @@ -329,6 +335,25 @@ func userMicDailyStatsUpdatedEvent(body []byte) (mysqlstorage.UserMicDailyStatsU }, true, nil } +func userRoomDailyStatsUpdatedEvent(body []byte) (mysqlstorage.UserRoomDailyStatsUpdatedEvent, bool, error) { + message, err := usermq.DecodeUserOutboxMessage(body) + if err != nil { + return mysqlstorage.UserRoomDailyStatsUpdatedEvent{}, false, err + } + if message.EventType != "UserRoomDailyStatsUpdated" { + return mysqlstorage.UserRoomDailyStatsUpdatedEvent{}, false, nil + } + payload := mysqlstorage.DecodeJSON(message.PayloadJSON) + return mysqlstorage.UserRoomDailyStatsUpdatedEvent{ + AppCode: message.AppCode, + EventID: message.EventID, + UserID: firstNonZeroInt64(mysqlstorage.Int64(payload, "user_id"), message.AggregateID), + StatDate: mysqlstorage.String(payload, "stat_date"), + RoomOnlineDeltaMS: mysqlstorage.Int64(payload, "room_online_delta_ms"), + OccurredAtMS: firstNonZeroInt64(mysqlstorage.Int64(payload, "updated_at_ms"), message.OccurredAtMS), + }, true, nil +} + func rechargeEvent(body []byte) (mysqlstorage.RechargeEvent, bool, error) { message, err := walletmq.DecodeWalletOutboxMessage(body) if err != nil { diff --git a/services/statistics-service/internal/app/query_http.go b/services/statistics-service/internal/app/query_http.go index e731b8e2..032c105c 100644 --- a/services/statistics-service/internal/app/query_http.go +++ b/services/statistics-service/internal/app/query_http.go @@ -192,9 +192,10 @@ func (s *queryHTTPServer) socialRequirements(w http.ResponseWriter, r *http.Requ CountryID: parseInt64(query.Get("country_id")), RegionID: parseInt64(query.Get("region_id")), RegionIDs: parseInt64CSV(query.Get("region_ids")), - Section: query.Get("section"), - UserRole: query.Get("user_role"), - PayerType: query.Get("payer_type"), + Section: query.Get("section"), + UserRole: query.Get("user_role"), + PayerType: query.Get("payer_type"), + NewUserType: query.Get("new_user_type"), }) if err != nil { writeJSON(w, http.StatusInternalServerError, map[string]any{"error": err.Error()}) diff --git a/services/statistics-service/internal/storage/mysql/query_test.go b/services/statistics-service/internal/storage/mysql/query_test.go index 433f9878..d7f08c33 100644 --- a/services/statistics-service/internal/storage/mysql/query_test.go +++ b/services/statistics-service/internal/storage/mysql/query_test.go @@ -349,6 +349,14 @@ func TestQuerySocialRequirementsAggregatesP0ToP5(t *testing.T) { }); err != nil { t.Fatalf("consume self game: %v", err) } + // day2 再押一次 dice:用于验证按游戏的同游戏次留(day1 cohort 1 人,day2 继续押注 → 100%)。 + if err := repository.ConsumeSelfGameMatch(ctx, SelfGameMatchEvent{ + AppCode: "lalu", EventID: "social:self-game:settled-day2", EventType: "SelfGameMatchSettled", GameID: "dice", CountryID: 86, RegionID: 210, + StakeCoin: 100, UserParticipants: 1, UserStakeCoin: 100, Participants: []SelfGameMatchParticipantEvent{{UserID: user1, ParticipantType: "user", StakeCoin: 100, Result: "lose"}}, + OccurredAtMS: start.Add(24*time.Hour + 30*time.Minute).UnixMilli(), + }); err != nil { + t.Fatalf("consume self game day2: %v", err) + } query := SocialRequirementsQuery{ AppCode: "lalu", @@ -366,14 +374,20 @@ func TestQuerySocialRequirementsAggregatesP0ToP5(t *testing.T) { socialMetricInt(t, newUsers.Total, "new_host_users") != 1 || socialMetricInt(t, newUsers.Total, "new_normal_users") != 1 || math.Abs(socialMetricFloat(t, newUsers.Total, "room_join_success_rate")-0.5) > 0.0001 || - math.Abs(socialMetricFloat(t, newUsers.Total, "new_host_d1_retention_rate")-1) > 0.0001 { + math.Abs(socialMetricFloat(t, newUsers.Total, "new_host_d1_retention_rate")-1) > 0.0001 || + // 新用户平均进房/上麦时长只统计当天注册用户:room_stay 300s/1人=5min,mic 120s/1人=2min。 + math.Abs(socialMetricFloat(t, newUsers.Total, "avg_room_stay_min")-5) > 0.0001 || + math.Abs(socialMetricFloat(t, newUsers.Total, "avg_mic_stay_min")-2) > 0.0001 || + // 新用户充值金额=全渠道:user1 普通充值 1200 + user2 币商入账 900。 + socialMetricInt(t, newUsers.Total, "new_user_recharge_usd_minor") != 2100 { t.Fatalf("P0 metrics mismatch: %+v", newUsers.Total.Metrics) } revenue := socialTestSection(t, result, SocialSectionRevenue) + // 文档口径:总充值 2100 = Google 500 + 三方(MiFaPay) 700 + 币商(finance verified) 900。 if socialMetricInt(t, revenue.Total, "recharge_usd_minor") != 2100 || socialMetricInt(t, revenue.Total, "google_recharge_usd_minor") != 500 || - socialMetricInt(t, revenue.Total, "third_party_recharge_usd_minor") != 900 || + socialMetricInt(t, revenue.Total, "third_party_recharge_usd_minor") != 700 || socialMetricInt(t, revenue.Total, "coin_seller_recharge_usd_minor") != 900 || socialMetricInt(t, revenue.Total, "recharge_count") != 3 || socialMetricInt(t, revenue.Total, "recharge_users") != 1 || @@ -386,9 +400,10 @@ func TestQuerySocialRequirementsAggregatesP0ToP5(t *testing.T) { t.Fatalf("query revenue requirements: %v", err) } paidRevenueSection := socialTestSection(t, paidRevenue, SocialSectionRevenue) + // paid 过滤只剩 user1:Google 500 + MiFaPay(三方) 700;user2 的币商订单不置付费标记被排除。 if socialMetricInt(t, paidRevenueSection.Total, "recharge_usd_minor") != 1200 || socialMetricInt(t, paidRevenueSection.Total, "google_recharge_usd_minor") != 500 || - socialMetricInt(t, paidRevenueSection.Total, "third_party_recharge_usd_minor") != 0 || + socialMetricInt(t, paidRevenueSection.Total, "third_party_recharge_usd_minor") != 700 || socialMetricInt(t, paidRevenueSection.Total, "recharge_count") != 2 || socialMetricInt(t, paidRevenueSection.Total, "first_recharge_users") != 1 || socialMetricInt(t, paidRevenueSection.Total, "repeat_recharge_users") != 1 || @@ -397,7 +412,10 @@ func TestQuerySocialRequirementsAggregatesP0ToP5(t *testing.T) { } retention := socialTestSection(t, result, SocialSectionRetention) - if math.Abs(socialMetricFloat(t, retention.Total, "registered_d1_active_rate")-0.5) > 0.0001 || + // 用户次留按全体活跃用户 cohort:day1 活跃 user1+user2,day2 仅 user1 回访 → 0.5。 + if socialMetricInt(t, retention.Total, "active_d1_active_base_users") != 2 || + socialMetricInt(t, retention.Total, "active_d1_active_users") != 1 || + math.Abs(socialMetricFloat(t, retention.Total, "active_d1_active_rate")-0.5) > 0.0001 || math.Abs(socialMetricFloat(t, retention.Total, "after_room_d1_room_rate")-1) > 0.0001 { t.Fatalf("P2 retention metrics mismatch: %+v", retention.Total.Metrics) } @@ -424,6 +442,60 @@ func TestQuerySocialRequirementsAggregatesP0ToP5(t *testing.T) { math.Abs(socialMetricFloat(t, game.Total, "probability_game_bet_arppu_coin")-300) > 0.0001 { t.Fatalf("P5 metrics mismatch: %+v", game.Total.Metrics) } + + // 按游戏明细:dice 自研(day1 押 400,day2 继续押 → 同游戏次留 100%),slot 厂商(300,无次留)。 + if len(game.Games) != 2 { + t.Fatalf("expected 2 game breakdown rows, got %+v", game.Games) + } + gameByName := map[string]SocialRequirementGame{} + for _, item := range game.Games { + gameByName[item.GameName] = item + } + dice, ok := gameByName["dice"] + if !ok || + socialMetricInt(t, dice.Total, "game_bet_users") != 1 || + socialMetricInt(t, dice.Total, "game_bet_coin") != 400 || + math.Abs(socialMetricFloat(t, dice.Total, "game_arppu_coin")-400) > 0.0001 || + math.Abs(socialMetricFloat(t, dice.Total, "game_d1_retention_rate")-1) > 0.0001 { + t.Fatalf("dice breakdown mismatch: %+v", dice.Total.Metrics) + } + slot, ok := gameByName["slot (vendor)"] + if !ok || + socialMetricInt(t, slot.Total, "game_bet_users") != 1 || + socialMetricInt(t, slot.Total, "game_bet_coin") != 300 || + math.Abs(socialMetricFloat(t, slot.Total, "game_d1_retention_rate")) > 0.0001 { + t.Fatalf("slot breakdown mismatch: %+v", slot.Total.Metrics) + } + if len(game.GameColumns) == 0 { + t.Fatalf("expected game breakdown columns") + } + + // 是否新用户筛选:day1 两人都是当天注册 → new=2、old=0。 + newUserActive, err := repository.QuerySocialRequirements(ctx, SocialRequirementsQuery{AppCode: "lalu", StartMS: query.StartMS, EndMS: query.EndMS, RegionIDs: []int64{210}, Section: SocialSectionActive, NewUserType: "new"}) + if err != nil { + t.Fatalf("query new-user active requirements: %v", err) + } + if socialMetricInt(t, socialTestSection(t, newUserActive, SocialSectionActive).Total, "active_users") != 2 { + t.Fatalf("new-user filtered DAU mismatch: %+v", socialTestSection(t, newUserActive, SocialSectionActive).Total.Metrics) + } + oldUserActive, err := repository.QuerySocialRequirements(ctx, SocialRequirementsQuery{AppCode: "lalu", StartMS: query.StartMS, EndMS: query.EndMS, RegionIDs: []int64{210}, Section: SocialSectionActive, NewUserType: "old"}) + if err != nil { + t.Fatalf("query old-user active requirements: %v", err) + } + if socialMetricInt(t, socialTestSection(t, oldUserActive, SocialSectionActive).Total, "active_users") != 0 { + t.Fatalf("old-user filtered DAU mismatch: %+v", socialTestSection(t, oldUserActive, SocialSectionActive).Total.Metrics) + } + + // 平均值行:两天窗口 day1 活跃 2 人、day2 活跃 1 人(user1 home_view)→ 汇总 3 人天、日均 1.5。 + twoDay, err := repository.QuerySocialRequirements(ctx, SocialRequirementsQuery{AppCode: "lalu", StartMS: query.StartMS, EndMS: start.Add(48 * time.Hour).UnixMilli(), RegionIDs: []int64{210}, Section: SocialSectionActive}) + if err != nil { + t.Fatalf("query two-day active requirements: %v", err) + } + twoDayActive := socialTestSection(t, twoDay, SocialSectionActive) + if socialMetricInt(t, twoDayActive.Total, "active_users") != 3 || + math.Abs(socialMetricFloat(t, twoDayActive.Average, "active_users")-1.5) > 0.0001 { + t.Fatalf("average row mismatch: total=%+v average=%+v", twoDayActive.Total.Metrics, twoDayActive.Average.Metrics) + } } func socialTestSection(t *testing.T, result SocialRequirements, key string) SocialRequirementSection { diff --git a/services/statistics-service/internal/storage/mysql/repository.go b/services/statistics-service/internal/storage/mysql/repository.go index bd8e1ce3..83c8669c 100644 --- a/services/statistics-service/internal/storage/mysql/repository.go +++ b/services/statistics-service/internal/storage/mysql/repository.go @@ -204,7 +204,7 @@ func (r *Repository) Migrate(ctx context.Context) error { game_bet_user TINYINT(1) NOT NULL DEFAULT 0, self_game_bet_user TINYINT(1) NOT NULL DEFAULT 0, probability_game_bet_user TINYINT(1) NOT NULL DEFAULT 0, chat_sent TINYINT(1) NOT NULL DEFAULT 0, follow_user TINYINT(1) NOT NULL DEFAULT 0, follow_room TINYINT(1) NOT NULL DEFAULT 0, gift_panel_open TINYINT(1) NOT NULL DEFAULT 0, probability_game_panel_open TINYINT(1) NOT NULL DEFAULT 0, - app_stay_ms BIGINT NOT NULL DEFAULT 0, room_stay_ms BIGINT NOT NULL DEFAULT 0, mic_stay_ms BIGINT NOT NULL DEFAULT 0, + app_stay_ms BIGINT NOT NULL DEFAULT 0, room_stay_ms BIGINT NOT NULL DEFAULT 0, room_online_ms BIGINT NOT NULL DEFAULT 0, mic_stay_ms BIGINT NOT NULL DEFAULT 0, recharge_count BIGINT NOT NULL DEFAULT 0, recharge_usd_minor BIGINT NOT NULL DEFAULT 0, google_recharge_usd_minor BIGINT NOT NULL DEFAULT 0, third_party_recharge_usd_minor BIGINT NOT NULL DEFAULT 0, coin_seller_recharge_usd_minor BIGINT NOT NULL DEFAULT 0, first_recharge_usd_minor BIGINT NOT NULL DEFAULT 0, repeat_recharge_usd_minor BIGINT NOT NULL DEFAULT 0, @@ -396,6 +396,7 @@ func (r *Repository) Migrate(ctx context.Context) error { `ALTER TABLE stat_app_day_country ADD COLUMN mic_online_ms BIGINT NOT NULL DEFAULT 0 AFTER salary_transfer_coin`, `ALTER TABLE stat_app_day_country ADD COLUMN mic_online_users BIGINT NOT NULL DEFAULT 0 AFTER mic_online_ms`, `ALTER TABLE stat_game_day_country ADD COLUMN refund_coin BIGINT NOT NULL DEFAULT 0 AFTER payout_coin`, + `ALTER TABLE stat_social_user_day ADD COLUMN room_online_ms BIGINT NOT NULL DEFAULT 0 AFTER room_stay_ms`, `ALTER TABLE stat_app_day_country ADD COLUMN region_id BIGINT NOT NULL DEFAULT 0 AFTER country_id`, `ALTER TABLE stat_user_day_activity ADD COLUMN region_id BIGINT NOT NULL DEFAULT 0 AFTER country_id`, `ALTER TABLE stat_user_registration ADD COLUMN region_id BIGINT NOT NULL DEFAULT 0 AFTER country_id`, @@ -707,6 +708,15 @@ type UserMicDailyStatsUpdatedEvent struct { OccurredAtMS int64 } +type UserRoomDailyStatsUpdatedEvent struct { + AppCode string + EventID string + UserID int64 + StatDate string + RoomOnlineDeltaMS int64 + OccurredAtMS int64 +} + type UserActiveEvent struct { AppCode string EventID string @@ -944,12 +954,16 @@ func (r *Repository) ConsumeRecharge(ctx context.Context, event RechargeEvent) e `, event.USDMinor, newUserUSD, coinSellerUSD, mifapayUSD, googleUSD, coinSellerTransferCoin, paidUsers, nowMS, appcode.Normalize(event.AppCode), scope.tz, scope.day, countryID, regionID); err != nil { return err } + // 数据需求文档口径:总充值 = Google + 第三方 + 币商。第三方= MiFaPay/V5Pay/USDT 等 + // 非 Google、非币商的支付渠道;币商美元金额走 finance verified 订单链路单独进入币商列。 googleUSD, thirdPartyUSD, coinSellerUSD := int64(0), int64(0), int64(0) switch strings.ToLower(strings.TrimSpace(event.RechargeType)) { case "google", "google_play": googleUSD = event.USDMinor case "coin_seller_transfer", "coin_seller": coinSellerUSD = event.USDMinor + default: + thirdPartyUSD = event.USDMinor } firstRecharge, repeatRecharge, firstUSD, repeatUSD := int64(0), int64(0), int64(0), int64(0) if event.RechargeSequence == 1 { @@ -997,8 +1011,8 @@ func (r *Repository) ConsumeFinanceCoinSellerRechargeOrder(ctx context.Context, } countryID, regionID := normalizeDimension(event.CountryID, event.RegionID) for _, scope := range statDayScopesFromContext(ctx, occurredAtMS) { - // Social BI 的第三方充值口径绑定 finance 工作台 verified 币商订单:金额和次数进入营收, - // 但不置 recharge_user/first/repeat 标记,避免财务补单把付费率和 ARPPU 分母放大。 + // finance 工作台 verified 币商订单只进入总充值和币商充值列(文档:币商充值=财务-代理充值), + // 不再重复写第三方列;也不置 recharge_user/first/repeat 标记,避免财务补单把付费率和 ARPPU 分母放大。 if err := applySocialUserDayDelta(ctx, tx, socialUserDayDelta{ AppCode: event.AppCode, StatTZ: scope.tz, @@ -1009,7 +1023,6 @@ func (r *Repository) ConsumeFinanceCoinSellerRechargeOrder(ctx context.Context, UpdatedAt: nowMS, RechargeCount: 1, RechargeUSDMinor: event.USDMinor, - ThirdPartyRechargeUSDMinor: event.USDMinor, CoinSellerRechargeUSDMinor: event.USDMinor, }); err != nil { return err @@ -1428,17 +1441,20 @@ func (r *Repository) ConsumeUserMicDailyStatsUpdated(ctx context.Context, event } micDelta := after - before if micDelta > 0 { + // 上麦必然已在房内:麦时长事实同时置进房成功标志,避免客户端 room_join 埋点丢失时 + // 出现"有上麦却无进房"的倒挂行。 if err := applySocialUserDayDelta(ctx, tx, socialUserDayDelta{ - AppCode: event.AppCode, - StatTZ: scope.tz, - StatDay: scope.day, - UserID: event.UserID, - CountryID: countryID, - RegionID: regionID, - UpdatedAt: nowMS, - Active: 1, - MicUp: 1, - MicStayMS: micDelta, + AppCode: event.AppCode, + StatTZ: scope.tz, + StatDay: scope.day, + UserID: event.UserID, + CountryID: countryID, + RegionID: regionID, + UpdatedAt: nowMS, + Active: 1, + RoomJoinOK: 1, + MicUp: 1, + MicStayMS: micDelta, }); err != nil { return err } @@ -1448,6 +1464,40 @@ func (r *Repository) ConsumeUserMicDailyStatsUpdated(ctx context.Context, event }) } +func (r *Repository) ConsumeUserRoomDailyStatsUpdated(ctx context.Context, event UserRoomDailyStatsUpdatedEvent) error { + return r.withEvent(ctx, SourceUser, event.EventID, "UserRoomDailyStatsUpdated", func(tx *sql.Tx, nowMS int64) error { + if event.RoomOnlineDeltaMS <= 0 || strings.TrimSpace(event.StatDate) == "" { + return nil + } + countryID, regionID, err := r.dimensionForUser(ctx, tx, event.AppCode, event.UserID, 0, 0) + if err != nil { + return err + } + for _, scope := range statDateScopesFromContext(ctx, event.StatDate) { + if err := ensureAppDay(ctx, tx, event.AppCode, scope.tz, scope.day, countryID, regionID, nowMS); err != nil { + return err + } + // 服务端在房事实落独立列 room_online_ms,不直接累加 room_stay_ms: + // 客户端 room_stay 埋点仍在上报,两条来源同时累加同一列会双计;查询口径取 GREATEST 兜数据断层。 + if err := applySocialUserDayDelta(ctx, tx, socialUserDayDelta{ + AppCode: event.AppCode, + StatTZ: scope.tz, + StatDay: scope.day, + UserID: event.UserID, + CountryID: countryID, + RegionID: regionID, + UpdatedAt: nowMS, + Active: 1, + RoomJoinOK: 1, + RoomOnlineMS: event.RoomOnlineDeltaMS, + }); err != nil { + return err + } + } + return nil + }) +} + 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) @@ -2053,7 +2103,9 @@ func (r *Repository) dimensionForUser(ctx context.Context, tx *sql.Tx, app strin func isConsumedCoinBizType(value string) bool { switch strings.ToLower(strings.TrimSpace(value)) { - case "direct_gift_debit", "red_packet_create", "wheel_draw_debit": + // vip_purchase / resource_shop_purchase 对应文档消费口径里的"购买VIP、买商城装扮", + // 计入消耗金币和消费渗透率(礼物扣款仍由 RoomGiftSent 单独投影,direct_gift_debit 在宽表侧清零防双计)。 + case "direct_gift_debit", "red_packet_create", "wheel_draw_debit", "vip_purchase", "resource_shop_purchase": return true default: return false 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 68dbfb5b..7ffeb34e 100644 --- a/services/statistics-service/internal/storage/mysql/social_requirements_query.go +++ b/services/statistics-service/internal/storage/mysql/social_requirements_query.go @@ -21,16 +21,17 @@ const ( ) type SocialRequirementsQuery struct { - AppCode string - StatTZ string - StartMS int64 - EndMS int64 - CountryID int64 - RegionID int64 - RegionIDs []int64 - Section string - UserRole string - PayerType string + AppCode string + StatTZ string + StartMS int64 + EndMS int64 + CountryID int64 + RegionID int64 + RegionIDs []int64 + Section string + UserRole string + PayerType string + NewUserType string } type SocialRequirements struct { @@ -51,7 +52,20 @@ type SocialRequirementSection struct { Columns []SocialRequirementColumn `json:"columns"` MetricDefinitions []MetricDefinition `json:"metric_definitions"` Total SocialRequirementRow `json:"total"` + Average SocialRequirementRow `json:"average"` DailySeries []SocialRequirementRow `json:"daily_series"` + // P5 游戏 section 附带的按游戏明细:来自 stat_self_game_user_day / stat_game_day_players 投影, + // 不受用户身份/付费身份/是否新用户筛选影响(厂商游戏无按用户金额,无法一致地过滤)。 + GameColumns []SocialRequirementColumn `json:"game_columns,omitempty"` + Games []SocialRequirementGame `json:"games,omitempty"` +} + +type SocialRequirementGame struct { + GameKey string `json:"game_key"` + GameSource string `json:"game_source"` + GameName string `json:"game_name"` + Total SocialRequirementRow `json:"total"` + DailySeries []SocialRequirementRow `json:"daily_series"` } type SocialRequirementColumn struct { @@ -62,8 +76,9 @@ type SocialRequirementColumn struct { } type SocialRequirementFilter struct { - UserRole string `json:"user_role"` - PayerType string `json:"payer_type"` + UserRole string `json:"user_role"` + PayerType string `json:"payer_type"` + NewUserType string `json:"new_user_type"` } type SocialRequirementRow struct { @@ -111,6 +126,7 @@ type socialRequirementUserDay struct { ProbabilityPanel int64 AppStayMS int64 RoomStayMS int64 + RoomOnlineMS int64 MicStayMS int64 RechargeCount int64 RechargeUSDMinor int64 @@ -148,6 +164,14 @@ type socialRequirementAggregate struct { RegisteredRoomGift int64 RegisteredRecharge int64 RegisteredGame int64 + RegisteredFollowUser int64 + RegisteredFollowRoom int64 + RegisteredChat int64 + RegisteredAppStayMS int64 + RegisteredRoomStayMS int64 + RegisteredMicStayMS int64 + RegisteredRechargeUSDMinor int64 + ConsumeUsers int64 MicUp int64 Gift int64 NormalGift int64 @@ -218,6 +242,16 @@ func (r *Repository) QuerySocialRequirements(ctx context.Context, query SocialRe } byDay, bySubjectDay := indexSocialRows(rows) sections := socialRequestedSections(query.Section) + var gameBreakdown []SocialRequirementGame + for _, section := range sections { + if section == SocialSectionGame { + gameBreakdown, err = r.querySocialGameBreakdown(ctx, app, statTZ, days, query.CountryID, query.RegionID, query.RegionIDs) + if err != nil { + return SocialRequirements{}, err + } + break + } + } out := SocialRequirements{ AppCode: app, StatTZ: statTZ, @@ -233,9 +267,9 @@ func (r *Repository) QuerySocialRequirements(ctx context.Context, query SocialRe totalAgg := socialRequirementAggregate{} totalRetention := map[string]retentionMetric{} for _, day := range days { - agg := aggregateSocialRows(byDay[day], section, query.UserRole, query.PayerType) + 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) + retention := socialRetentionMetrics(day, byDay[day], bySubjectDay, section, query.UserRole, query.PayerType, query.NewUserType) mergeRetentionMetrics(totalRetention, retention) sectionRows = append(sectionRows, SocialRequirementRow{ StatDay: day, @@ -243,19 +277,55 @@ func (r *Repository) QuerySocialRequirements(ctx context.Context, query SocialRe Metrics: socialSectionMetrics(section, agg, retention), }) } - out.Sections = append(out.Sections, SocialRequirementSection{ - Key: section, - Label: socialSectionLabel(section), - Filters: SocialRequirementFilter{UserRole: normalizeSocialRequirementRole(query.UserRole), PayerType: normalizeSocialPayerType(query.PayerType)}, + sectionOut := SocialRequirementSection{ + Key: section, + Label: socialSectionLabel(section), + Filters: SocialRequirementFilter{ + UserRole: normalizeSocialRequirementRole(query.UserRole), + PayerType: normalizeSocialPayerType(query.PayerType), + NewUserType: normalizeSocialNewUserType(query.NewUserType), + }, Columns: socialRequirementColumns(section), MetricDefinitions: socialRequirementMetricDefinitions(section), Total: SocialRequirementRow{StatDay: "total", Label: "汇总", Metrics: socialSectionMetrics(section, totalAgg, totalRetention)}, + Average: socialAverageRow(sectionRows), DailySeries: sectionRows, - }) + } + if section == SocialSectionGame { + sectionOut.GameColumns = socialGameBreakdownColumns() + sectionOut.Games = gameBreakdown + } + out.Sections = append(out.Sections, sectionOut) } return out, nil } +// socialAverageRow 输出按天算术平均的"平均值"行:每个指标对有值的天求均值。 +// 计数/金额类是"日均量",比例类是"日均率"(与汇总行的整段合并口径互补)。 +func socialAverageRow(rows []SocialRequirementRow) SocialRequirementRow { + sums := map[string]float64{} + counts := map[string]int{} + for _, row := range rows { + for key, value := range row.Metrics { + switch v := value.(type) { + case int64: + sums[key] += float64(v) + counts[key]++ + case float64: + sums[key] += v + counts[key]++ + } + } + } + metrics := make(map[string]any, len(sums)) + for key, sum := range sums { + if counts[key] > 0 { + metrics[key] = sum / float64(counts[key]) + } + } + return SocialRequirementRow{StatDay: "average", Label: "平均值", Metrics: metrics} +} + 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 ?"} @@ -280,7 +350,7 @@ func (r *Repository) querySocialUserDays(ctx context.Context, app string, statTZ 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, probability_game_bet_user, chat_sent, follow_user, follow_room, gift_panel_open, probability_game_panel_open, - app_stay_ms, room_stay_ms, mic_stay_ms, recharge_count, recharge_usd_minor, + app_stay_ms, room_stay_ms, room_online_ms, mic_stay_ms, recharge_count, recharge_usd_minor, google_recharge_usd_minor, third_party_recharge_usd_minor, coin_seller_recharge_usd_minor, first_recharge_usd_minor, repeat_recharge_usd_minor, normal_gift_coin, lucky_gift_coin, super_lucky_gift_coin, lucky_gift_payout_coin, super_lucky_gift_payout_coin, game_bet_coin, game_bet_count, @@ -302,7 +372,7 @@ func (r *Repository) querySocialUserDays(ctx context.Context, app string, statTZ &item.MicUp, &item.Gift, &item.NormalGift, &item.LuckyGift, &item.SuperGift, &item.Recharge, &item.FirstRecharge, &item.RepeatRecharge, &item.GameBet, &item.SelfGameBet, &item.ProbabilityBet, &item.Chat, &item.FollowUser, &item.FollowRoom, &item.GiftPanel, &item.ProbabilityPanel, - &item.AppStayMS, &item.RoomStayMS, &item.MicStayMS, &item.RechargeCount, &item.RechargeUSDMinor, + &item.AppStayMS, &item.RoomStayMS, &item.RoomOnlineMS, &item.MicStayMS, &item.RechargeCount, &item.RechargeUSDMinor, &item.GoogleRechargeUSDMinor, &item.ThirdPartyRechargeUSDMinor, &item.CoinSellerRechargeUSDMinor, &item.FirstRechargeUSDMinor, &item.RepeatRechargeUSDMinor, &item.NormalGiftCoin, &item.LuckyGiftCoin, &item.SuperGiftCoin, &item.LuckyGiftPayoutCoin, &item.SuperGiftPayoutCoin, &item.GameBetCoin, &item.GameBetCount, @@ -310,6 +380,16 @@ 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 + } out = append(out, item) } return out, rows.Err() @@ -328,10 +408,10 @@ func indexSocialRows(rows []socialRequirementUserDay) (map[string][]socialRequir return byDay, bySubjectDay } -func aggregateSocialRows(rows []socialRequirementUserDay, section string, role string, payerType string) socialRequirementAggregate { +func aggregateSocialRows(rows []socialRequirementUserDay, section string, role string, payerType string, newUserType string) socialRequirementAggregate { var agg socialRequirementAggregate for _, row := range rows { - if !socialRowMatchesSection(row, section, role, payerType) { + if !socialRowMatchesSection(row, section, role, payerType, newUserType) { continue } agg.AppFirstOpen += flagValue(row.AppFirstOpen) @@ -362,6 +442,26 @@ func aggregateSocialRows(rows []socialRequirementUserDay, section string, role s if row.Registered > 0 && row.GameBet > 0 { agg.RegisteredGame++ } + // P0 的时长/关注/聊天/充值金额按文档限定「当天注册的新用户」,不能混入全体用户。 + if row.Registered > 0 { + if row.FollowUser > 0 { + agg.RegisteredFollowUser++ + } + if row.FollowRoom > 0 { + agg.RegisteredFollowRoom++ + } + if row.Chat > 0 { + agg.RegisteredChat++ + } + agg.RegisteredAppStayMS += row.AppStayMS + agg.RegisteredRoomStayMS += row.RoomStayMS + agg.RegisteredMicStayMS += row.MicStayMS + agg.RegisteredRechargeUSDMinor += row.RechargeUSDMinor + } + // 消费渗透率的分子是「有任一金币消耗行为」的去重用户(送礼/游戏/其他消费),不能把各行为人数直接相加。 + if row.Gift > 0 || row.GameBet > 0 || row.OtherConsumeCoin > 0 { + agg.ConsumeUsers++ + } agg.MicUp += flagValue(row.MicUp) agg.Gift += flagValue(row.Gift) agg.NormalGift += flagValue(row.NormalGift) @@ -419,6 +519,14 @@ func (a *socialRequirementAggregate) add(other socialRequirementAggregate) { a.RegisteredRoomGift += other.RegisteredRoomGift a.RegisteredRecharge += other.RegisteredRecharge a.RegisteredGame += other.RegisteredGame + a.RegisteredFollowUser += other.RegisteredFollowUser + a.RegisteredFollowRoom += other.RegisteredFollowRoom + a.RegisteredChat += other.RegisteredChat + a.RegisteredAppStayMS += other.RegisteredAppStayMS + a.RegisteredRoomStayMS += other.RegisteredRoomStayMS + a.RegisteredMicStayMS += other.RegisteredMicStayMS + a.RegisteredRechargeUSDMinor += other.RegisteredRechargeUSDMinor + a.ConsumeUsers += other.ConsumeUsers a.MicUp += other.MicUp a.Gift += other.Gift a.NormalGift += other.NormalGift @@ -460,15 +568,17 @@ 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) map[string]retentionMetric { +func socialRetentionMetrics(day string, rows []socialRequirementUserDay, bySubjectDay map[string]map[string]socialRequirementUserDay, section string, role string, payerType string, newUserType string) map[string]retentionMetric { out := map[string]retentionMetric{} for _, row := range rows { - if !socialRowMatchesSection(row, section, role, payerType) { + if !socialRowMatchesSection(row, section, role, payerType, newUserType) { continue } + // 文档口径:用户次留/3/7/15/30日留以「当日全体活跃用户」为基数,次日继续活跃算留存; + // 新用户(注册 cohort)留存只保留在 P0 的分身份次留里。 for _, offset := range []int{1, 3, 7, 15, 30} { - if row.Registered > 0 { - addSocialRetention(out, "registered_d"+intLabel(offset)+"_active", row, bySubjectDay, offset, func(target socialRequirementUserDay) bool { return target.Active > 0 }) + if row.Active > 0 { + addSocialRetention(out, "active_d"+intLabel(offset)+"_active", row, bySubjectDay, offset, func(target socialRequirementUserDay) bool { return target.Active > 0 }) } } if row.RoomJoinOK > 0 { @@ -539,7 +649,7 @@ func socialSectionMetrics(section string, agg socialRequirementAggregate, retent "paid_rate": ratio(agg.Recharge, agg.Active), "arpu_usd_minor": div(agg.RechargeUSDMinor, agg.Active), "arppu_usd_minor": div(ordinaryRechargeUSDMinor, agg.Recharge), - "consumption_penetration_rate": ratio(agg.Gift+agg.GameBet, agg.Active), + "consumption_penetration_rate": ratio(agg.ConsumeUsers, agg.Active), "game_consumption_ratio": ratio(agg.GameBetCoin, totalConsume), "lucky_gift_consumption_ratio": ratio(agg.LuckyGiftCoin+agg.SuperGiftCoin, totalConsume), "normal_gift_consumption_ratio": ratio(agg.NormalGiftCoin, totalConsume), @@ -559,17 +669,18 @@ func socialSectionMetrics(section string, agg socialRequirementAggregate, retent "active_users": agg.Active, "room_join_success_users": agg.RoomJoinOK, "room_join_fail_users": agg.RoomJoinNG, - "room_join_success_rate": ratio(agg.RoomJoinOK, agg.RoomJoinOK+agg.RoomJoinNG), - "room_join_fail_rate": ratio(agg.RoomJoinNG, agg.RoomJoinOK+agg.RoomJoinNG), - "mic_up_users": agg.MicUp, - "mic_up_rate": ratio(agg.MicUp, agg.RoomJoinOK), - "gift_users": agg.Gift, - "gift_rate": ratio(agg.Gift, agg.RoomJoinOK), - "game_users": agg.GameBet, - "game_conversion_rate": ratio(agg.GameBet, agg.Active), - "chat_users": agg.Chat, - "chat_conversion_rate": ratio(agg.Chat, agg.Active), - "avg_app_stay_min": minutesPerUser(agg.AppStayMS, agg.Active), + // 文档口径:进房成功率/失败率的分母都是 DAU,不是进房尝试数。 + "room_join_success_rate": ratio(agg.RoomJoinOK, agg.Active), + "room_join_fail_rate": ratio(agg.RoomJoinNG, agg.Active), + "mic_up_users": agg.MicUp, + "mic_up_rate": ratio(agg.MicUp, agg.RoomJoinOK), + "gift_users": agg.Gift, + "gift_rate": ratio(agg.Gift, agg.RoomJoinOK), + "game_users": agg.GameBet, + "game_conversion_rate": ratio(agg.GameBet, agg.RoomJoinOK), + "chat_users": agg.Chat, + "chat_conversion_rate": ratio(agg.Chat, agg.Active), + "avg_app_stay_min": minutesPerUser(agg.AppStayMS, agg.Active), } case SocialSectionGift: return map[string]any{ @@ -629,27 +740,51 @@ func socialSectionMetrics(section string, agg socialRequirementAggregate, retent "recharge_rate": ratio(agg.RegisteredRecharge, agg.Registered), "game_users": agg.RegisteredGame, "game_conversion_rate": ratio(agg.RegisteredGame, agg.Registered), - "avg_app_stay_min": minutesPerUser(agg.AppStayMS, agg.Active), - "avg_room_stay_min": minutesPerUser(agg.RoomStayMS, agg.RoomJoinOK), - "avg_mic_stay_min": minutesPerUser(agg.MicStayMS, agg.MicUp), - "new_user_recharge_usd_minor": agg.FirstRechargeUSDMinor, - "follow_user_users": agg.FollowUser, - "follow_room_users": agg.FollowRoom, - "chat_users": agg.Chat, + // P0 全部限定当天注册的新用户:时长按新用户累计、除以对应行为的新用户数。 + "avg_app_stay_min": minutesPerUser(agg.RegisteredAppStayMS, agg.Registered), + "avg_room_stay_min": minutesPerUser(agg.RegisteredRoomStayMS, agg.RegisteredRoomJoinOK), + "avg_mic_stay_min": minutesPerUser(agg.RegisteredMicStayMS, agg.RegisteredMicUp), + "new_user_recharge_usd_minor": agg.RegisteredRechargeUSDMinor, + "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"), } } } -func socialRowMatchesSection(row socialRequirementUserDay, section string, role string, payerType string) bool { +func socialRowMatchesSection(row socialRequirementUserDay, section string, role string, payerType string, newUserType string) bool { switch section { case SocialSectionNewUsers: return true case SocialSectionGift, SocialSectionGame: - return socialRoleMatches(row, role) + return socialRoleMatches(row, role) && socialNewUserMatches(row, newUserType) default: - return socialRoleMatches(row, role) && socialPayerMatches(row, payerType) + return socialRoleMatches(row, role) && socialPayerMatches(row, payerType) && socialNewUserMatches(row, newUserType) + } +} + +// 是否新用户筛选:新用户 = 当天注册成功的用户(registered_success 标志按行的 stat_day 判定)。 +func socialNewUserMatches(row socialRequirementUserDay, newUserType string) bool { + switch normalizeSocialNewUserType(newUserType) { + case "new": + return row.Registered > 0 + case "old": + return row.Registered == 0 + default: + return true + } +} + +func normalizeSocialNewUserType(value string) string { + switch strings.ToLower(strings.TrimSpace(value)) { + case "new": + return "new" + case "old", "existing", "non_new": + return "old" + default: + return "all" } } @@ -741,8 +876,9 @@ func socialRequirementMetricDefinitions(section string) []MetricDefinition { switch section { case SocialSectionRevenue: return []MetricDefinition{ - {Metric: "recharge_usd_minor", Definition: "普通 WalletRechargeRecorded 用户充值和 finance verified 币商充值订单汇总,单位 USD minor。"}, - {Metric: "third_party_recharge_usd_minor", Definition: "finance 工作台币商充值订单 verify_status=verified 后按 created_at_ms 计入;普通 MifaPay/V5Pay/USDT 用户充值不进入此列。"}, + {Metric: "recharge_usd_minor", Definition: "普通 WalletRechargeRecorded 用户充值和 finance verified 币商充值订单汇总,单位 USD minor;总充值 = Google + 第三方 + 币商。"}, + {Metric: "third_party_recharge_usd_minor", Definition: "MiFaPay/V5Pay/USDT 等非 Google、非币商支付渠道的用户充值金额。"}, + {Metric: "coin_seller_recharge_usd_minor", Definition: "finance 工作台币商充值订单 verify_status=verified 后按 created_at_ms 计入。"}, {Metric: "repurchase_rate", Definition: "复购充值用户 / 当日充值用户。"}, {Metric: "paid_rate", Definition: "充值用户 / DAU,支持用户身份和当日付费身份筛选。"}, {Metric: "arpu_usd_minor", Definition: "充值金额 / DAU。"}, @@ -750,7 +886,7 @@ func socialRequirementMetricDefinitions(section string) []MetricDefinition { } case SocialSectionRetention: return []MetricDefinition{ - {Metric: "registered_d1_active_rate", Definition: "注册 cohort 在第 1 个统计日后的活跃留存。D3/D7/D15/D30 同理。"}, + {Metric: "active_d1_active_rate", Definition: "当日全体活跃用户(进入 app)在次日继续活跃的比例;D3/D7/D15/D30 同理。不是新用户留存。"}, {Metric: "after_room_d1_room_rate", Definition: "进房 cohort 在次日再次进房的留存。"}, {Metric: "after_recharge_d1_recharge_rate", Definition: "充值 cohort 在次日再次充值的留存。"}, } @@ -807,23 +943,23 @@ func socialRequirementColumns(section string) []SocialRequirementColumn { } case SocialSectionRetention: return []SocialRequirementColumn{ - {Key: "registered_d1_active_base_users", Label: "新用户D1基数", Type: "count"}, - {Key: "registered_d1_active_users", Label: "新用户D1留存", Type: "count"}, - {Key: "registered_d1_active_rate", Label: "新用户D1留存率", Type: "ratio"}, - {Key: "registered_d3_active_rate", Label: "新用户D3留存率", Type: "ratio"}, - {Key: "registered_d7_active_rate", Label: "新用户D7留存率", Type: "ratio"}, - {Key: "registered_d15_active_rate", Label: "新用户D15留存率", Type: "ratio"}, - {Key: "registered_d30_active_rate", Label: "新用户D30留存率", Type: "ratio"}, - {Key: "after_room_d1_active_rate", Label: "进房后D1活跃留存", Type: "ratio"}, - {Key: "after_room_d1_room_rate", Label: "进房后D1进房留存", Type: "ratio"}, - {Key: "after_mic_d1_active_rate", Label: "上麦后D1活跃留存", Type: "ratio"}, - {Key: "after_mic_d1_mic_rate", Label: "上麦后D1上麦留存", Type: "ratio"}, - {Key: "after_gift_d1_active_rate", Label: "送礼后D1活跃留存", Type: "ratio"}, - {Key: "after_gift_d1_gift_rate", Label: "送礼后D1送礼留存", Type: "ratio"}, - {Key: "after_game_d1_active_rate", Label: "游戏后D1活跃留存", Type: "ratio"}, - {Key: "after_game_d1_game_rate", Label: "游戏后D1游戏留存", Type: "ratio"}, - {Key: "after_recharge_d1_active_rate", Label: "充值后D1活跃留存", Type: "ratio"}, - {Key: "after_recharge_d1_recharge_rate", Label: "充值后D1充值留存", Type: "ratio"}, + {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_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"}, + {Key: "active_d30_active_rate", Label: "用户30日留", Type: "ratio"}, + {Key: "after_room_d1_active_rate", Label: "进房后次留(活跃)", Type: "ratio", Tooltip: "当天进房后,次日继续登录"}, + {Key: "after_room_d1_room_rate", Label: "进房后次留(进房)", Type: "ratio", Tooltip: "当天进房后,次日继续进房"}, + {Key: "after_mic_d1_active_rate", Label: "上麦后次留(活跃)", Type: "ratio", Tooltip: "当天上麦后,次日继续登录"}, + {Key: "after_mic_d1_mic_rate", Label: "上麦后次留(上麦)", Type: "ratio", Tooltip: "当天上麦后,次日继续上麦"}, + {Key: "after_gift_d1_active_rate", Label: "送礼后次留(活跃)", Type: "ratio", Tooltip: "当天送礼后,次日继续登录"}, + {Key: "after_gift_d1_gift_rate", Label: "送礼后次留(送礼)", Type: "ratio", Tooltip: "当天送礼后,次日继续送礼"}, + {Key: "after_game_d1_active_rate", Label: "游戏次留(活跃)", Type: "ratio", Tooltip: "当天押注后,次日继续登录"}, + {Key: "after_game_d1_game_rate", Label: "游戏次留(游戏)", Type: "ratio", Tooltip: "当天押注后,次日继续押注"}, + {Key: "after_recharge_d1_active_rate", Label: "充值后次留(活跃)", Type: "ratio", Tooltip: "当天充值后,次日继续活跃"}, + {Key: "after_recharge_d1_recharge_rate", Label: "充值后次留(充值)", Type: "ratio", Tooltip: "当天充值后,次日继续充值"}, } case SocialSectionActive: return []SocialRequirementColumn{ @@ -900,13 +1036,13 @@ func socialRequirementColumns(section string) []SocialRequirementColumn { {Key: "recharge_rate", Label: "新用户充值率", Type: "ratio"}, {Key: "game_users", Label: "新用户游戏", Type: "count"}, {Key: "game_conversion_rate", Label: "新用户游戏转化率", Type: "ratio"}, - {Key: "avg_app_stay_min", Label: "人均App停留(分钟)", Type: "number"}, - {Key: "avg_room_stay_min", Label: "人均房间停留(分钟)", Type: "number"}, - {Key: "avg_mic_stay_min", Label: "人均麦上停留(分钟)", Type: "number"}, - {Key: "new_user_recharge_usd_minor", Label: "新用户充值金额", Type: "money_minor"}, - {Key: "follow_user_users", Label: "关注用户人数", Type: "count"}, - {Key: "follow_room_users", Label: "关注房间人数", Type: "count"}, - {Key: "chat_users", Label: "聊天用户", Type: "count"}, + {Key: "avg_app_stay_min", Label: "新用户平均停留(分钟)", Type: "number", Tooltip: "当天注册的新用户 App 停留总时长 / 新用户注册成功人数"}, + {Key: "avg_room_stay_min", Label: "新用户平均进房时长(分钟)", Type: "number", Tooltip: "当天注册的新用户房间停留总时长 / 新用户进房成功人数"}, + {Key: "avg_mic_stay_min", Label: "新用户平均上麦时长(分钟)", Type: "number", Tooltip: "当天注册的新用户麦上总时长 / 新用户上麦人数"}, + {Key: "new_user_recharge_usd_minor", Label: "新用户充值金额", Type: "money_minor", Tooltip: "当天注册的新用户全渠道充值金额"}, + {Key: "follow_user_users", Label: "新用户关注行为人数", Type: "count", Tooltip: "当天注册的新用户中发生过关注用户行为的人数"}, + {Key: "follow_room_users", Label: "新用户关注房间人数", Type: "count", Tooltip: "当天注册的新用户中发生过关注房间行为的人数"}, + {Key: "chat_users", Label: "新用户聊天人数", Type: "count", Tooltip: "当天注册的新用户中发送过 IM 消息(房间或私聊)的人数"}, {Key: "new_host_d1_retention_rate", Label: "新主播D1留存", Type: "ratio"}, {Key: "new_user_d1_retention_rate", Label: "新普通用户D1留存", Type: "ratio"}, } @@ -954,6 +1090,218 @@ func socialDayRange(startDay string, endDay string) []string { return days } +type socialGameKey struct { + Source string + Platform string + GameID string +} + +type socialGameDayData struct { + Users map[string]map[int64]bool // stat_day -> 押注用户集合 + Coin map[string]int64 // stat_day -> 押注金币 +} + +// querySocialGameBreakdown 输出 P5 的按游戏明细:押注用户、同游戏次留、ARPPU、押注金币。 +// 自研游戏读 stat_self_game_user_day(用户级、含金额);厂商/概率游戏用户集读 stat_game_day_players、 +// 金额读 stat_game_day_country(该表无用户级金额)。次留需要展示末日的次日数据,成员集多读 1 天。 +func (r *Repository) querySocialGameBreakdown(ctx context.Context, app string, statTZ string, days []string, countryID int64, regionID int64, regionIDs []int64) ([]SocialRequirementGame, error) { + if len(days) == 0 { + return nil, nil + } + startDay := days[0] + memberEndDay := addStatDays(days[len(days)-1], 1) + games := map[socialGameKey]*socialGameDayData{} + ensure := func(key socialGameKey) *socialGameDayData { + if games[key] == nil { + games[key] = &socialGameDayData{Users: map[string]map[int64]bool{}, Coin: map[string]int64{}} + } + return games[key] + } + scopeConditions := func(base []string, args []any) ([]string, []any) { + if countryID > 0 { + base = append(base, "country_id = ?") + args = append(args, countryID) + } + if regionID > 0 { + base = append(base, "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) + } + base = append(base, "region_id IN ("+strings.Join(placeholders, ",")+")") + } + return base, args + } + + selfConditions, selfArgs := scopeConditions( + []string{"app_code = ?", "stat_tz = ?", "stat_day BETWEEN ? AND ?", "match_count > 0"}, + []any{appcode.Normalize(app), normalizeStatTZ(statTZ), startDay, memberEndDay}, + ) + selfRows, err := r.db.QueryContext(ctx, ` + SELECT DATE_FORMAT(stat_day, '%Y-%m-%d'), game_id, user_id, stake_coin + FROM stat_self_game_user_day + WHERE `+strings.Join(selfConditions, " AND "), selfArgs...) + if err != nil { + return nil, err + } + defer selfRows.Close() + for selfRows.Next() { + var day, gameID string + var userID, stakeCoin int64 + if err := selfRows.Scan(&day, &gameID, &userID, &stakeCoin); err != nil { + return nil, err + } + data := ensure(socialGameKey{Source: "self", GameID: gameID}) + if data.Users[day] == nil { + data.Users[day] = map[int64]bool{} + } + data.Users[day][userID] = true + data.Coin[day] += stakeCoin + } + if err := selfRows.Err(); err != nil { + return nil, err + } + + vendorConditions, vendorArgs := scopeConditions( + []string{"app_code = ?", "stat_tz = ?", "stat_day BETWEEN ? AND ?"}, + []any{appcode.Normalize(app), normalizeStatTZ(statTZ), startDay, memberEndDay}, + ) + vendorRows, err := r.db.QueryContext(ctx, ` + SELECT DATE_FORMAT(stat_day, '%Y-%m-%d'), platform_code, game_id, user_id + FROM stat_game_day_players + WHERE `+strings.Join(vendorConditions, " AND "), vendorArgs...) + if err != nil { + return nil, err + } + defer vendorRows.Close() + for vendorRows.Next() { + var day, platform, gameID string + var userID int64 + if err := vendorRows.Scan(&day, &platform, &gameID, &userID); err != nil { + return nil, err + } + data := ensure(socialGameKey{Source: "vendor", Platform: platform, GameID: gameID}) + if data.Users[day] == nil { + data.Users[day] = map[int64]bool{} + } + data.Users[day][userID] = true + } + if err := vendorRows.Err(); err != nil { + return nil, err + } + + turnoverRows, err := r.db.QueryContext(ctx, ` + SELECT DATE_FORMAT(stat_day, '%Y-%m-%d'), platform_code, game_id, SUM(turnover_coin) + FROM stat_game_day_country + WHERE `+strings.Join(vendorConditions, " AND ")+` + GROUP BY stat_day, platform_code, game_id`, vendorArgs...) + if err != nil { + return nil, err + } + defer turnoverRows.Close() + for turnoverRows.Next() { + var day, platform, gameID string + var turnover int64 + if err := turnoverRows.Scan(&day, &platform, &gameID, &turnover); err != nil { + return nil, err + } + key := socialGameKey{Source: "vendor", Platform: platform, GameID: gameID} + if games[key] == nil { + // 只有金额没有用户投影的历史脏数据不单独成行,避免出现"有流水无用户"的幽灵游戏。 + continue + } + games[key].Coin[day] += turnover + } + if err := turnoverRows.Err(); err != nil { + return nil, err + } + + out := make([]SocialRequirementGame, 0, len(games)) + for key, data := range games { + daily := make([]SocialRequirementRow, 0, len(days)) + var totalUsers, totalCoin int64 + totalRetention := retentionMetric{} + for _, day := range days { + users := int64(len(data.Users[day])) + coin := data.Coin[day] + retention := retentionMetric{Base: users} + nextDay := data.Users[addStatDays(day, 1)] + for userID := range data.Users[day] { + if nextDay[userID] { + retention.Users++ + } + } + totalUsers += users + totalCoin += coin + totalRetention.Base += retention.Base + totalRetention.Users += retention.Users + daily = append(daily, SocialRequirementRow{ + StatDay: day, + Label: day, + Metrics: socialGameRowMetrics(users, coin, retention), + }) + } + if totalUsers == 0 && totalCoin == 0 { + continue + } + keyParts := []string{key.Source} + if strings.TrimSpace(key.Platform) != "" { + keyParts = append(keyParts, strings.TrimSpace(key.Platform)) + } + keyParts = append(keyParts, strings.TrimSpace(key.GameID)) + out = append(out, SocialRequirementGame{ + GameKey: strings.Join(keyParts, ":"), + GameSource: key.Source, + GameName: socialGameDisplayName(key), + Total: SocialRequirementRow{StatDay: "total", Label: "汇总", Metrics: socialGameRowMetrics(totalUsers, totalCoin, totalRetention)}, + DailySeries: daily, + }) + } + sort.Slice(out, func(i, j int) bool { + left := out[i].Total.Metrics["game_bet_coin"].(int64) + right := out[j].Total.Metrics["game_bet_coin"].(int64) + if left != right { + return left > right + } + return out[i].GameName < out[j].GameName + }) + return out, nil +} + +func socialGameRowMetrics(users int64, coin int64, retention retentionMetric) map[string]any { + return map[string]any{ + "game_bet_users": users, + "game_bet_coin": coin, + "game_arppu_coin": div(coin, users), + "game_d1_retention_base_users": retention.Base, + "game_d1_retention_users": retention.Users, + "game_d1_retention_rate": ratio(retention.Users, retention.Base), + } +} + +func socialGameDisplayName(key socialGameKey) string { + name := strings.TrimSpace(key.GameID) + if name == "" { + name = "unknown" + } + if key.Source == "vendor" && strings.TrimSpace(key.Platform) != "" { + return name + " (" + strings.TrimSpace(key.Platform) + ")" + } + return name +} + +func socialGameBreakdownColumns() []SocialRequirementColumn { + return []SocialRequirementColumn{ + {Key: "game_bet_users", Label: "押注用户数", Type: "count", Tooltip: "当日押注过该游戏的去重用户数"}, + {Key: "game_d1_retention_rate", Label: "游戏次留", Type: "ratio", Tooltip: "当日押注该游戏的用户中,次日继续押注同一游戏的比例"}, + {Key: "game_arppu_coin", Label: "ARPPU(金币)", Type: "coin", Tooltip: "该游戏押注金币 / 押注用户数"}, + {Key: "game_bet_coin", Label: "押注金币", Type: "coin"}, + } +} + func normalizePositiveIDs(values []int64) []int64 { seen := map[int64]bool{} out := []int64{} diff --git a/services/statistics-service/internal/storage/mysql/social_room_online_test.go b/services/statistics-service/internal/storage/mysql/social_room_online_test.go new file mode 100644 index 00000000..447eaf20 --- /dev/null +++ b/services/statistics-service/internal/storage/mysql/social_room_online_test.go @@ -0,0 +1,100 @@ +package mysql + +import ( + "context" + "runtime" + "testing" + "time" + + "hyapp/internal/testutil/mysqlschema" + "hyapp/pkg/appcode" +) + +func TestConsumeUserRoomDailyStatsUpdatedProjectsRoomOnline(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_room_online_test", + }) + repository, err := Open(ctx, statsSchema.DSN) + if err != nil { + t.Fatalf("open repository: %v", err) + } + t.Cleanup(func() { _ = repository.Close() }) + + appCtx := appcode.WithContext(ctx, "lalu") + occurredAt := time.Date(2026, 7, 1, 10, 0, 0, 0, time.UTC).UnixMilli() + + // 客户端 room_stay 埋点先落 60s;服务端事实到达前它是 room_stay_ms 的唯一来源。 + if _, err := repository.ConsumeAppTrackingEvents(appCtx, []AppTrackingEvent{{ + AppCode: "lalu", + EventID: "evt-room-stay-client", + EventName: "room_stay", + UserID: 42, + DeviceID: "dev-42", + DurationMS: 60_000, + Success: true, + OccurredAtMS: occurredAt, + }}); err != nil { + t.Fatalf("consume client room_stay: %v", err) + } + + event := UserRoomDailyStatsUpdatedEvent{ + AppCode: "lalu", + EventID: "UserRoomDailyStatsUpdated:sess-1:2026-07-01", + UserID: 42, + StatDate: "2026-07-01", + RoomOnlineDeltaMS: 600_000, + OccurredAtMS: occurredAt, + } + if err := repository.ConsumeUserRoomDailyStatsUpdated(appCtx, event); err != nil { + t.Fatalf("consume server room online fact: %v", err) + } + // 事件级幂等:同一 event_id 重放不能双计。 + if err := repository.ConsumeUserRoomDailyStatsUpdated(appCtx, event); err != nil { + t.Fatalf("replay server room online fact: %v", err) + } + if err := repository.ConsumeUserRoomDailyStatsUpdated(appCtx, UserRoomDailyStatsUpdatedEvent{ + AppCode: "lalu", + EventID: "UserRoomDailyStatsUpdated:sess-2:2026-07-01", + UserID: 42, + StatDate: "2026-07-01", + RoomOnlineDeltaMS: 300_000, + OccurredAtMS: occurredAt, + }); err != nil { + t.Fatalf("consume second server room online fact: %v", err) + } + + var roomStayMS, roomOnlineMS, roomJoinOK int64 + if err := repository.db.QueryRowContext(ctx, ` + SELECT room_stay_ms, room_online_ms, room_join_success + FROM stat_social_user_day + WHERE app_code = 'lalu' AND stat_tz = 'UTC' AND stat_day = '2026-07-01' AND subject_key = 'u:42' + `).Scan(&roomStayMS, &roomOnlineMS, &roomJoinOK); err != nil { + t.Fatalf("query stat_social_user_day: %v", err) + } + // 双轨分列:客户端埋点只进 room_stay_ms,服务端事实只进 room_online_ms,互不双计。 + if roomStayMS != 60_000 || roomOnlineMS != 900_000 || roomJoinOK != 1 { + t.Fatalf("social user day mismatch: room_stay=%d room_online=%d join_ok=%d", roomStayMS, roomOnlineMS, roomJoinOK) + } + + rows, err := repository.querySocialUserDays(ctx, "lalu", "UTC", "2026-07-01", "2026-07-01", 0, 0, nil) + if err != nil { + t.Fatalf("query social user days: %v", err) + } + var found bool + for _, row := range rows { + if row.Subject != "u:42" { + continue + } + found = true + // 查询口径取 GREATEST(room_stay_ms, room_online_ms):切换期两条来源并存也不会低估在房时长。 + if row.RoomStayMS != 900_000 || row.RoomOnlineMS != 900_000 { + t.Fatalf("query clamp mismatch: %+v", row) + } + } + if !found { + t.Fatalf("subject u:42 not returned by querySocialUserDays: %+v", rows) + } +} diff --git a/services/statistics-service/internal/storage/mysql/social_user_day.go b/services/statistics-service/internal/storage/mysql/social_user_day.go index 42602195..1f5796ba 100644 --- a/services/statistics-service/internal/storage/mysql/social_user_day.go +++ b/services/statistics-service/internal/storage/mysql/social_user_day.go @@ -42,6 +42,7 @@ type socialUserDayDelta struct { ProbabilityPanel int64 AppStayMS int64 RoomStayMS int64 + RoomOnlineMS int64 MicStayMS int64 RechargeCount int64 RechargeUSDMinor int64 @@ -120,6 +121,7 @@ func applySocialUserDayDelta(ctx context.Context, tx *sql.Tx, delta socialUserDa probability_game_panel_open = GREATEST(probability_game_panel_open, ?), app_stay_ms = app_stay_ms + ?, room_stay_ms = room_stay_ms + ?, + room_online_ms = room_online_ms + ?, mic_stay_ms = mic_stay_ms + ?, recharge_count = recharge_count + ?, recharge_usd_minor = recharge_usd_minor + ?, @@ -147,7 +149,7 @@ func applySocialUserDayDelta(ctx context.Context, tx *sql.Tx, delta socialUserDa flagValue(delta.MicUp), flagValue(delta.Gift), flagValue(delta.NormalGift), flagValue(delta.LuckyGift), flagValue(delta.SuperGift), flagValue(delta.Recharge), flagValue(delta.FirstRecharge), flagValue(delta.RepeatRecharge), flagValue(delta.GameBet), flagValue(delta.SelfGameBet), flagValue(delta.ProbabilityBet), flagValue(delta.Chat), flagValue(delta.FollowUser), flagValue(delta.FollowRoom), flagValue(delta.GiftPanel), - flagValue(delta.ProbabilityPanel), normalizeID(delta.AppStayMS), normalizeID(delta.RoomStayMS), normalizeID(delta.MicStayMS), + flagValue(delta.ProbabilityPanel), normalizeID(delta.AppStayMS), normalizeID(delta.RoomStayMS), normalizeID(delta.RoomOnlineMS), normalizeID(delta.MicStayMS), normalizeID(delta.RechargeCount), normalizeID(delta.RechargeUSDMinor), normalizeID(delta.GoogleRechargeUSDMinor), normalizeID(delta.ThirdPartyRechargeUSDMinor), normalizeID(delta.CoinSellerRechargeUSDMinor), normalizeID(delta.FirstRechargeUSDMinor), normalizeID(delta.RepeatRechargeUSDMinor), normalizeID(delta.NormalGiftCoin), normalizeID(delta.LuckyGiftCoin), normalizeID(delta.SuperGiftCoin), normalizeID(delta.LuckyGiftPayoutCoin), @@ -234,6 +236,8 @@ func socialDeltaForAppTrackingEvent(event AppTrackingEvent, scope statDayScope, return socialUserDayDelta{}, false } delta.Active = 1 + // 上麦成功隐含进房成功,补置进房标志,保证进房人数 >= 上麦人数。 + delta.RoomJoinOK = 1 delta.MicUp = 1 case "send_message": if !event.Success && strings.TrimSpace(event.ErrorCode) != "" { diff --git a/services/user-service/configs/config.docker.yaml b/services/user-service/configs/config.docker.yaml index 9f00df4a..1d8c2a82 100644 --- a/services/user-service/configs/config.docker.yaml +++ b/services/user-service/configs/config.docker.yaml @@ -36,6 +36,9 @@ invite_recharge_worker: enabled: true mic_time_worker: enabled: true +room_time_worker: + enabled: true + consumer_group: "hyapp-user-roomtime-room-outbox" cp_relationship_worker: enabled: true consumer_group: "hyapp-user-cp-room-outbox" diff --git a/services/user-service/configs/config.tencent.example.yaml b/services/user-service/configs/config.tencent.example.yaml index 6e6c7150..53d052da 100644 --- a/services/user-service/configs/config.tencent.example.yaml +++ b/services/user-service/configs/config.tencent.example.yaml @@ -36,6 +36,9 @@ invite_recharge_worker: enabled: true mic_time_worker: enabled: true +room_time_worker: + enabled: true + consumer_group: "hyapp-user-roomtime-room-outbox" cp_relationship_worker: enabled: true consumer_group: "hyapp-user-cp-room-outbox" diff --git a/services/user-service/configs/config.yaml b/services/user-service/configs/config.yaml index d7559424..7db2e170 100644 --- a/services/user-service/configs/config.yaml +++ b/services/user-service/configs/config.yaml @@ -37,6 +37,9 @@ invite_recharge_worker: enabled: true mic_time_worker: enabled: true +room_time_worker: + enabled: true + consumer_group: "hyapp-user-roomtime-room-outbox" cp_relationship_worker: enabled: true consumer_group: "hyapp-user-cp-room-outbox" 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 646fc9e4..21ba7657 100644 --- a/services/user-service/deploy/mysql/initdb/001_user_service.sql +++ b/services/user-service/deploy/mysql/initdb/001_user_service.sql @@ -193,6 +193,44 @@ CREATE TABLE IF NOT EXISTS manager_user_blocks ( KEY idx_manager_user_blocks_expire (app_code, status, blocked_until_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='经理中心用户封禁记录表'; +CREATE TABLE IF NOT EXISTS admin_user_bans ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + ban_id VARCHAR(96) NOT NULL COMMENT '管理员封禁事实 ID', + command_id VARCHAR(128) NOT NULL COMMENT '后台请求幂等命令 ID', + target_user_id BIGINT NOT NULL COMMENT '被封禁用户 ID', + target_old_status VARCHAR(32) NOT NULL COMMENT '创建事实前的用户状态,仅供审计', + expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '到期时间,UTC epoch ms;0 表示永久', + status VARCHAR(32) NOT NULL COMMENT 'active/released/expired', + reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '封禁原因', + operator_admin_id BIGINT NOT NULL COMMENT '创建封禁的后台管理员 ID', + released_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '手动解封管理员 ID;系统到期为 0', + released_reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '释放原因', + released_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '释放时间,UTC epoch ms', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, ban_id), + UNIQUE KEY uk_admin_user_bans_command (app_code, command_id), + KEY idx_admin_user_bans_target (app_code, target_user_id, status, created_at_ms), + KEY idx_admin_user_bans_expire (app_code, status, expires_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='后台管理员用户封禁事实表'; + +-- 空 ban_id 解封会按用户选择最新 active 管理员事实;独立命令表把一次选择固定到 resolved_ban_id, +-- 避免网络重试继续释放下一条重叠封禁。 +CREATE TABLE IF NOT EXISTS admin_user_ban_release_commands ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + command_id VARCHAR(128) NOT NULL COMMENT '稳定解封命令 ID,通常取 request_id', + target_user_id BIGINT NOT NULL COMMENT '目标用户 ID', + requested_ban_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '调用方指定 ban_id;空表示选择最新 active 管理员封禁', + resolved_ban_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '本命令实际释放的 ban_id', + release_status VARCHAR(32) NOT NULL COMMENT 'released/expired', + operator_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '手动操作管理员 ID;系统到期为 0', + reason VARCHAR(255) NOT NULL DEFAULT '' 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, command_id), + KEY idx_admin_ban_release_resolved (app_code, resolved_ban_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='后台管理员解封命令幂等事实表'; + CREATE TABLE IF NOT EXISTS user_reports ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', report_id VARCHAR(96) NOT NULL COMMENT '举报单业务 ID', @@ -738,6 +776,70 @@ CREATE TABLE IF NOT EXISTS user_mic_event_consumption ( KEY idx_user_mic_event_user (app_code, user_id, created_at_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户麦位事件消费位点表'; +CREATE TABLE IF NOT EXISTS user_room_sessions ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + room_session_id VARCHAR(128) NOT NULL COMMENT '在房会话 ID,取 RoomUserJoined 事件 ID', + user_id BIGINT NOT NULL COMMENT '用户 ID', + room_id VARCHAR(64) NOT NULL COMMENT '房间 ID', + status VARCHAR(32) NOT NULL COMMENT '业务状态 open/ended', + is_robot TINYINT(1) NOT NULL DEFAULT 0 COMMENT '进房时固化的机器人标记,机器人会话不产生统计事实', + joined_at_ms BIGINT NOT NULL COMMENT '进房时间,UTC epoch ms', + ended_at_ms BIGINT NULL COMMENT '离房时间,UTC epoch ms', + end_reason VARCHAR(64) NOT NULL DEFAULT '' COMMENT '结束原因', + room_online_ms BIGINT NOT NULL DEFAULT 0 COMMENT '在房毫秒值', + opened_event_id VARCHAR(128) NOT NULL COMMENT '进房事件 ID', + closed_event_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '闭合事件 ID', + last_event_id VARCHAR(128) NOT NULL COMMENT '最后事件 ID', + last_room_version BIGINT NOT NULL DEFAULT 0 COMMENT '最后房间版本', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, room_session_id), + KEY idx_user_room_sessions_user_status (app_code, user_id, status, joined_at_ms), + KEY idx_user_room_sessions_room_user (app_code, room_id, user_id, status), + KEY idx_user_room_sessions_open_timeout (app_code, status, joined_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户在房会话表'; + +CREATE TABLE IF NOT EXISTS user_room_daily_stats ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + user_id BIGINT NOT NULL COMMENT '用户 ID', + stat_date CHAR(10) NOT NULL COMMENT '统计日期,UTC', + room_online_ms BIGINT NOT NULL DEFAULT 0 COMMENT '在房毫秒值', + session_count BIGINT NOT NULL DEFAULT 0 COMMENT '会话数量', + first_room_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '首次在房时间,UTC epoch ms', + last_room_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '最后在房时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, user_id, stat_date), + KEY idx_user_room_daily_date (app_code, stat_date, room_online_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户在房每日统计表'; + +CREATE TABLE IF NOT EXISTS user_room_orphan_leaves ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + event_id VARCHAR(128) NOT NULL COMMENT '离房事件 ID', + room_id VARCHAR(64) NOT NULL COMMENT '房间 ID', + user_id BIGINT NOT NULL COMMENT '用户 ID', + left_at_ms BIGINT NOT NULL COMMENT '离房时间,UTC epoch ms', + reason VARCHAR(64) NOT NULL DEFAULT '' COMMENT '离房原因', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + PRIMARY KEY (app_code, event_id), + KEY idx_user_room_orphan_room_user (app_code, room_id, user_id, left_at_ms), + KEY idx_user_room_orphan_left_at (app_code, left_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='先于进房事实到达的离房事件暂存表'; + +CREATE TABLE IF NOT EXISTS user_room_event_consumption ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + event_id VARCHAR(128) NOT NULL COMMENT '事件幂等 ID', + event_type VARCHAR(64) NOT NULL COMMENT '事件类型', + room_id VARCHAR(64) NOT NULL COMMENT '房间 ID', + user_id BIGINT NOT NULL COMMENT '用户 ID', + status VARCHAR(32) NOT NULL COMMENT '业务状态', + skip_reason VARCHAR(128) NOT NULL DEFAULT '' COMMENT '跳过原因', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + consumed_at_ms BIGINT NULL COMMENT '消费时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, event_id), + KEY idx_user_room_event_user (app_code, user_id, created_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户在房事件消费位点表'; + CREATE TABLE IF NOT EXISTS host_profiles ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', user_id BIGINT NOT NULL PRIMARY KEY COMMENT '用户 ID', diff --git a/services/user-service/deploy/mysql/migrations/010_admin_user_bans.sql b/services/user-service/deploy/mysql/migrations/010_admin_user_bans.sql new file mode 100644 index 00000000..abfeb90c --- /dev/null +++ b/services/user-service/deploy/mysql/migrations/010_admin_user_bans.sql @@ -0,0 +1,42 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +USE hyapp_user; + +-- 管理员封禁与经理中心封禁保持独立事实,解封时在 user-service 内同时检查两种来源。 +CREATE TABLE IF NOT EXISTS admin_user_bans ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + ban_id VARCHAR(96) NOT NULL COMMENT '管理员封禁事实 ID', + command_id VARCHAR(128) NOT NULL COMMENT '后台请求幂等命令 ID', + target_user_id BIGINT NOT NULL COMMENT '被封禁用户 ID', + target_old_status VARCHAR(32) NOT NULL COMMENT '创建事实前的用户状态,仅供审计', + expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '到期时间,UTC epoch ms;0 表示永久', + status VARCHAR(32) NOT NULL COMMENT 'active/released/expired', + reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '封禁原因', + operator_admin_id BIGINT NOT NULL COMMENT '创建封禁的后台管理员 ID', + released_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '手动解封管理员 ID;系统到期为 0', + released_reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '释放原因', + released_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '释放时间,UTC epoch ms', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, ban_id), + UNIQUE KEY uk_admin_user_bans_command (app_code, command_id), + KEY idx_admin_user_bans_target (app_code, target_user_id, status, created_at_ms), + KEY idx_admin_user_bans_expire (app_code, status, expires_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='后台管理员用户封禁事实表'; + +-- 解封命令必须独立保存幂等事实:后台在合并摘要只看到经理封禁时会按用户释放最新管理员封禁, +-- 若 HTTP/gRPC 超时后重试,不能继续释放下一条重叠的管理员封禁。 +CREATE TABLE IF NOT EXISTS admin_user_ban_release_commands ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + command_id VARCHAR(128) NOT NULL COMMENT '稳定解封命令 ID,通常取 request_id', + target_user_id BIGINT NOT NULL COMMENT '目标用户 ID', + requested_ban_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '调用方指定 ban_id;空表示选择最新 active 管理员封禁', + resolved_ban_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '本命令实际释放的 ban_id', + release_status VARCHAR(32) NOT NULL COMMENT 'released/expired', + operator_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '手动操作管理员 ID;系统到期为 0', + reason VARCHAR(255) NOT NULL DEFAULT '' 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, command_id), + KEY idx_admin_ban_release_resolved (app_code, resolved_ban_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='后台管理员解封命令幂等事实表'; diff --git a/services/user-service/deploy/mysql/migrations/011_user_room_sessions.sql b/services/user-service/deploy/mysql/migrations/011_user_room_sessions.sql new file mode 100644 index 00000000..572058f2 --- /dev/null +++ b/services/user-service/deploy/mysql/migrations/011_user_room_sessions.sql @@ -0,0 +1,69 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +USE hyapp_user; + +-- 用户在房时长服务端事实:消费 room outbox 的 RoomUserJoined/RoomUserLeft/RoomUserKicked, +-- 替代只靠客户端 room_stay 埋点的口径(杀进程丢时长导致进房时长偏低甚至小于上麦时长)。 +CREATE TABLE IF NOT EXISTS user_room_sessions ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + room_session_id VARCHAR(128) NOT NULL COMMENT '在房会话 ID,取 RoomUserJoined 事件 ID', + user_id BIGINT NOT NULL COMMENT '用户 ID', + room_id VARCHAR(64) NOT NULL COMMENT '房间 ID', + status VARCHAR(32) NOT NULL COMMENT '业务状态 open/ended', + is_robot TINYINT(1) NOT NULL DEFAULT 0 COMMENT '进房时固化的机器人标记,机器人会话不产生统计事实', + joined_at_ms BIGINT NOT NULL COMMENT '进房时间,UTC epoch ms', + ended_at_ms BIGINT NULL COMMENT '离房时间,UTC epoch ms', + end_reason VARCHAR(64) NOT NULL DEFAULT '' COMMENT '结束原因', + room_online_ms BIGINT NOT NULL DEFAULT 0 COMMENT '在房毫秒值', + opened_event_id VARCHAR(128) NOT NULL COMMENT '进房事件 ID', + closed_event_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '闭合事件 ID', + last_event_id VARCHAR(128) NOT NULL COMMENT '最后事件 ID', + last_room_version BIGINT NOT NULL DEFAULT 0 COMMENT '最后房间版本', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, room_session_id), + KEY idx_user_room_sessions_user_status (app_code, user_id, status, joined_at_ms), + KEY idx_user_room_sessions_room_user (app_code, room_id, user_id, status), + KEY idx_user_room_sessions_open_timeout (app_code, status, joined_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户在房会话表'; + +CREATE TABLE IF NOT EXISTS user_room_daily_stats ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + user_id BIGINT NOT NULL COMMENT '用户 ID', + stat_date CHAR(10) NOT NULL COMMENT '统计日期,UTC', + room_online_ms BIGINT NOT NULL DEFAULT 0 COMMENT '在房毫秒值', + session_count BIGINT NOT NULL DEFAULT 0 COMMENT '会话数量', + first_room_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '首次在房时间,UTC epoch ms', + last_room_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '最后在房时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, user_id, stat_date), + KEY idx_user_room_daily_date (app_code, stat_date, room_online_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户在房每日统计表'; + +CREATE TABLE IF NOT EXISTS user_room_orphan_leaves ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + event_id VARCHAR(128) NOT NULL COMMENT '离房事件 ID', + room_id VARCHAR(64) NOT NULL COMMENT '房间 ID', + user_id BIGINT NOT NULL COMMENT '用户 ID', + left_at_ms BIGINT NOT NULL COMMENT '离房时间,UTC epoch ms', + reason VARCHAR(64) NOT NULL DEFAULT '' COMMENT '离房原因', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + PRIMARY KEY (app_code, event_id), + KEY idx_user_room_orphan_room_user (app_code, room_id, user_id, left_at_ms), + KEY idx_user_room_orphan_left_at (app_code, left_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='先于进房事实到达的离房事件暂存表'; + +CREATE TABLE IF NOT EXISTS user_room_event_consumption ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + event_id VARCHAR(128) NOT NULL COMMENT '事件幂等 ID', + event_type VARCHAR(64) NOT NULL COMMENT '事件类型', + room_id VARCHAR(64) NOT NULL COMMENT '房间 ID', + user_id BIGINT NOT NULL COMMENT '用户 ID', + status VARCHAR(32) NOT NULL COMMENT '业务状态', + skip_reason VARCHAR(128) NOT NULL DEFAULT '' COMMENT '跳过原因', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + consumed_at_ms BIGINT NULL COMMENT '消费时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, event_id), + KEY idx_user_room_event_user (app_code, user_id, created_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户在房事件消费位点表'; diff --git a/services/user-service/internal/app/app.go b/services/user-service/internal/app/app.go index 77a9b9cb..dfa1db93 100644 --- a/services/user-service/internal/app/app.go +++ b/services/user-service/internal/app/app.go @@ -33,6 +33,7 @@ import ( cpdomain "hyapp/services/user-service/internal/domain/cp" invitedomain "hyapp/services/user-service/internal/domain/invite" mictimedomain "hyapp/services/user-service/internal/domain/mictime" + roomtimedomain "hyapp/services/user-service/internal/domain/roomtime" "hyapp/services/user-service/internal/integration/activityclient" "hyapp/services/user-service/internal/integration/roomclient" "hyapp/services/user-service/internal/integration/walletclient" @@ -41,6 +42,7 @@ import ( hostservice "hyapp/services/user-service/internal/service/host" inviteservice "hyapp/services/user-service/internal/service/invite" mictimeservice "hyapp/services/user-service/internal/service/mictime" + roomtimeservice "hyapp/services/user-service/internal/service/roomtime" userservice "hyapp/services/user-service/internal/service/user" mysqlstorage "hyapp/services/user-service/internal/storage/mysql" grpcserver "hyapp/services/user-service/internal/transport/grpc" @@ -78,6 +80,8 @@ type App struct { inviteSvc *inviteservice.Service // micTimeSvc 消费 room mic outbox,维护用户维度麦上时长 read model。 micTimeSvc *mictimeservice.Service + // roomTimeSvc 消费 room presence outbox,维护用户维度在房时长 read model。 + roomTimeSvc *roomtimeservice.Service // cpSvc 消费 room gift outbox,维护 CP/兄弟/姐妹申请和亲密值。 cpSvc *cpservice.Service // loginRiskRedisClose 关闭登录风险 Redis cache;cache 不作为启动硬依赖。 @@ -133,6 +137,7 @@ func New(cfg config.Config) (*App, error) { hostRepo := mysqlRepo.HostRepository() inviteRepo := mysqlRepo.InviteRepository() micTimeRepo := mysqlRepo.MicTimeRepository() + roomTimeRepo := mysqlRepo.RoomTimeRepository() cpRepo := mysqlRepo.CPRepository() var ipDecisionCache authservice.IPDecisionCache var registerRiskConfigCache authservice.RegisterRiskConfigCache @@ -313,12 +318,13 @@ func New(cfg config.Config) (*App, error) { ) inviteSvc := inviteservice.New(inviteRepo) micTimeSvc := mictimeservice.New(micTimeRepo) + roomTimeSvc := roomtimeservice.New(roomTimeRepo) cpSvc := cpservice.New(cpRepo, // CP service 同时承担送礼事件消费和榜单读模型刷新;Redis/wallet 依赖只在榜单相关方法里被强校验。 cpservice.WithIntimacyLeaderboardStore(cpLeaderboardStore), cpservice.WithAvatarFrameReader(avatarFrameReader), ) - mqConsumers, err := newMQConsumers(cfg, inviteSvc, micTimeSvc, cpSvc) + mqConsumers, err := newMQConsumers(cfg, inviteSvc, micTimeSvc, roomTimeSvc, cpSvc) if err != nil { if loginRiskRedisClose != nil { _ = loginRiskRedisClose() @@ -366,6 +372,7 @@ func New(cfg config.Config) (*App, error) { } userServer := grpcserver.NewServer(authSvc, userSvc, hostSvc) userServer.SetMicTimeService(micTimeSvc) + userServer.SetRoomTimeService(roomTimeSvc) userServer.SetCPService(cpSvc) // 多个 protobuf service 共用一个 Server 适配器,领域逻辑仍拆在 auth/user/host service。 userv1.RegisterAuthServiceServer(server, userServer) @@ -427,6 +434,7 @@ func New(cfg config.Config) (*App, error) { userSvc: userSvc, inviteSvc: inviteSvc, micTimeSvc: micTimeSvc, + roomTimeSvc: roomTimeSvc, cpSvc: cpSvc, loginRiskRedisClose: loginRiskRedisClose, cpLeaderboardRedisClose: cpLeaderboardRedisClose, @@ -630,8 +638,8 @@ func (i tencentIMAccountImporter) ImportAccount(ctx context.Context, userID int6 }) } -func newMQConsumers(cfg config.Config, inviteSvc *inviteservice.Service, micTimeSvc *mictimeservice.Service, cpSvc *cpservice.Service) ([]*rocketmqx.Consumer, error) { - consumers := make([]*rocketmqx.Consumer, 0, 3) +func newMQConsumers(cfg config.Config, inviteSvc *inviteservice.Service, micTimeSvc *mictimeservice.Service, roomTimeSvc *roomtimeservice.Service, cpSvc *cpservice.Service) ([]*rocketmqx.Consumer, error) { + consumers := make([]*rocketmqx.Consumer, 0, 4) if cfg.InviteRechargeWorker.Enabled && cfg.RocketMQ.WalletOutbox.Enabled { consumer, err := rocketmqx.NewConsumer(walletOutboxConsumerConfig(cfg.RocketMQ)) if err != nil { @@ -670,6 +678,27 @@ func newMQConsumers(cfg config.Config, inviteSvc *inviteservice.Service, micTime } consumers = append(consumers, consumer) } + if cfg.RoomTimeWorker.Enabled && cfg.RocketMQ.RoomOutbox.Enabled { + // 在房时长消费使用独立 consumer group,保证和麦位时长/CP 读模型各自拥有 MQ 位点和重试节奏。 + consumer, err := rocketmqx.NewConsumer(roomTimeOutboxConsumerConfig(cfg)) + if err != nil { + shutdownMQConsumers(consumers) + return nil, err + } + if err := consumer.Subscribe(cfg.RocketMQ.RoomOutbox.Topic, roommq.TagRoomOutboxEvent, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { + event, ok, err := roomPresenceEventFromRoomMessage(message.Body) + if err != nil || !ok { + return err + } + _, err = roomTimeSvc.ConsumeRoomPresenceEvent(appcode.WithContext(ctx, event.AppCode), event) + return err + }); err != nil { + _ = consumer.Shutdown() + shutdownMQConsumers(consumers) + return nil, err + } + consumers = append(consumers, consumer) + } if cfg.CPRelationshipWorker.Enabled && cfg.RocketMQ.RoomOutbox.Enabled { // CP 关系消费使用独立 consumer group,保证和麦位时长读模型各自拥有 MQ 位点和重试节奏。 consumer, err := rocketmqx.NewConsumer(cpRoomOutboxConsumerConfig(cfg)) @@ -750,6 +779,46 @@ func roomMicEventFromRoomMessage(body []byte) (mictimedomain.RoomMicEvent, bool, }, true, nil } +func roomPresenceEventFromRoomMessage(body []byte) (roomtimedomain.RoomPresenceEvent, bool, error) { + envelope, _, err := roommq.DecodeRoomOutboxMessage(body) + if err != nil { + return roomtimedomain.RoomPresenceEvent{}, false, err + } + event := roomtimedomain.RoomPresenceEvent{ + AppCode: appcode.Normalize(envelope.GetAppCode()), + EventID: envelope.GetEventId(), + EventType: envelope.GetEventType(), + RoomID: envelope.GetRoomId(), + RoomVersion: envelope.GetRoomVersion(), + OccurredAtMs: envelope.GetOccurredAtMs(), + } + switch envelope.GetEventType() { + case roomtimedomain.RoomUserJoinedEventType: + var joined roomeventsv1.RoomUserJoined + if err := proto.Unmarshal(envelope.GetBody(), &joined); err != nil { + return roomtimedomain.RoomPresenceEvent{}, false, err + } + event.UserID = joined.GetUserId() + event.IsRobot = joined.GetIsRobot() + case roomtimedomain.RoomUserLeftEventType: + var left roomeventsv1.RoomUserLeft + if err := proto.Unmarshal(envelope.GetBody(), &left); err != nil { + return roomtimedomain.RoomPresenceEvent{}, false, err + } + event.UserID = left.GetUserId() + case roomtimedomain.RoomUserKickedEventType: + // 踢人/系统驱逐/关房清场只发 RoomUserKicked,不再补 RoomUserLeft;presence 主体是 target_user_id。 + var kicked roomeventsv1.RoomUserKicked + if err := proto.Unmarshal(envelope.GetBody(), &kicked); err != nil { + return roomtimedomain.RoomPresenceEvent{}, false, err + } + event.UserID = kicked.GetTargetUserId() + default: + return roomtimedomain.RoomPresenceEvent{}, false, nil + } + return event, true, nil +} + func roomGiftCPEventFromRoomMessage(body []byte) (cpdomain.GiftEvent, bool, error) { envelope, _, err := roommq.DecodeRoomOutboxMessage(body) if err != nil { @@ -835,6 +904,10 @@ func cpRoomOutboxConsumerConfig(cfg config.Config) rocketmqx.ConsumerConfig { return rocketmqConsumerConfig(cfg.RocketMQ, cfg.CPRelationshipWorker.ConsumerGroup, cfg.RocketMQ.RoomOutbox.ConsumerMaxReconsumeTimes) } +func roomTimeOutboxConsumerConfig(cfg config.Config) rocketmqx.ConsumerConfig { + return rocketmqConsumerConfig(cfg.RocketMQ, cfg.RoomTimeWorker.ConsumerGroup, cfg.RocketMQ.RoomOutbox.ConsumerMaxReconsumeTimes) +} + func userOutboxProducerConfig(cfg config.RocketMQConfig) rocketmqx.ProducerConfig { return rocketmqx.ProducerConfig{ EndpointConfig: rocketmqx.EndpointConfig{ diff --git a/services/user-service/internal/config/config.go b/services/user-service/internal/config/config.go index 41db61fa..00397ca2 100644 --- a/services/user-service/internal/config/config.go +++ b/services/user-service/internal/config/config.go @@ -39,6 +39,8 @@ type Config struct { InviteRechargeWorker InviteRechargeWorkerConfig `yaml:"invite_recharge_worker"` // MicTimeWorker 控制 room-service 麦位事件消费和用户麦上时长聚合。 MicTimeWorker MicTimeWorkerConfig `yaml:"mic_time_worker"` + // RoomTimeWorker 控制 room-service 进退房事件消费和用户在房时长聚合。 + RoomTimeWorker RoomTimeWorkerConfig `yaml:"room_time_worker"` // CPRelationshipWorker 控制 room-service 送礼事件消费和 CP 关系申请/亲密值维护。 CPRelationshipWorker CPRelationshipWorkerConfig `yaml:"cp_relationship_worker"` // CPIntimacyLeaderboard 控制 CP 亲密值排行榜 Redis 读模型。 @@ -186,6 +188,14 @@ type MicTimeWorkerConfig struct { Enabled bool `yaml:"enabled"` } +// RoomTimeWorkerConfig 保存房间进退房事件消费策略。 +type RoomTimeWorkerConfig struct { + // Enabled 控制是否启动 room outbox MQ 消费;关闭后查询仍可读取已聚合数据。 + Enabled bool `yaml:"enabled"` + // ConsumerGroup 必须独立于麦位/CP 消费,避免读模型共享 MQ 位点。 + ConsumerGroup string `yaml:"consumer_group"` +} + // CPRelationshipWorkerConfig 保存 CP 礼物事件消费策略。 type CPRelationshipWorkerConfig struct { // Enabled 控制是否启动 room gift MQ 消费;关闭后只能处理历史已消费关系。 @@ -290,6 +300,10 @@ func Default() Config { MicTimeWorker: MicTimeWorkerConfig{ Enabled: false, }, + RoomTimeWorker: RoomTimeWorkerConfig{ + Enabled: false, + ConsumerGroup: "hyapp-user-roomtime-room-outbox", + }, CPRelationshipWorker: CPRelationshipWorkerConfig{ Enabled: false, ConsumerGroup: "hyapp-user-cp-room-outbox", @@ -455,6 +469,13 @@ func Load(path string) (Config, error) { if cfg.MicTimeWorker.Enabled && !cfg.RocketMQ.RoomOutbox.Enabled { return Config{}, errors.New("mic_time_worker requires rocketmq.room_outbox.enabled") } + cfg.RoomTimeWorker.ConsumerGroup = strings.TrimSpace(cfg.RoomTimeWorker.ConsumerGroup) + if cfg.RoomTimeWorker.ConsumerGroup == "" { + cfg.RoomTimeWorker.ConsumerGroup = "hyapp-user-roomtime-room-outbox" + } + if cfg.RoomTimeWorker.Enabled && !cfg.RocketMQ.RoomOutbox.Enabled { + return Config{}, errors.New("room_time_worker requires rocketmq.room_outbox.enabled") + } cfg.CPRelationshipWorker.ConsumerGroup = strings.TrimSpace(cfg.CPRelationshipWorker.ConsumerGroup) if cfg.CPRelationshipWorker.ConsumerGroup == "" { cfg.CPRelationshipWorker.ConsumerGroup = "hyapp-user-cp-room-outbox" diff --git a/services/user-service/internal/domain/roomtime/roomtime.go b/services/user-service/internal/domain/roomtime/roomtime.go new file mode 100644 index 00000000..4db5ef40 --- /dev/null +++ b/services/user-service/internal/domain/roomtime/roomtime.go @@ -0,0 +1,69 @@ +// Package roomtime defines user-scoped in-room duration facts. +package roomtime + +const ( + // RoomUserJoinedEventType opens an in-room session when the durable outbox fact arrives. + RoomUserJoinedEventType = "RoomUserJoined" + // RoomUserLeftEventType closes an in-room session on voluntary or stale-swept leave. + RoomUserLeftEventType = "RoomUserLeft" + // RoomUserKickedEventType closes an in-room session; kick/system evict/close room 只发该事实,不再补 RoomUserLeft。 + RoomUserKickedEventType = "RoomUserKicked" + + // SessionStatusOpen means the user is considered inside the room by the read model. + SessionStatusOpen = "open" + // SessionStatusEnded is terminal and must never be reopened by replayed events. + SessionStatusEnded = "ended" + + // EventTypeUserRoomDailyStatsUpdated is emitted for each UTC day touched by a closed session. + EventTypeUserRoomDailyStatsUpdated = "UserRoomDailyStatsUpdated" + + // EndReasonLeft closes a session from RoomUserLeft. + EndReasonLeft = "left" + // EndReasonKicked closes a session from RoomUserKicked(含系统驱逐与关房清场). + EndReasonKicked = "kicked" + // EndReasonSupersededByJoin closes a lingering open session in another room when a newer join arrives. + EndReasonSupersededByJoin = "superseded_by_join" + // EndReasonSupersededByRejoin closes a lingering open session in the same room when a newer join arrives. + EndReasonSupersededByRejoin = "superseded_by_rejoin" + // EndReasonOrphanLeft closes a session synthesized from a leave fact that arrived before its join fact. + EndReasonOrphanLeft = "orphan_left" + + // CompensationReasonOpenSessionMaxWindow closes open sessions at a configured safety ceiling. + CompensationReasonOpenSessionMaxWindow = "compensated_open_session_max_window" +) + +// RoomPresenceEvent is the decoded room presence fact used by user-service in-room duration aggregation. +type RoomPresenceEvent struct { + AppCode string + EventID string + EventType string + RoomID string + RoomVersion int64 + OccurredAtMs int64 + // UserID is the presence subject: RoomUserJoined/RoomUserLeft 的 user_id,RoomUserKicked 的 target_user_id。 + UserID int64 + // IsRobot 只在 RoomUserJoined 上有意义,会话开启时固化,机器人会话不产生统计事实。 + IsRobot bool +} + +// ApplyResult describes one idempotent event application. +type ApplyResult struct { + Consumed bool + Skipped bool + Opened bool + Closed bool + Reason string +} + +// CompensationOptions bounds abnormal open sessions so missing leave events cannot accumulate forever. +type CompensationOptions struct { + NowMs int64 + BatchSize int + OpenSessionMaxAgeMs int64 +} + +// CompensationResult summarizes one compensation scan. +type CompensationResult struct { + ClosedCount int + OrphanLeavesDeleted int +} diff --git a/services/user-service/internal/domain/user/admin.go b/services/user-service/internal/domain/user/admin.go new file mode 100644 index 00000000..b5714133 --- /dev/null +++ b/services/user-service/internal/domain/user/admin.go @@ -0,0 +1,56 @@ +package user + +const ( + // AdminRoleHost 表示当前有效主播身份。 + AdminRoleHost = "host" + // AdminRoleAgency 表示当前有效公会 owner 身份,普通公会成员不会获得该角色。 + AdminRoleAgency = "agency" + // AdminRoleBD 表示当前有效普通 BD 身份。 + AdminRoleBD = "bd" + // AdminRoleBDLeader 表示当前有效 BD Leader 身份;它可以和普通 BD 身份同时存在。 + AdminRoleBDLeader = "bd_leader" + // AdminRoleCoinSeller 表示当前有效币商身份。 + AdminRoleCoinSeller = "coin_seller" + // AdminRoleManager 表示当前有效经理身份。 + AdminRoleManager = "manager" +) + +const ( + // BanSourceAdmin 表示有效封禁来自后台管理员事实表。 + BanSourceAdmin = "admin" + // BanSourceManager 表示有效封禁来自经理中心事实表。 + BanSourceManager = "manager" + // BanSourceLegacy 表示历史 banned/disabled 状态没有可管理的封禁事实,必须按永久处理。 + BanSourceLegacy = "legacy" +) + +// ActiveBanSummary 是后台列表读取的合并封禁视图。 +// 多个来源重叠时,Permanent 只要命中任一永久事实即为 true;否则 ExpiresAtMs 取最晚到期时间。 +type ActiveBanSummary struct { + Active bool + Source string + BanID string + Permanent bool + ExpiresAtMs int64 + UserStatus Status + OperatorType string + OperatorUserID int64 + Reason string + CreatedAtMs int64 + ActiveBanCount int32 +} + +// AdminProfile 是 user-service 为后台用户列表提供的 owner 事实投影。 +// 钱包余额、等级等其他 owner 的字段由 admin-server 分别批量聚合,不能塞进该查询回查跨库数据。 +type AdminProfile struct { + User User + BirthDate string + RegisterDevice string + LastSuccessLoginAtMs int64 + Roles []string + Ban ActiveBanSummary + LastOperatorType string + LastOperatorUserID int64 + LastOperationReason string + LastOperationAtMs int64 +} diff --git a/services/user-service/internal/domain/user/user.go b/services/user-service/internal/domain/user/user.go index b4a5255a..f47e4cb0 100644 --- a/services/user-service/internal/domain/user/user.go +++ b/services/user-service/internal/domain/user/user.go @@ -934,7 +934,7 @@ func ValidResolvableDisplayUserID(value string) bool { // ValidAdminPrettyDisplayUserID 校验后台直接发放的靓号内容。 func ValidAdminPrettyDisplayUserID(value string) bool { - // 后台发放支持阿拉伯语、英文和数字;禁止空白、控制字符、emoji 与标点,避免登录和展示链路出现不可输入字符。 + // 靓号是运营展示文本而非登录凭据,必须接受 Unicode 字体、符号和 emoji;仍拒绝空值、首尾空白及控制字符,避免换行等不可见控制码污染列表、日志和协议载荷。 if value == "" || strings.TrimSpace(value) != value { return false } @@ -942,10 +942,9 @@ func ValidAdminPrettyDisplayUserID(value string) bool { return false } for _, r := range value { - if unicode.IsLetter(r) || unicode.IsDigit(r) || unicode.IsMark(r) { - continue + if unicode.IsControl(r) { + return false } - return false } return true } diff --git a/services/user-service/internal/domain/user/user_test.go b/services/user-service/internal/domain/user/user_test.go index cd238451..cd418902 100644 --- a/services/user-service/internal/domain/user/user_test.go +++ b/services/user-service/internal/domain/user/user_test.go @@ -23,14 +23,14 @@ func TestValidDisplayUserIDAllowsFiveDigitSeedAccounts(t *testing.T) { func TestValidResolvableDisplayUserIDAllowsDefaultAndPrettyIDs(t *testing.T) { t.Parallel() - valid := []string{"10001", "123456", "1111cc1111", "VIP2026", "ملك123", "Cafe\u0301123"} + valid := []string{"10001", "123456", "1111cc1111", "VIP2026", "ملك123", "Cafe\u0301123", "𝕸⃝é中⚡️™"} for _, value := range valid { if !ValidResolvableDisplayUserID(value) { t.Fatalf("resolvable display_user_id %q should be valid", value) } } - invalid := []string{"", " ", "VIP-2026", "VIP 2026", "VIP😀", "\nVIP", "VIP!"} + invalid := []string{"", " ", " VIP", "VIP ", "\nVIP", "VIP\x00"} for _, value := range invalid { if ValidResolvableDisplayUserID(value) { t.Fatalf("resolvable display_user_id %q should be invalid", value) @@ -41,14 +41,15 @@ func TestValidResolvableDisplayUserIDAllowsDefaultAndPrettyIDs(t *testing.T) { func TestValidAdminPrettyDisplayUserID(t *testing.T) { t.Parallel() - valid := []string{"VIP2026", "ملك123", "Cafe\u0301123"} + // Unicode 字体可能含数学字母、组合标记、符号及 emoji;后台靓号必须完整保留这些展示字符。 + valid := []string{"VIP2026", "ملك123", "Cafe\u0301123", "𝕸⃝é中⚡️™", "VIP-2026", "VIP 2026", "VIP😀", "VIP!"} for _, value := range valid { if !ValidAdminPrettyDisplayUserID(value) { t.Fatalf("admin pretty display_user_id %q should be valid", value) } } - invalid := []string{"", " ", "VIP-2026", "VIP 2026", "VIP😀", "\nVIP", "VIP!"} + invalid := []string{"", " ", " VIP", "VIP ", "\nVIP", "VIP\x00"} for _, value := range invalid { if ValidAdminPrettyDisplayUserID(value) { t.Fatalf("admin pretty display_user_id %q should be invalid", value) diff --git a/services/user-service/internal/service/host/commands.go b/services/user-service/internal/service/host/commands.go index 78bd6ea7..a578b374 100644 --- a/services/user-service/internal/service/host/commands.go +++ b/services/user-service/internal/service/host/commands.go @@ -1,6 +1,6 @@ package host -// SearchAgenciesCommand 描述同国家 Agency 搜索条件。 +// SearchAgenciesCommand 描述 Agency 搜索条件;范围由持久化层按 app_code 的角色区域策略决定。 type SearchAgenciesCommand struct { UserID int64 Keyword string diff --git a/services/user-service/internal/service/host/service.go b/services/user-service/internal/service/host/service.go index 8b7d82fe..2575f50a 100644 --- a/services/user-service/internal/service/host/service.go +++ b/services/user-service/internal/service/host/service.go @@ -106,7 +106,7 @@ func WithClock(now func() time.Time) Option { } } -// SearchAgencies 返回当前用户同国家可加入的有效 Agency。 +// SearchAgencies 返回当前用户可加入的有效 Agency;持久化层按 app_code 决定 Huwaa 全域或其他 App 同国家范围。 func (s *Service) SearchAgencies(ctx context.Context, userID int64, keyword string, pageSize int32) ([]hostdomain.Agency, error) { if s.repository == nil { return nil, xerr.New(xerr.Unavailable, "host repository is not configured") @@ -120,7 +120,7 @@ func (s *Service) SearchAgencies(ctx context.Context, userID int64, keyword stri limit = 50 } - // 业务层只负责输入归一化;用户国家过滤由持久化层读取 users 当前事实完成。 + // 业务层只负责输入归一化;App 级区域策略和用户国家事实都由持久化层统一执行。 return s.repository.SearchAgencies(ctx, SearchAgenciesCommand{ UserID: userID, Keyword: strings.TrimSpace(keyword), @@ -282,7 +282,7 @@ func (s *Service) InviteBD(ctx context.Context, command InviteBDInput) (hostdoma if err := s.requireWriteDependencies(); err != nil { return hostdomain.RoleInvitation{}, err } - // 负责人身份、区域、目标是否已有 BD 都交给持久化层在同一事务中校验,避免发出不可处理的待确认消息。 + // 负责人身份、App 级区域策略、目标是否已有 BD 都在同一事务中校验,避免发出不可处理的待确认消息。 if strings.TrimSpace(command.CommandID) == "" || command.InviterUserID <= 0 || command.TargetUserID <= 0 { return hostdomain.RoleInvitation{}, xerr.New(xerr.InvalidArgument, "command_id, inviter_user_id and target_user_id are required") } diff --git a/services/user-service/internal/service/host/service_test.go b/services/user-service/internal/service/host/service_test.go index 34f304d7..829620af 100644 --- a/services/user-service/internal/service/host/service_test.go +++ b/services/user-service/internal/service/host/service_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "hyapp/pkg/appcode" "hyapp/pkg/xerr" hostdomain "hyapp/services/user-service/internal/domain/host" userdomain "hyapp/services/user-service/internal/domain/user" @@ -36,8 +37,13 @@ func seedActiveUser(t *testing.T, repository *mysqltest.Repository, userID int64 } func seedActiveUserInCountry(t *testing.T, repository *mysqltest.Repository, userID int64, regionID int64, country string, avatar string) { + seedActiveUserInAppAndCountry(t, repository, appcode.Default, userID, regionID, country, avatar) +} + +func seedActiveUserInAppAndCountry(t *testing.T, repository *mysqltest.Repository, app string, userID int64, regionID int64, country string, avatar string) { t.Helper() repository.PutUser(userdomain.User{ + AppCode: app, UserID: userID, DefaultDisplayUserID: displayID(userID), CurrentDisplayUserID: displayID(userID), @@ -241,6 +247,47 @@ func TestApplyReviewApproveCreatesHostMembershipIdempotently(t *testing.T) { } } +func TestDefaultAppHostApplicationStillRejectsCrossRegionAtApplyAndReview(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + seedActiveUser(t, repository, 101, 10) + seedActiveUser(t, repository, 202, 20) + seedActiveUser(t, repository, 203, 10) + repository.PutAgency(hostdomain.Agency{ + AgencyID: 301, + OwnerUserID: 101, + RegionID: 10, + Status: hostdomain.AgencyStatusActive, + JoinEnabled: true, + }) + svc := newHostService(repository, 1_500, 2_500) + + if _, err := svc.ApplyToAgency(ctx, hostservice.ApplyToAgencyInput{ + CommandID: "lalu-apply-cross-region", + UserID: 202, + AgencyID: 301, + }); xerr.CodeOf(err) != xerr.PermissionDenied { + t.Fatalf("default App must keep apply-time region boundary: %v", err) + } + application, err := svc.ApplyToAgency(ctx, hostservice.ApplyToAgencyInput{ + CommandID: "lalu-apply-before-region-drift", + UserID: 203, + AgencyID: 301, + }) + if err != nil { + t.Fatalf("same-region application setup failed: %v", err) + } + seedActiveUser(t, repository, 203, 20) + if _, err := svc.ReviewAgencyApplication(ctx, hostservice.ReviewAgencyApplicationInput{ + CommandID: "lalu-review-after-region-drift", + ReviewerUserID: 101, + ApplicationID: application.ApplicationID, + Decision: hostdomain.ApplicationDecisionApprove, + }); xerr.CodeOf(err) != xerr.PermissionDenied { + t.Fatalf("default App must keep review-time region boundary: %v", err) + } +} + func TestAcceptAgencyInvitationCreatesOwnerHostAndPreservesExistingHostBinding(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) @@ -660,6 +707,129 @@ func TestRoleInvitationCreateRejectsCrossRegionWithRegionMismatch(t *testing.T) } } +func TestHuwaaAgencyAndBDInvitationsAllowCrossRegionAtCreateAndAccept(t *testing.T) { + ctx := appcode.WithContext(context.Background(), "huwaa") + repository := mysqltest.NewRepository(t) + for _, region := range []userdomain.Region{ + {AppCode: "huwaa", RegionID: 10, RegionCode: "R10", Name: "Region 10", Status: userdomain.RegionStatusActive}, + {AppCode: "huwaa", RegionID: 20, RegionCode: "R20", Name: "Region 20", Status: userdomain.RegionStatusActive}, + } { + repository.PutRegion(region) + } + seedActiveUserInAppAndCountry(t, repository, "huwaa", 711, 10, "US", "") + seedActiveUserInAppAndCountry(t, repository, "huwaa", 712, 20, "CA", "") + seedActiveUserInAppAndCountry(t, repository, "huwaa", 722, 20, "GB", "") + + // 先通过正式写入口建立 inviter 的 Leader + 普通 BD 双身份,后续两类邀请都使用同一套真实权限事实。 + setupSvc := newHostService(repository, 20_000, 21_000) + if _, err := setupSvc.CreateBDLeader(ctx, hostservice.CreateBDLeaderInput{ + CommandID: "huwaa-create-cross-region-inviter", + AdminUserID: 1, + TargetUserID: 711, + }); err != nil { + t.Fatalf("CreateBDLeader inviter failed: %v", err) + } + svc := newHostService(repository, 21_000, 22_000) + + agencyInvitation, err := svc.InviteAgency(ctx, hostservice.InviteAgencyInput{ + CommandID: "huwaa-invite-agency-cross-region", + InviterUserID: 711, + TargetUserID: 712, + AgencyName: "Huwaa Cross Region Agency", + }) + if err != nil { + t.Fatalf("Huwaa InviteAgency should allow cross-region target: %v", err) + } + agencyResult, err := svc.ProcessRoleInvitation(ctx, hostservice.ProcessRoleInvitationInput{ + CommandID: "huwaa-accept-agency-cross-region", + ActorUserID: 712, + InvitationID: agencyInvitation.InvitationID, + Action: hostdomain.InvitationActionAccept, + }) + if err != nil { + t.Fatalf("Huwaa agency invitation accept should allow cross-region organization link: %v", err) + } + if agencyResult.Agency.RegionID != 20 || agencyResult.Agency.ParentBDUserID != 711 { + t.Fatalf("cross-region agency must keep target region and inviter relationship: %+v", agencyResult.Agency) + } + // 产品只放开 Host 主动申请;Agency owner 主动邀请 Host 仍沿用原区域边界,避免把例外扩散到未授权流程。 + if _, err := svc.InviteHost(ctx, hostservice.InviteHostInput{ + CommandID: "huwaa-invite-host-cross-region-still-blocked", + InviterUserID: 712, + TargetUserID: 711, + }); xerr.CodeOf(err) != xerr.RegionMismatch { + t.Fatalf("Huwaa Agency-to-Host invitation must remain region-scoped: %v", err) + } + + bdInvitation, err := svc.InviteBD(ctx, hostservice.InviteBDInput{ + CommandID: "huwaa-invite-bd-cross-region", + InviterUserID: 711, + TargetUserID: 722, + }) + if err != nil { + t.Fatalf("Huwaa InviteBD should allow cross-region target: %v", err) + } + bdResult, err := svc.ProcessRoleInvitation(ctx, hostservice.ProcessRoleInvitationInput{ + CommandID: "huwaa-accept-bd-cross-region", + ActorUserID: 722, + InvitationID: bdInvitation.InvitationID, + Action: hostdomain.InvitationActionAccept, + }) + if err != nil { + t.Fatalf("Huwaa BD invitation accept should allow cross-region leader link: %v", err) + } + if bdResult.BDProfile.RegionID != 20 || bdResult.BDProfile.ParentLeaderUserID != 711 { + t.Fatalf("cross-region BD must keep target region and inviter leader: %+v", bdResult.BDProfile) + } +} + +func TestHuwaaHostApplicationSearchAndReviewAllowCrossRegion(t *testing.T) { + ctx := appcode.WithContext(context.Background(), "huwaa") + repository := mysqltest.NewRepository(t) + seedActiveUserInAppAndCountry(t, repository, "huwaa", 731, 10, "US", "") + seedActiveUserInAppAndCountry(t, repository, "huwaa", 732, 20, "CA", "") + svc := newHostService(repository, 22_000, 23_000) + + created, err := svc.CreateAgency(ctx, hostservice.CreateAgencyInput{ + CommandID: "huwaa-create-host-application-agency", + AdminUserID: 1, + OwnerUserID: 731, + Name: "Huwaa Global Agency", + JoinEnabled: true, + }) + if err != nil { + t.Fatalf("CreateAgency failed: %v", err) + } + agencies, err := svc.SearchAgencies(ctx, 732, "", 20) + if err != nil { + t.Fatalf("Huwaa SearchAgencies failed: %v", err) + } + if len(agencies) != 1 || agencies[0].AgencyID != created.Agency.AgencyID { + t.Fatalf("Huwaa host applicant must discover cross-country agency: %+v", agencies) + } + + application, err := svc.ApplyToAgency(ctx, hostservice.ApplyToAgencyInput{ + CommandID: "huwaa-apply-host-cross-region", + UserID: 732, + AgencyID: created.Agency.AgencyID, + }) + if err != nil { + t.Fatalf("Huwaa host application should allow cross-region agency: %v", err) + } + result, err := svc.ReviewAgencyApplication(ctx, hostservice.ReviewAgencyApplicationInput{ + CommandID: "huwaa-review-host-cross-region", + ReviewerUserID: 731, + ApplicationID: application.ApplicationID, + Decision: hostdomain.ApplicationDecisionApprove, + }) + if err != nil { + t.Fatalf("Huwaa host application review should preserve cross-region relationship: %v", err) + } + if result.Membership.RegionID != 20 || result.Membership.AgencyID != created.Agency.AgencyID || result.Application.Status != hostdomain.ApplicationStatusApproved { + t.Fatalf("cross-region host application facts mismatch: %+v", result) + } +} + func TestRoleInvitationAcceptRejectsRegionDriftWithRegionMismatch(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) @@ -1690,6 +1860,45 @@ func TestListActiveCoinSellersInMyRegionFiltersByCurrentUserRegion(t *testing.T) } } +func TestHuwaaCoinSellerListAndSubApplicationRemainRegionScoped(t *testing.T) { + ctx := appcode.WithContext(context.Background(), "huwaa") + repository := mysqltest.NewRepository(t) + for _, region := range []userdomain.Region{ + {AppCode: "huwaa", RegionID: 70, RegionCode: "R70", Name: "Region 70", Status: userdomain.RegionStatusActive}, + {AppCode: "huwaa", RegionID: 71, RegionCode: "R71", Name: "Region 71", Status: userdomain.RegionStatusActive}, + } { + repository.PutRegion(region) + } + seedActiveUserInAppAndCountry(t, repository, "huwaa", 940, 70, "US", "") + seedActiveUserInAppAndCountry(t, repository, "huwaa", 941, 70, "US", "") + seedActiveUserInAppAndCountry(t, repository, "huwaa", 942, 71, "CA", "") + svc := newHostService(repository, 23_000, 24_000) + for _, userID := range []int64{941, 942} { + if _, err := svc.CreateCoinSeller(ctx, hostservice.CreateCoinSellerInput{ + CommandID: fmt.Sprintf("huwaa-create-coin-seller-%d", userID), + AdminUserID: 1, + TargetUserID: userID, + }); err != nil { + t.Fatalf("CreateCoinSeller(%d) failed: %v", userID, err) + } + } + + items, err := svc.ListActiveCoinSellersInMyRegion(ctx, 940) + if err != nil { + t.Fatalf("ListActiveCoinSellersInMyRegion failed: %v", err) + } + if len(items) != 1 || items[0].UserID != 941 { + t.Fatalf("Huwaa coin-seller list must remain same-region: %+v", items) + } + if _, err := svc.SubmitSubCoinSellerApplication(ctx, hostservice.SubmitSubCoinSellerApplicationInput{ + CommandID: "huwaa-submit-cross-region-sub-seller", + ParentUserID: 941, + TargetUserID: 942, + }); xerr.CodeOf(err) != xerr.RegionMismatch { + t.Fatalf("Huwaa sub coin-seller invitation must remain region-scoped: %v", err) + } +} + func TestCreateSubCoinSellerRPCRequiresAdminReview(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) diff --git a/services/user-service/internal/service/roomtime/service.go b/services/user-service/internal/service/roomtime/service.go new file mode 100644 index 00000000..c778611a --- /dev/null +++ b/services/user-service/internal/service/roomtime/service.go @@ -0,0 +1,65 @@ +// Package roomtime runs room presence outbox consumers and exposes in-room duration compensation. +package roomtime + +import ( + "context" + "time" + + "hyapp/pkg/xerr" + roomtimedomain "hyapp/services/user-service/internal/domain/roomtime" +) + +// Repository applies room presence events and compensates abnormal open sessions. +type Repository interface { + ProcessRoomPresenceEvent(ctx context.Context, event roomtimedomain.RoomPresenceEvent) (roomtimedomain.ApplyResult, error) + CompensateOpenSessions(ctx context.Context, options roomtimedomain.CompensationOptions) (roomtimedomain.CompensationResult, error) +} + +// Service owns the user in-room duration read model. +type Service struct { + repository Repository +} + +// CompensationWorkerOptions controls abnormal open session closure. +type CompensationWorkerOptions struct { + WorkerID string + BatchSize int + OpenSessionMaxAge time.Duration +} + +// New creates a room time service with the repository that owns idempotent application. +func New(repository Repository) *Service { + return &Service{repository: repository} +} + +// ConsumeRoomPresenceEvent applies one MQ-delivered RoomUserJoined/RoomUserLeft/RoomUserKicked fact. +func (s *Service) ConsumeRoomPresenceEvent(ctx context.Context, event roomtimedomain.RoomPresenceEvent) (roomtimedomain.ApplyResult, error) { + if s == nil || s.repository == nil { + return roomtimedomain.ApplyResult{}, xerr.New(xerr.Unavailable, "room time repository is not configured") + } + switch event.EventType { + case roomtimedomain.RoomUserJoinedEventType, roomtimedomain.RoomUserLeftEventType, roomtimedomain.RoomUserKickedEventType: + default: + return roomtimedomain.ApplyResult{Skipped: true, Reason: "unsupported_event_type"}, nil + } + return s.repository.ProcessRoomPresenceEvent(ctx, event) +} + +// ProcessOpenSessionCompensationBatch exposes one bounded compensation scan for cron-service. +func (s *Service) ProcessOpenSessionCompensationBatch(ctx context.Context, options CompensationWorkerOptions) (roomtimedomain.CompensationResult, error) { + if s == nil || s.repository == nil { + return roomtimedomain.CompensationResult{}, xerr.New(xerr.Unavailable, "room time repository is not configured") + } + if options.BatchSize <= 0 { + options.BatchSize = 200 + } + if options.OpenSessionMaxAge <= 0 { + // stale worker 2 分钟内会把断线用户判离房;这里只兜 room-service 节点崩溃或 outbox 丢失的极端场景。 + options.OpenSessionMaxAge = 24 * time.Hour + } + return s.repository.CompensateOpenSessions(ctx, roomtimedomain.CompensationOptions{ + NowMs: time.Now().UnixMilli(), + BatchSize: options.BatchSize, + OpenSessionMaxAgeMs: options.OpenSessionMaxAge.Milliseconds(), + }) +} diff --git a/services/user-service/internal/service/user/admin_ban.go b/services/user-service/internal/service/user/admin_ban.go new file mode 100644 index 00000000..7c83bc32 --- /dev/null +++ b/services/user-service/internal/service/user/admin_ban.go @@ -0,0 +1,155 @@ +package user + +import ( + "context" + "strings" + + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + userdomain "hyapp/services/user-service/internal/domain/user" +) + +const ( + AdminUserBanStatusActive = "active" + AdminUserBanStatusReleased = "released" + AdminUserBanStatusExpired = "expired" + + adminUserBanReasonPrefix = "admin_user_ban:" +) + +// AdminUserBanCommand 是后台管理员永久或限时封禁命令;ExpiresAtMs=0 明确表示永久。 +type AdminUserBanCommand struct { + CommandID string + TargetUserID int64 + ExpiresAtMs int64 + OperatorAdminID int64 + Reason string + RequestID string + NowMs int64 +} + +// ReleaseAdminUserBanCommand 只释放指定 ban_id,避免一个管理员操作覆盖其他管理员的独立封禁事实。 +type ReleaseAdminUserBanCommand struct { + BanID string + TargetUserID int64 + OperatorAdminID int64 + Status string + Reason string + RequestID string + NowMs int64 +} + +// AdminUserBan 是后台管理员封禁事实;TargetOldStatus 用于审计,不作为自动恢复的唯一判断依据。 +type AdminUserBan struct { + BanID string + CommandID string + TargetUserID int64 + TargetOldStatus userdomain.Status + ExpiresAtMs int64 + Status string + Reason string + OperatorAdminID int64 + CreatedAtMs int64 + UpdatedAtMs int64 + ReleasedByAdminID int64 + ReleasedReason string + ReleasedAtMs int64 +} + +// AdminUserBanPersistenceResult 表达创建封禁和账号准入状态在同一事务提交后的事实。 +type AdminUserBanPersistenceResult struct { + Ban AdminUserBan + Status UserStatusPersistenceResult + StatusChanged bool +} + +// AdminUserBanRelease 表达一条管理员封禁释放后的用户状态;仍有其他来源时 Restored=false。 +type AdminUserBanRelease struct { + Ban AdminUserBan + User userdomain.User + Restored bool +} + +// AdminBanUser 创建永久或限时管理员封禁。 +// 已被其他管理员/经理封禁的用户允许叠加新事实,但不会重复吊销 session 或重复驱逐实时连接。 +func (s *Service) AdminBanUser(ctx context.Context, command AdminUserBanCommand) (AdminUserBan, UserStatusResult, error) { + if s.moderationRepository == nil { + return AdminUserBan{}, UserStatusResult{}, xerr.New(xerr.Unavailable, "moderation repository is not configured") + } + command.CommandID = strings.TrimSpace(command.CommandID) + command.Reason = strings.TrimSpace(command.Reason) + if command.CommandID == "" || command.TargetUserID <= 0 || command.OperatorAdminID <= 0 || command.ExpiresAtMs < 0 { + return AdminUserBan{}, UserStatusResult{}, xerr.New(xerr.InvalidArgument, "admin ban command is incomplete") + } + // 封禁期限由 user-service owner 时钟判定;调用方 sent_at_ms 仅是链路元数据,延迟或伪造值不能创建已过期事实。 + command.NowMs = s.now().UTC().UnixMilli() + if command.ExpiresAtMs > 0 && command.ExpiresAtMs <= command.NowMs { + return AdminUserBan{}, UserStatusResult{}, xerr.New(xerr.InvalidArgument, "expires_at_ms must be in the future or zero") + } + if command.Reason == "" { + command.Reason = "admin_user_ban" + } + if command.RequestID == "" { + command.RequestID = command.CommandID + } + + persisted, err := s.moderationRepository.CreateAdminUserBan(ctx, command) + if err != nil { + return AdminUserBan{}, UserStatusResult{}, err + } + statusCommand := UserStatusCommand{ + AppCode: appcode.FromContext(ctx), + TargetUserID: command.TargetUserID, + Status: userdomain.StatusBanned, + OperatorType: OperatorTypeAdmin, + OperatorUserID: command.OperatorAdminID, + Reason: adminUserBanReasonPrefix + persisted.Ban.BanID, + RequestID: command.RequestID, + NowMs: command.NowMs, + } + return persisted.Ban, s.statusResultAfterPersistence(ctx, statusCommand, persisted.Status, persisted.StatusChanged), nil +} + +// AdminUnbanUser 手动释放一条管理员封禁。 +// repository 在同一事务内重新检查其他管理员和经理封禁;没有满足恢复条件时仅释放事实,不改 users.status。 +func (s *Service) AdminUnbanUser(ctx context.Context, command ReleaseAdminUserBanCommand) (AdminUserBan, UserStatusResult, error) { + if s.moderationRepository == nil { + return AdminUserBan{}, UserStatusResult{}, xerr.New(xerr.Unavailable, "moderation repository is not configured") + } + command.BanID = strings.TrimSpace(command.BanID) + command.Reason = strings.TrimSpace(command.Reason) + if command.TargetUserID <= 0 || command.OperatorAdminID <= 0 { + return AdminUserBan{}, UserStatusResult{}, xerr.New(xerr.InvalidArgument, "admin unban command is incomplete") + } + // 解封审计和状态恢复统一使用 owner 时钟,避免跨服务时钟偏差污染事实顺序。 + command.NowMs = s.now().UTC().UnixMilli() + command.RequestID = strings.TrimSpace(command.RequestID) + if command.RequestID == "" { + return AdminUserBan{}, UserStatusResult{}, xerr.New(xerr.InvalidArgument, "admin unban request_id is required") + } + if command.Reason == "" { + command.Reason = "admin_user_unban" + } + command.Status = AdminUserBanStatusReleased + + release, err := s.moderationRepository.ReleaseAdminUserBan(ctx, command) + if err != nil { + return AdminUserBan{}, UserStatusResult{}, err + } + return release.Ban, UserStatusResult{User: release.User, AccessTokenRevoked: true}, nil +} + +// ExpireAdminUserBans 处理一批已到期的限时管理员封禁;永久封禁的 expires_at_ms=0 永远不会被 claim。 +func (s *Service) ExpireAdminUserBans(ctx context.Context, limit int32) (int, error) { + if s.moderationRepository == nil { + return 0, xerr.New(xerr.Unavailable, "moderation repository is not configured") + } + if limit <= 0 || limit > 500 { + limit = 100 + } + releases, err := s.moderationRepository.ExpireAdminUserBans(ctx, s.now().UTC().UnixMilli(), limit) + if err != nil { + return 0, err + } + return len(releases), nil +} diff --git a/services/user-service/internal/service/user/admin_profile.go b/services/user-service/internal/service/user/admin_profile.go new file mode 100644 index 00000000..5364e8e7 --- /dev/null +++ b/services/user-service/internal/service/user/admin_profile.go @@ -0,0 +1,40 @@ +package user + +import ( + "context" + + "hyapp/pkg/xerr" + userdomain "hyapp/services/user-service/internal/domain/user" +) + +const maxAdminProfileBatchSize = 500 + +// BatchGetUserAdminProfiles 一次读取后台列表所需的 user-service owner 事实。 +// 调用方必须按返回 map 的 key 处理缺失用户,不能用请求 ID 构造占位资料。 +func (s *Service) BatchGetUserAdminProfiles(ctx context.Context, userIDs []int64) (map[int64]userdomain.AdminProfile, error) { + if len(userIDs) == 0 { + return map[int64]userdomain.AdminProfile{}, nil + } + if s.userRepository == nil { + return nil, xerr.New(xerr.Unavailable, "user repository is not configured") + } + + // 去重既限制 SQL IN 参数数量,也保证同一个用户的角色与封禁事实只聚合一次。 + unique := make([]int64, 0, len(userIDs)) + seen := make(map[int64]struct{}, len(userIDs)) + for _, userID := range userIDs { + if userID <= 0 { + return nil, xerr.New(xerr.InvalidArgument, "user_ids contains invalid value") + } + if _, exists := seen[userID]; exists { + continue + } + seen[userID] = struct{}{} + unique = append(unique, userID) + } + if len(unique) > maxAdminProfileBatchSize { + return nil, xerr.New(xerr.InvalidArgument, "user_ids exceeds batch limit") + } + + return s.userRepository.BatchGetUserAdminProfiles(ctx, unique, s.now().UTC().UnixMilli()) +} diff --git a/services/user-service/internal/service/user/moderation.go b/services/user-service/internal/service/user/moderation.go index 667b4bd3..23ee917d 100644 --- a/services/user-service/internal/service/user/moderation.go +++ b/services/user-service/internal/service/user/moderation.go @@ -106,6 +106,7 @@ type ManagerUserBlock struct { // ManagerUserBlockRelease 带上是否需要恢复 users.status,避免释放记录时误放仍被其他经理封禁的用户。 type ManagerUserBlockRelease struct { Block ManagerUserBlock + User userdomain.User ShouldRestore bool } @@ -136,20 +137,26 @@ func (s *Service) SetUserStatus(ctx context.Context, command UserStatusCommand) if err != nil { return UserStatusResult{}, err } + return s.statusResultAfterPersistence(ctx, command, persisted, true), nil +} + +// statusResultAfterPersistence 统一把已经提交的用户状态事实转换为外部副作用结果。 +// runBanSideEffects=false 用于“用户原本已 banned、只新增重叠封禁事实”的场景,避免重复踢 IM/房间。 +func (s *Service) statusResultAfterPersistence(ctx context.Context, command UserStatusCommand, persisted UserStatusPersistenceResult, runBanSideEffects bool) UserStatusResult { result := UserStatusResult{ User: persisted.User, RevokedSessionCount: int64(len(persisted.RevokedSessionIDs)), AccessTokenRevoked: true, } - if command.Status == userdomain.StatusActive { + if command.Status == userdomain.StatusActive || !runBanSideEffects { // 恢复 active 只改变准入状态,不重建旧 session、IM 登录或房间 presence。 - return result, nil + return result } result.AccessTokenRevoked, result.AccessTokenError = s.writeSessionDenylist(ctx, command, persisted.RevokedSessionIDs, userStatusRevokeReason) result.IMKicked, result.IMKickError = s.kickIMLogin(ctx, command.TargetUserID) result.RoomEvicted, result.RoomID, result.RTCKicked, result.RTCKickError, result.RoomEvictError = s.evictCurrentRoom(ctx, command) - return result, nil + return result } // CreateManagerUserBlock 创建经理封禁记录并把目标用户状态置为 banned。 @@ -225,7 +232,7 @@ func (s *Service) ListManagerUserBlocks(ctx context.Context, managerUserID int64 func (s *Service) UnblockManagerUser(ctx context.Context, command ReleaseManagerUserBlockCommand) (ManagerUserBlock, UserStatusResult, error) { command.Status = ManagerUserBlockStatusReleased - return s.releaseManagerUserBlock(ctx, command, OperatorTypeAppUser) + return s.releaseManagerUserBlock(ctx, command) } func (s *Service) ExpireManagerUserBlocks(ctx context.Context, limit int32) (int, error) { @@ -240,28 +247,12 @@ func (s *Service) ExpireManagerUserBlocks(ctx context.Context, limit int32) (int if err != nil { return 0, err } - for _, release := range releases { - if !release.ShouldRestore { - // 释放封禁记录不等于一定恢复用户;仍有其他经理封禁或最后一次 ban 不是经理封禁时必须保持 banned。 - continue - } - if _, err := s.SetUserStatus(ctx, UserStatusCommand{ - AppCode: appcode.FromContext(ctx), - TargetUserID: release.Block.TargetUserID, - Status: userdomain.StatusActive, - OperatorType: OperatorTypeSystem, - OperatorUserID: 0, - Reason: "manager_center_block_expired:" + release.Block.BlockID, - RequestID: "manager_block_expire:" + release.Block.BlockID, - NowMs: nowMS, - }); err != nil { - return len(releases), err - } - } + // repository 已在每条释放事务内同时检查 admin/manager 两类 active 事实并按需恢复 users.status; + // service 不再二次 SetUserStatus,避免检查与写入之间插入新的封禁事实。 return len(releases), nil } -func (s *Service) releaseManagerUserBlock(ctx context.Context, command ReleaseManagerUserBlockCommand, operatorType string) (ManagerUserBlock, UserStatusResult, error) { +func (s *Service) releaseManagerUserBlock(ctx context.Context, command ReleaseManagerUserBlockCommand) (ManagerUserBlock, UserStatusResult, error) { if s.moderationRepository == nil { return ManagerUserBlock{}, UserStatusResult{}, xerr.New(xerr.Unavailable, "moderation repository is not configured") } @@ -282,22 +273,9 @@ func (s *Service) releaseManagerUserBlock(ctx context.Context, command ReleaseMa } if !release.ShouldRestore { // repository 已判断能否安全恢复;这里不能盲目 SetUserStatus(active),否则会覆盖后台封禁或并发经理封禁。 - return release.Block, UserStatusResult{}, nil + return release.Block, UserStatusResult{User: release.User, AccessTokenRevoked: true}, nil } - status, err := s.SetUserStatus(ctx, UserStatusCommand{ - AppCode: appcode.FromContext(ctx), - TargetUserID: release.Block.TargetUserID, - Status: userdomain.StatusActive, - OperatorType: operatorType, - OperatorUserID: command.ManagerUserID, - Reason: "manager_center_unblock:" + release.Block.BlockID, - RequestID: command.RequestID, - NowMs: command.NowMS, - }) - if err != nil { - return ManagerUserBlock{}, UserStatusResult{}, err - } - return release.Block, status, nil + return release.Block, UserStatusResult{User: release.User, AccessTokenRevoked: true}, nil } func (s *Service) writeSessionDenylist(ctx context.Context, command UserStatusCommand, sessionIDs []string, reason string) (bool, string) { diff --git a/services/user-service/internal/service/user/moderation_test.go b/services/user-service/internal/service/user/moderation_test.go index b2f6d540..7847681b 100644 --- a/services/user-service/internal/service/user/moderation_test.go +++ b/services/user-service/internal/service/user/moderation_test.go @@ -8,6 +8,7 @@ import ( roomv1 "hyapp.local/api/proto/room/v1" "hyapp/pkg/appcode" + "hyapp/pkg/xerr" invitedomain "hyapp/services/user-service/internal/domain/invite" userdomain "hyapp/services/user-service/internal/domain/user" ) @@ -102,12 +103,141 @@ func TestSetUserStatusSurfacesAccessDenylistError(t *testing.T) { } } +func TestAdminBanUserAcceptsPermanentBanAndRunsRealtimeSideEffectsOnce(t *testing.T) { + repository := &fakeModerationRepository{ + user: userdomain.User{AppCode: "lalu", UserID: 10001, Status: userdomain.StatusBanned}, + sessionIDs: []string{"sess_admin"}, + } + denylist := &fakeSessionDenylist{} + im := &fakeIMLoginKicker{} + room := &fakeRoomEvictor{resp: &roomv1.SystemEvictUserResponse{Result: &roomv1.CommandResult{Applied: true}}} + svc := New(repository, + WithModerationRepository(repository), + WithSessionDenylist(denylist, time.Minute), + WithIMLoginKicker(im), + WithRoomEvictor(room), + WithClock(func() time.Time { return time.UnixMilli(1_700_000_000_000).UTC() }), + ) + + ban, result, err := svc.AdminBanUser(appcode.WithContext(context.Background(), "lalu"), AdminUserBanCommand{ + CommandID: "admin-ban-command", + TargetUserID: 10001, + ExpiresAtMs: 0, + OperatorAdminID: 9001, + RequestID: "req-admin-ban", + NowMs: 1, + }) + if err != nil { + t.Fatalf("AdminBanUser failed: %v", err) + } + if ban.ExpiresAtMs != 0 || ban.Status != AdminUserBanStatusActive { + t.Fatalf("permanent admin ban mismatch: %+v", ban) + } + if len(denylist.sessions) != 1 || denylist.sessions[0] != "sess_admin" || im.userID != 10001 || room.req.GetTargetUserId() != 10001 { + t.Fatalf("admin ban side effects mismatch: denylist=%+v im=%d room=%+v", denylist.sessions, im.userID, room.req) + } + if !result.AccessTokenRevoked || result.RevokedSessionCount != 1 { + t.Fatalf("admin ban status result mismatch: %+v", result) + } + if repository.lastAdminBanCommand.NowMs != 1_700_000_000_000 { + t.Fatalf("user-service owner clock must override caller sent_at_ms: %+v", repository.lastAdminBanCommand) + } +} + +func TestAdminUnbanUserUsesOwnerClock(t *testing.T) { + repository := &fakeModerationRepository{adminBanRelease: AdminUserBanRelease{ + Ban: AdminUserBan{BanID: "ban-1", TargetUserID: 10001, Status: AdminUserBanStatusReleased}, + User: userdomain.User{AppCode: "lalu", UserID: 10001, Status: userdomain.StatusActive}, + }} + svc := New(repository, + WithModerationRepository(repository), + WithClock(func() time.Time { return time.UnixMilli(1_700_000_000_000).UTC() }), + ) + _, _, err := svc.AdminUnbanUser(context.Background(), ReleaseAdminUserBanCommand{ + BanID: "ban-1", TargetUserID: 10001, OperatorAdminID: 9001, + Reason: "manual", RequestID: "unban-owner-clock", NowMs: 1, + }) + if err != nil { + t.Fatalf("AdminUnbanUser failed: %v", err) + } + if repository.lastAdminBanReleaseCommand.NowMs != 1_700_000_000_000 { + t.Fatalf("unban must use user-service owner clock: %+v", repository.lastAdminBanReleaseCommand) + } +} + +func TestAdminBanUserDoesNotRepeatSideEffectsForOverlappingBan(t *testing.T) { + repository := &fakeModerationRepository{ + user: userdomain.User{AppCode: "lalu", UserID: 10001, Status: userdomain.StatusBanned}, + adminBanPersistence: AdminUserBanPersistenceResult{ + Ban: AdminUserBan{BanID: "admin-ban-2", TargetUserID: 10001, Status: AdminUserBanStatusActive}, + Status: UserStatusPersistenceResult{User: userdomain.User{AppCode: "lalu", UserID: 10001, Status: userdomain.StatusBanned}}, + StatusChanged: false, + }, + } + im := &fakeIMLoginKicker{} + room := &fakeRoomEvictor{} + svc := New(repository, WithModerationRepository(repository), WithIMLoginKicker(im), WithRoomEvictor(room)) + + _, result, err := svc.AdminBanUser(appcode.WithContext(context.Background(), "lalu"), AdminUserBanCommand{ + CommandID: "overlap", + TargetUserID: 10001, + OperatorAdminID: 9002, + }) + if err != nil { + t.Fatalf("AdminBanUser overlap failed: %v", err) + } + if im.userID != 0 || room.req != nil { + t.Fatalf("overlapping ban must not repeat realtime side effects: im=%d room=%+v", im.userID, room.req) + } + if result.User.Status != userdomain.StatusBanned { + t.Fatalf("overlapping ban must preserve banned projection: %+v", result) + } +} + +func TestAdminBanUserRejectsExpiredDeadline(t *testing.T) { + repository := &fakeModerationRepository{} + svc := New(repository, WithModerationRepository(repository), WithClock(func() time.Time { + return time.UnixMilli(1_700_000_000_000).UTC() + })) + + _, _, err := svc.AdminBanUser(context.Background(), AdminUserBanCommand{ + CommandID: "expired", + TargetUserID: 10001, + OperatorAdminID: 9001, + ExpiresAtMs: 1_700_000_000_000, + }) + if xerr.CodeOf(err) != xerr.InvalidArgument { + t.Fatalf("expired deadline must be rejected, err=%v", err) + } +} + +func TestBatchGetUserAdminProfilesDeduplicatesAndLimitsInput(t *testing.T) { + repository := &fakeModerationRepository{adminProfiles: map[int64]userdomain.AdminProfile{ + 10001: {User: userdomain.User{UserID: 10001}}, + }} + svc := New(repository) + + profiles, err := svc.BatchGetUserAdminProfiles(context.Background(), []int64{10001, 10001}) + if err != nil || profiles[10001].User.UserID != 10001 { + t.Fatalf("batch admin profile failed: profiles=%+v err=%v", profiles, err) + } + tooMany := make([]int64, maxAdminProfileBatchSize+1) + for index := range tooMany { + tooMany[index] = int64(index + 1) + } + if _, err := svc.BatchGetUserAdminProfiles(context.Background(), tooMany); xerr.CodeOf(err) != xerr.InvalidArgument { + t.Fatalf("oversized admin profile batch must be rejected, err=%v", err) + } +} + type fakeModerationRepository struct { user userdomain.User inviteReferrer userdomain.User sessionIDs []string countrySessionIDs []string lastCommand UserStatusCommand + lastAdminBanCommand AdminUserBanCommand + lastAdminBanReleaseCommand ReleaseAdminUserBanCommand lastProfileCommand userdomain.ProfileUpdateCommand lastWithdrawAddressCommand userdomain.WithdrawAddressUpdateCommand lastCountryCommand userdomain.CountryChangeCommand @@ -116,6 +246,10 @@ type fakeModerationRepository struct { lastBindInvite userdomain.BindInviteReferrerCommand countryChangeCalls int lastReport userdomain.Report + adminProfiles map[int64]userdomain.AdminProfile + adminBanPersistence AdminUserBanPersistenceResult + adminBanRelease AdminUserBanRelease + adminBanExpirations []AdminUserBanRelease } func (r *fakeModerationRepository) SetUserStatus(_ context.Context, command UserStatusCommand) (UserStatusPersistenceResult, error) { @@ -155,6 +289,34 @@ func (r *fakeModerationRepository) ExpireManagerUserBlocks(context.Context, int6 return nil, nil } +func (r *fakeModerationRepository) CreateAdminUserBan(_ context.Context, command AdminUserBanCommand) (AdminUserBanPersistenceResult, error) { + r.lastAdminBanCommand = command + if r.adminBanPersistence.Ban.BanID == "" { + r.adminBanPersistence = AdminUserBanPersistenceResult{ + Ban: AdminUserBan{ + BanID: "admin-ban-1", + CommandID: command.CommandID, + TargetUserID: command.TargetUserID, + ExpiresAtMs: command.ExpiresAtMs, + Status: AdminUserBanStatusActive, + OperatorAdminID: command.OperatorAdminID, + }, + Status: UserStatusPersistenceResult{User: r.user, RevokedSessionIDs: append([]string{}, r.sessionIDs...)}, + StatusChanged: true, + } + } + return r.adminBanPersistence, nil +} + +func (r *fakeModerationRepository) ReleaseAdminUserBan(_ context.Context, command ReleaseAdminUserBanCommand) (AdminUserBanRelease, error) { + r.lastAdminBanReleaseCommand = command + return r.adminBanRelease, nil +} + +func (r *fakeModerationRepository) ExpireAdminUserBans(context.Context, int64, int32) ([]AdminUserBanRelease, error) { + return r.adminBanExpirations, nil +} + func (r *fakeModerationRepository) GetUser(context.Context, int64) (userdomain.User, error) { return r.user, nil } @@ -216,6 +378,13 @@ func (r *fakeModerationRepository) BatchGetUsers(context.Context, []int64) (map[ return nil, nil } +func (r *fakeModerationRepository) BatchGetUserAdminProfiles(context.Context, []int64, int64) (map[int64]userdomain.AdminProfile, error) { + if r.adminProfiles == nil { + return map[int64]userdomain.AdminProfile{}, nil + } + return r.adminProfiles, nil +} + func (r *fakeModerationRepository) BatchGetRoomBasicUsers(context.Context, []int64) (map[int64]userdomain.RoomBasicUser, error) { return nil, nil } diff --git a/services/user-service/internal/service/user/service.go b/services/user-service/internal/service/user/service.go index 9b5a70ca..1f220e08 100644 --- a/services/user-service/internal/service/user/service.go +++ b/services/user-service/internal/service/user/service.go @@ -45,6 +45,8 @@ type UserRepository interface { BusinessUserLookup(ctx context.Context, keyword string, numericKeyword bool, pageSize int32) ([]userdomain.BusinessUserLookupItem, error) // BatchGetUsers 批量查询用户主状态,缺失用户不应返回占位对象。 BatchGetUsers(ctx context.Context, userIDs []int64) (map[int64]userdomain.User, error) + // BatchGetUserAdminProfiles 批量读取后台列表需要的用户、身份、登录和封禁 owner 事实。 + BatchGetUserAdminProfiles(ctx context.Context, userIDs []int64, nowMs int64) (map[int64]userdomain.AdminProfile, error) // BatchGetRoomBasicUsers 批量查询房间首屏最小用户资料,不触发完整用户主状态投影。 BatchGetRoomBasicUsers(ctx context.Context, userIDs []int64) (map[int64]userdomain.RoomBasicUser, error) // GetInviteAttribution 按被邀请用户读取邀请归因快照;无关系时返回 Found=false。 @@ -170,6 +172,9 @@ type ModerationRepository interface { ListManagerUserBlocks(ctx context.Context, managerUserID int64, status string, pageSize int32) ([]ManagerUserBlock, error) ReleaseManagerUserBlock(ctx context.Context, command ReleaseManagerUserBlockCommand) (ManagerUserBlockRelease, error) ExpireManagerUserBlocks(ctx context.Context, nowMS int64, limit int32) ([]ManagerUserBlockRelease, error) + CreateAdminUserBan(ctx context.Context, command AdminUserBanCommand) (AdminUserBanPersistenceResult, error) + ReleaseAdminUserBan(ctx context.Context, command ReleaseAdminUserBanCommand) (AdminUserBanRelease, error) + ExpireAdminUserBans(ctx context.Context, nowMS int64, limit int32) ([]AdminUserBanRelease, error) } // SessionDenylist 写入 gateway access token 快速拒绝缓存。 diff --git a/services/user-service/internal/storage/mysql/host/applications.go b/services/user-service/internal/storage/mysql/host/applications.go index 44303066..f21118aa 100644 --- a/services/user-service/internal/storage/mysql/host/applications.go +++ b/services/user-service/internal/storage/mysql/host/applications.go @@ -28,7 +28,7 @@ func (r *Repository) ApplyToAgency(ctx context.Context, command hostservice.Appl } // 申请人此时可能还没有 host_profiles 行,因此以 users 行作为“按用户串行化”的主锁。 - // 区域也从用户表读取,保证申请创建时的区域是 user-service 的当前事实。 + // 区域从用户表读取,作为后续 Host/成员关系的当前投影;Huwaa 允许它与 Agency owner 区域不同,但不会迁移申请人区域。 userRegionID, err := r.userRegion(ctx, tx, command.UserID, "FOR UPDATE") if err != nil { return hostdomain.AgencyApplication{}, err @@ -46,7 +46,7 @@ func (r *Repository) ApplyToAgency(ctx context.Context, command hostservice.Appl if agency.Status != hostdomain.AgencyStatusActive || !agency.JoinEnabled { return hostdomain.AgencyApplication{}, xerr.New(xerr.Conflict, "agency is not joinable") } - if agency.RegionID != userRegionID { + if roleRegionMatchRequired(ctx) && agency.RegionID != userRegionID { return hostdomain.AgencyApplication{}, xerr.New(xerr.PermissionDenied, "agency region does not match user region") } // 第一阶段规则是一个 Host 同时只能归属一个有效 Agency; @@ -129,13 +129,13 @@ func (r *Repository) ReviewAgencyApplication(ctx context.Context, command hostse return hostdomain.ReviewAgencyApplicationResult{}, xerr.New(xerr.Conflict, "agency is not active") } - // 申请创建后申请人或 Agency 拥有者区域都可能被后台调整;通过前重新锁申请人 users 行, - // 并用 Agency 当前拥有者区域校验,申请表不再保存区域快照。 + // 申请创建后申请人或 Agency 拥有者区域都可能被后台调整;通过前重新锁申请人 users 行。 + // 其他 App 继续按 Agency 当前拥有者区域复验,Huwaa 只跳过匹配,不在申请表恢复区域快照或修改 users。 regionID, err := r.userRegion(ctx, tx, application.ApplicantUserID, "FOR UPDATE") if err != nil { return hostdomain.ReviewAgencyApplicationResult{}, err } - if regionID != agency.RegionID { + if roleRegionMatchRequired(ctx) && regionID != agency.RegionID { return hostdomain.ReviewAgencyApplicationResult{}, xerr.New(xerr.PermissionDenied, "application region no longer matches") } diff --git a/services/user-service/internal/storage/mysql/host/invitations.go b/services/user-service/internal/storage/mysql/host/invitations.go index 2dfe5be4..73a26ad1 100644 --- a/services/user-service/internal/storage/mysql/host/invitations.go +++ b/services/user-service/internal/storage/mysql/host/invitations.go @@ -14,7 +14,7 @@ import ( const userOutboxEventRoleInvitationCreated = "RoleInvitationCreated" -// InviteAgency 创建 Agency 角色邀请,校验 inviter BD 身份和目标用户区域。 +// InviteAgency 创建 Agency 角色邀请;除 Huwaa 外校验 inviter BD 和目标用户区域一致。 func (r *Repository) InviteAgency(ctx context.Context, command hostservice.InviteAgencyCommand) (hostdomain.RoleInvitation, error) { tx, err := r.db.BeginTx(ctx, nil) if err != nil { @@ -44,7 +44,7 @@ func (r *Repository) InviteAgency(ctx context.Context, command hostservice.Invit if err != nil { return hostdomain.RoleInvitation{}, err } - if targetRegionID != inviter.RegionID { + if roleRegionMatchRequired(ctx) && targetRegionID != inviter.RegionID { return hostdomain.RoleInvitation{}, xerr.New(xerr.RegionMismatch, "target region does not match inviter region") } // Agency owner 和 Host 成员归属是两套身份;目标已有 active Host 绑定时仍允许成为 Agency owner, @@ -125,12 +125,12 @@ func (r *Repository) InviteBD(ctx context.Context, command hostservice.InviteBDC if inviter.Status != hostdomain.BDStatusActive { return hostdomain.RoleInvitation{}, xerr.New(xerr.PermissionDenied, "inviter is not active bd leader") } - // BD 从属于负责人的区域,邀请创建时先锁目标用户当前区域。 + // 邀请创建时锁目标用户当前区域;其他 App 要求和 Leader 同区,Huwaa 允许跨区但 BD 投影仍来自目标 users 当前区域。 targetRegionID, err := r.userRegion(ctx, tx, command.TargetUserID, "FOR UPDATE") if err != nil { return hostdomain.RoleInvitation{}, err } - if targetRegionID != inviter.RegionID { + if roleRegionMatchRequired(ctx) && targetRegionID != inviter.RegionID { return hostdomain.RoleInvitation{}, xerr.New(xerr.RegionMismatch, "target region does not match leader region") } // 只有 active 普通 BD 才算已有权限;disabled 行可以重新发邀请, @@ -484,8 +484,8 @@ func (r *Repository) ProcessRoleInvitation(ctx context.Context, command hostserv } func (r *Repository) acceptAgencyInvitation(ctx context.Context, tx *sql.Tx, command hostservice.ProcessRoleInvitationCommand, invitation *hostdomain.RoleInvitation, result *hostdomain.ProcessRoleInvitationResult) (bool, bool, error) { - // 邀请可能放置一段时间后才被接受,所以目标用户和邀请 BD 都用 users 当前区域重新对齐。 - // 邀请表不再保存区域快照,旧库残留的 region_id 也不能参与是否可接受的业务判断。 + // 邀请可能放置一段时间后才被接受,所以目标用户和邀请 BD 都读取 users 当前区域。 + // 其他 App 用它们重新对齐;Huwaa 允许跨区,且邀请表仍不保存区域快照、不迁移目标用户。 targetRegionID, err := r.userRegion(ctx, tx, invitation.TargetUserID, "FOR UPDATE") if err != nil { return false, false, err @@ -494,7 +494,7 @@ func (r *Repository) acceptAgencyInvitation(ctx context.Context, tx *sql.Tx, com if err != nil { return false, false, err } - if targetRegionID != inviterRegionID { + if roleRegionMatchRequired(ctx) && targetRegionID != inviterRegionID { return false, false, xerr.New(xerr.RegionMismatch, "target region no longer matches invitation") } // 目标已有 Host 绑定时保留绑定,不再把 Host 当前归属切到自己新建的 Agency。 @@ -624,7 +624,7 @@ func (r *Repository) acceptHostInvitation(ctx context.Context, tx *sql.Tx, comma } func (r *Repository) acceptBDInvitation(ctx context.Context, tx *sql.Tx, command hostservice.ProcessRoleInvitationCommand, invitation *hostdomain.RoleInvitation, result *hostdomain.ProcessRoleInvitationResult) error { - // BD 邀请同样以目标用户和发起 Leader 的 users 当前区域为准;旧邀请快照不能继续授权跨区接受。 + // BD 邀请同样读取目标用户和发起 Leader 的 users 当前区域;其他 App 阻止漂移/跨区,Huwaa 只取消匹配校验。 targetRegionID, err := r.userRegion(ctx, tx, invitation.TargetUserID, "FOR UPDATE") if err != nil { return err @@ -633,7 +633,7 @@ func (r *Repository) acceptBDInvitation(ctx context.Context, tx *sql.Tx, command if err != nil { return err } - if targetRegionID != leaderRegionID { + if roleRegionMatchRequired(ctx) && targetRegionID != leaderRegionID { return xerr.New(xerr.RegionMismatch, "target region no longer matches invitation") } // BD 身份是独立角色事实,不依赖 host_profile;active BD 不能被覆盖, diff --git a/services/user-service/internal/storage/mysql/host/queries.go b/services/user-service/internal/storage/mysql/host/queries.go index 597282f6..86d7a422 100644 --- a/services/user-service/internal/storage/mysql/host/queries.go +++ b/services/user-service/internal/storage/mysql/host/queries.go @@ -13,13 +13,13 @@ import ( hostservice "hyapp/services/user-service/internal/service/host" ) -// SearchAgencies 返回用户当前国家内可加入的有效 Agency。 +// SearchAgencies 返回当前 App 内可加入的有效 Agency;除 Huwaa 外继续按用户当前国家收敛候选集。 func (r *Repository) SearchAgencies(ctx context.Context, command hostservice.SearchAgenciesCommand) ([]hostdomain.Agency, error) { country, err := r.userCountry(ctx, r.db, command.UserID, "") if err != nil { return nil, err } - if country == "" { + if roleRegionMatchRequired(ctx) && country == "" { // 国家是 App 推荐列表的硬边界,缺失时不能退化成跨国或全局列表。 return nil, xerr.New(xerr.InvalidArgument, "user country is required") } @@ -47,12 +47,16 @@ func (r *Repository) SearchAgencies(ctx context.Context, command hostservice.Sea AND active_member.agency_id = a.agency_id AND active_member.status = ? WHERE a.app_code = ? - AND owner.country = ? AND owner.status = 'active' AND a.status = ? AND a.join_enabled = TRUE ` - args := []any{hostdomain.MembershipStatusActive, appcode.FromContext(ctx), country, hostdomain.AgencyStatusActive} + args := []any{hostdomain.MembershipStatusActive, appcode.FromContext(ctx), hostdomain.AgencyStatusActive} + if roleRegionMatchRequired(ctx) { + // 其他 App 保留历史国家边界;条件由服务端用户资料派生,客户端不能伪造国家扩大结果集。 + query += ` AND owner.country = ?` + args = append(args, country) + } if strings.TrimSpace(command.Keyword) != "" { keyword := strings.TrimSpace(command.Keyword) query += ` AND (a.name LIKE ? OR a.agency_id = ? OR owner.current_display_user_id = ?)` diff --git a/services/user-service/internal/storage/mysql/host/region_policy.go b/services/user-service/internal/storage/mysql/host/region_policy.go new file mode 100644 index 00000000..b3a0bd1a --- /dev/null +++ b/services/user-service/internal/storage/mysql/host/region_policy.go @@ -0,0 +1,15 @@ +package host + +import ( + "context" + + "hyapp/pkg/appcode" +) + +const huwaaAppCode = "huwaa" + +// roleRegionMatchRequired 只控制 Agency 角色邀请、Host 主动申请和 BD 邀请的区域匹配。 +// Huwaa 的这些组织拓展允许跨区域,但角色事实仍归属目标用户当前区域;Agency 主动邀请 Host、币商列表和子币商关系不得复用该例外。 +func roleRegionMatchRequired(ctx context.Context) bool { + return appcode.FromContext(ctx) != huwaaAppCode +} diff --git a/services/user-service/internal/storage/mysql/host/region_policy_test.go b/services/user-service/internal/storage/mysql/host/region_policy_test.go new file mode 100644 index 00000000..f1ea8c96 --- /dev/null +++ b/services/user-service/internal/storage/mysql/host/region_policy_test.go @@ -0,0 +1,28 @@ +package host + +import ( + "context" + "testing" + + "hyapp/pkg/appcode" +) + +func TestRoleRegionMatchRequiredOnlyExemptsNormalizedHuwaa(t *testing.T) { + for _, testCase := range []struct { + name string + app string + required bool + }{ + {name: "default_lalu", app: "", required: true}, + {name: "explicit_lalu", app: "lalu", required: true}, + {name: "fami", app: "fami", required: true}, + {name: "normalized_huwaa", app: " HUWAa ", required: false}, + } { + t.Run(testCase.name, func(t *testing.T) { + ctx := appcode.WithContext(context.Background(), testCase.app) + if got := roleRegionMatchRequired(ctx); got != testCase.required { + t.Fatalf("roleRegionMatchRequired(%q) = %v, want %v", testCase.app, got, testCase.required) + } + }) + } +} diff --git a/services/user-service/internal/storage/mysql/identity/pretty_test.go b/services/user-service/internal/storage/mysql/identity/pretty_test.go index 2e8c35ca..67c4ab94 100644 --- a/services/user-service/internal/storage/mysql/identity/pretty_test.go +++ b/services/user-service/internal/storage/mysql/identity/pretty_test.go @@ -80,7 +80,7 @@ func TestGeneratePrettyDisplayIDCandidatesWithConfig(t *testing.T) { if err != nil { t.Fatalf("generate custom candidates failed: %v", err) } - if strings.Join(custom, ",") != "VIP2026,ملك123" { + if strings.Join(custom, ",") != "VIP2026,ملك123,VIP!" { t.Fatalf("custom candidates = %#v", custom) } } diff --git a/services/user-service/internal/storage/mysql/repositories.go b/services/user-service/internal/storage/mysql/repositories.go index 4a68b9e8..d8c20ccb 100644 --- a/services/user-service/internal/storage/mysql/repositories.go +++ b/services/user-service/internal/storage/mysql/repositories.go @@ -10,6 +10,7 @@ import ( invitestorage "hyapp/services/user-service/internal/storage/mysql/invite" mictimestorage "hyapp/services/user-service/internal/storage/mysql/mictime" regionstorage "hyapp/services/user-service/internal/storage/mysql/region" + roomtimestorage "hyapp/services/user-service/internal/storage/mysql/roomtime" userstorage "hyapp/services/user-service/internal/storage/mysql/user" ) @@ -85,6 +86,14 @@ func (r *Repository) MicTimeRepository() *mictimestorage.Repository { return mictimestorage.New(r.db) } +// 基于 user-service 共享 MySQL 连接池返回用户在房时长存储对象。 +func (r *Repository) RoomTimeRepository() *roomtimestorage.Repository { + if r == nil { + return nil + } + return roomtimestorage.New(r.db) +} + // 基于 user-service 共享 MySQL 连接池返回 CP/兄弟/姐妹关系存储对象。 func (r *Repository) CPRepository() *cpstorage.Repository { if r == nil { diff --git a/services/user-service/internal/storage/mysql/roomtime/repository.go b/services/user-service/internal/storage/mysql/roomtime/repository.go new file mode 100644 index 00000000..3bfb27bb --- /dev/null +++ b/services/user-service/internal/storage/mysql/roomtime/repository.go @@ -0,0 +1,543 @@ +// Package roomtime stores user-scoped in-room duration read models in MySQL. +package roomtime + +import ( + "context" + "database/sql" + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + mysqldriver "github.com/go-sql-driver/mysql" + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + roomtimedomain "hyapp/services/user-service/internal/domain/roomtime" +) + +// Repository owns in-room session state and user duration aggregates inside user-service MySQL. +type Repository struct { + db *sql.DB +} + +const ( + defaultCompensationBatchSize = 200 + defaultOpenSessionCompensationMs = int64(24 * 60 * 60 * 1000) + userOutboxStatusPending = "pending" +) + +// New creates an in-room duration repository backed by the shared user-service connection pool. +func New(db *sql.DB) *Repository { + return &Repository{db: db} +} + +// ProcessRoomPresenceEvent idempotently applies one RoomUserJoined/RoomUserLeft/RoomUserKicked fact. +func (r *Repository) ProcessRoomPresenceEvent(ctx context.Context, event roomtimedomain.RoomPresenceEvent) (roomtimedomain.ApplyResult, error) { + if r == nil || r.db == nil { + return roomtimedomain.ApplyResult{}, xerr.New(xerr.Unavailable, "room time repository is not configured") + } + event = normalizeRoomPresenceEvent(event) + if event.EventID == "" || event.EventType == "" { + return roomtimedomain.ApplyResult{}, xerr.New(xerr.InvalidArgument, "room presence event identity is required") + } + if event.OccurredAtMs <= 0 { + event.OccurredAtMs = time.Now().UnixMilli() + } + + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return roomtimedomain.ApplyResult{}, err + } + defer tx.Rollback() + + if err := insertEventConsumption(ctx, tx, event); err != nil { + if isDuplicate(err) { + return roomtimedomain.ApplyResult{Skipped: true, Reason: "already_consumed"}, nil + } + return roomtimedomain.ApplyResult{}, err + } + + var result roomtimedomain.ApplyResult + switch { + case event.RoomID == "" || event.UserID <= 0: + result = roomtimedomain.ApplyResult{Skipped: true, Reason: "incomplete_presence_event"} + case event.EventType == roomtimedomain.RoomUserJoinedEventType: + result, err = applyJoined(ctx, tx, event) + case event.EventType == roomtimedomain.RoomUserLeftEventType: + result, err = applyLeft(ctx, tx, event, roomtimedomain.EndReasonLeft) + case event.EventType == roomtimedomain.RoomUserKickedEventType: + result, err = applyLeft(ctx, tx, event, roomtimedomain.EndReasonKicked) + default: + result = roomtimedomain.ApplyResult{Skipped: true, Reason: "unsupported_presence_event"} + } + if err != nil { + return roomtimedomain.ApplyResult{}, err + } + if result.Reason == "" && result.Skipped { + result.Reason = "skipped" + } + status := "consumed" + if result.Skipped { + status = "skipped" + } + if err := finishEventConsumption(ctx, tx, event, status, result.Reason); err != nil { + return roomtimedomain.ApplyResult{}, err + } + if err := tx.Commit(); err != nil { + return roomtimedomain.ApplyResult{}, err + } + if !result.Skipped { + result.Consumed = true + } + return result, nil +} + +// CompensateOpenSessions closes abnormal sessions whose authoritative leave event never reached user-service. +func (r *Repository) CompensateOpenSessions(ctx context.Context, options roomtimedomain.CompensationOptions) (roomtimedomain.CompensationResult, error) { + if r == nil || r.db == nil { + return roomtimedomain.CompensationResult{}, xerr.New(xerr.Unavailable, "room time repository is not configured") + } + options = normalizeCompensationOptions(options) + + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return roomtimedomain.CompensationResult{}, err + } + defer tx.Rollback() + + cutoff := options.NowMs - options.OpenSessionMaxAgeMs + app := appcode.FromContext(ctx) + rows, err := tx.QueryContext(ctx, ` + SELECT app_code, room_session_id, user_id, room_id, status, is_robot, joined_at_ms, last_room_version + FROM user_room_sessions + WHERE app_code = ? AND status = ? AND joined_at_ms <= ? + ORDER BY joined_at_ms ASC, room_session_id ASC + LIMIT ? + FOR UPDATE SKIP LOCKED + `, app, roomtimedomain.SessionStatusOpen, cutoff, options.BatchSize) + if err != nil { + return roomtimedomain.CompensationResult{}, err + } + + candidates := make([]roomSessionRow, 0, options.BatchSize) + for rows.Next() { + var session roomSessionRow + if err := rows.Scan(&session.AppCode, &session.RoomSessionID, &session.UserID, &session.RoomID, &session.Status, &session.IsRobot, &session.JoinedAtMs, &session.LastRoomVersion); err != nil { + _ = rows.Close() + return roomtimedomain.CompensationResult{}, err + } + candidates = append(candidates, session) + } + if err := rows.Close(); err != nil { + return roomtimedomain.CompensationResult{}, err + } + if err := rows.Err(); err != nil { + return roomtimedomain.CompensationResult{}, err + } + + var result roomtimedomain.CompensationResult + for _, session := range candidates { + if err := closeRoomSession(ctx, tx, session, closeRoomSessionInput{ + ClosedEventID: fmt.Sprintf("compensated:%s", session.RoomSessionID), + EndAtMs: minInt64(options.NowMs, session.JoinedAtMs+options.OpenSessionMaxAgeMs), + EndReason: roomtimedomain.CompensationReasonOpenSessionMaxWindow, + UpdatedAtMs: options.NowMs, + RoomVersion: session.LastRoomVersion, + }); err != nil { + return roomtimedomain.CompensationResult{}, err + } + result.ClosedCount++ + } + + // 孤儿 Left 只用于修正乱序到达;超过补偿窗口后已不可能再匹配任何进房事实,按批清理。 + deleted, err := tx.ExecContext(ctx, ` + DELETE FROM user_room_orphan_leaves + WHERE app_code = ? AND left_at_ms <= ? + LIMIT ? + `, app, cutoff, options.BatchSize) + if err != nil { + return roomtimedomain.CompensationResult{}, err + } + if affected, err := deleted.RowsAffected(); err == nil { + result.OrphanLeavesDeleted = int(affected) + } + + if err := tx.Commit(); err != nil { + return roomtimedomain.CompensationResult{}, err + } + return result, nil +} + +func applyJoined(ctx context.Context, tx *sql.Tx, event roomtimedomain.RoomPresenceEvent) (roomtimedomain.ApplyResult, error) { + openSessions, err := openSessionsForUpdate(ctx, tx, event.AppCode, event.UserID) + if err != nil { + return roomtimedomain.ApplyResult{}, err + } + for _, session := range openSessions { + // 一个用户同一时刻只保留一个在房会话:房间侧一个在线周期只发一条 Joined, + // 这里还有 open 会话说明它的 Left/Kicked 丢失或尚未到达,用新进房时刻闭合避免双计。 + reason := roomtimedomain.EndReasonSupersededByJoin + if session.RoomID == event.RoomID { + reason = roomtimedomain.EndReasonSupersededByRejoin + } + if err := closeRoomSession(ctx, tx, session, closeRoomSessionInput{ + ClosedEventID: event.EventID, + EndAtMs: event.OccurredAtMs, + EndReason: reason, + UpdatedAtMs: event.OccurredAtMs, + RoomVersion: event.RoomVersion, + }); err != nil { + return roomtimedomain.ApplyResult{}, err + } + } + + orphan, matched, err := matchOrphanLeave(ctx, tx, event) + if err != nil { + return roomtimedomain.ApplyResult{}, err + } + joinedSession := roomSessionRow{ + AppCode: event.AppCode, + RoomSessionID: event.EventID, + UserID: event.UserID, + RoomID: event.RoomID, + Status: roomtimedomain.SessionStatusOpen, + IsRobot: event.IsRobot, + JoinedAtMs: event.OccurredAtMs, + LastRoomVersion: event.RoomVersion, + } + if matched { + // Left 先到、Joined 后到:直接落一条已闭合会话,时长取两个事实的间隔。 + if err := insertRoomSession(ctx, tx, joinedSession, event, roomtimedomain.SessionStatusOpen); err != nil { + return roomtimedomain.ApplyResult{}, err + } + if err := closeRoomSession(ctx, tx, joinedSession, closeRoomSessionInput{ + ClosedEventID: orphan.EventID, + EndAtMs: orphan.LeftAtMs, + EndReason: roomtimedomain.EndReasonOrphanLeft, + UpdatedAtMs: event.OccurredAtMs, + RoomVersion: event.RoomVersion, + }); err != nil { + return roomtimedomain.ApplyResult{}, err + } + if _, err := tx.ExecContext(ctx, ` + DELETE FROM user_room_orphan_leaves WHERE app_code = ? AND event_id = ? + `, event.AppCode, orphan.EventID); err != nil { + return roomtimedomain.ApplyResult{}, err + } + return roomtimedomain.ApplyResult{Consumed: true, Opened: true, Closed: true, Reason: "matched_orphan_left"}, nil + } + + if err := insertRoomSession(ctx, tx, joinedSession, event, roomtimedomain.SessionStatusOpen); err != nil { + return roomtimedomain.ApplyResult{}, err + } + return roomtimedomain.ApplyResult{Consumed: true, Opened: true}, nil +} + +func applyLeft(ctx context.Context, tx *sql.Tx, event roomtimedomain.RoomPresenceEvent, endReason string) (roomtimedomain.ApplyResult, error) { + openSessions, err := openRoomSessionsForUpdate(ctx, tx, event.AppCode, event.RoomID, event.UserID) + if err != nil { + return roomtimedomain.ApplyResult{}, err + } + closed := 0 + sawNewerSession := false + for _, session := range openSessions { + if session.JoinedAtMs > event.OccurredAtMs { + // Left 早于当前 open 会话的进房时刻,说明它属于更早的在线周期;那个周期已被 supersede 闭合,直接丢弃。 + sawNewerSession = true + continue + } + if err := closeRoomSession(ctx, tx, session, closeRoomSessionInput{ + ClosedEventID: event.EventID, + EndAtMs: event.OccurredAtMs, + EndReason: endReason, + UpdatedAtMs: event.OccurredAtMs, + RoomVersion: event.RoomVersion, + }); err != nil { + return roomtimedomain.ApplyResult{}, err + } + closed++ + } + if closed > 0 { + return roomtimedomain.ApplyResult{Consumed: true, Closed: true}, nil + } + if sawNewerSession { + return roomtimedomain.ApplyResult{Skipped: true, Reason: "stale_left_event"}, nil + } + // 没有可闭合的会话:Left 可能先于 Joined 到达,暂存等 Joined 到达时直接生成闭合会话。 + // 踢人对已离房用户也会发 RoomUserKicked,这类孤儿记录不会匹配任何更晚的进房事实,由补偿任务清理。 + if _, err := tx.ExecContext(ctx, ` + INSERT IGNORE INTO user_room_orphan_leaves (app_code, event_id, room_id, user_id, left_at_ms, reason, created_at_ms) + VALUES (?, ?, ?, ?, ?, ?, ?) + `, event.AppCode, event.EventID, event.RoomID, event.UserID, event.OccurredAtMs, endReason, event.OccurredAtMs); err != nil { + return roomtimedomain.ApplyResult{}, err + } + return roomtimedomain.ApplyResult{Skipped: true, Reason: "left_before_join_buffered"}, nil +} + +type closeRoomSessionInput struct { + ClosedEventID string + EndAtMs int64 + EndReason string + UpdatedAtMs int64 + RoomVersion int64 +} + +func closeRoomSession(ctx context.Context, tx *sql.Tx, session roomSessionRow, input closeRoomSessionInput) error { + input.ClosedEventID = strings.TrimSpace(input.ClosedEventID) + if input.ClosedEventID == "" { + input.ClosedEventID = "closed:" + session.RoomSessionID + } + input.EndReason = strings.TrimSpace(input.EndReason) + if input.EndReason == "" { + input.EndReason = roomtimedomain.EndReasonLeft + } + if input.EndAtMs < session.JoinedAtMs { + input.EndAtMs = session.JoinedAtMs + } + if input.UpdatedAtMs <= 0 { + input.UpdatedAtMs = input.EndAtMs + } + roomOnlineMs := maxInt64(0, input.EndAtMs-session.JoinedAtMs) + + _, err := tx.ExecContext(ctx, ` + UPDATE user_room_sessions + SET status = ?, ended_at_ms = ?, end_reason = ?, room_online_ms = ?, + closed_event_id = ?, last_event_id = ?, last_room_version = GREATEST(last_room_version, ?), updated_at_ms = ? + WHERE app_code = ? AND room_session_id = ? AND status <> ? + `, roomtimedomain.SessionStatusEnded, input.EndAtMs, input.EndReason, roomOnlineMs, + input.ClosedEventID, input.ClosedEventID, input.RoomVersion, input.UpdatedAtMs, + session.AppCode, session.RoomSessionID, roomtimedomain.SessionStatusEnded) + if err != nil { + return err + } + if session.IsRobot { + // 机器人在房不产生活跃/时长统计事实;会话仍闭合留档,方便排查调度行为。 + return nil + } + return incrementDaily(ctx, tx, session, input) +} + +func incrementDaily(ctx context.Context, tx *sql.Tx, session roomSessionRow, input closeRoomSessionInput) error { + for date, part := range splitByUTCDay(session.JoinedAtMs, input.EndAtMs) { + _, err := tx.ExecContext(ctx, ` + INSERT INTO user_room_daily_stats ( + app_code, user_id, stat_date, room_online_ms, session_count, first_room_at_ms, last_room_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, 1, ?, ?, ?) + ON DUPLICATE KEY UPDATE + room_online_ms = room_online_ms + VALUES(room_online_ms), + session_count = session_count + 1, + first_room_at_ms = CASE WHEN first_room_at_ms = 0 OR first_room_at_ms > VALUES(first_room_at_ms) THEN VALUES(first_room_at_ms) ELSE first_room_at_ms END, + last_room_at_ms = GREATEST(last_room_at_ms, VALUES(last_room_at_ms)), + updated_at_ms = VALUES(updated_at_ms) + `, session.AppCode, session.UserID, date, part.DurationMs, part.FirstAtMs, part.LastAtMs, input.UpdatedAtMs) + if err != nil { + return err + } + if err := insertUserOutbox(ctx, tx, session.AppCode, + roomtimedomain.EventTypeUserRoomDailyStatsUpdated+":"+session.RoomSessionID+":"+date, + roomtimedomain.EventTypeUserRoomDailyStatsUpdated, "user_room_daily_stats", session.UserID, input.UpdatedAtMs, map[string]any{ + "app_code": session.AppCode, + "user_id": session.UserID, + "room_id": session.RoomID, + "stat_date": date, + "room_session_id": session.RoomSessionID, + "room_online_delta_ms": part.DurationMs, + "session_count_delta": 1, + "end_reason": input.EndReason, + "updated_at_ms": input.UpdatedAtMs, + }); err != nil { + return err + } + } + return nil +} + +type roomSessionRow struct { + AppCode string + RoomSessionID string + UserID int64 + RoomID string + Status string + IsRobot bool + JoinedAtMs int64 + LastRoomVersion int64 +} + +type orphanLeaveRow struct { + EventID string + LeftAtMs int64 +} + +func openSessionsForUpdate(ctx context.Context, tx *sql.Tx, appCode string, userID int64) ([]roomSessionRow, error) { + return scanSessions(tx.QueryContext(ctx, ` + SELECT app_code, room_session_id, user_id, room_id, status, is_robot, joined_at_ms, last_room_version + FROM user_room_sessions + WHERE app_code = ? AND user_id = ? AND status = ? + ORDER BY joined_at_ms ASC, room_session_id ASC + FOR UPDATE + `, appCode, userID, roomtimedomain.SessionStatusOpen)) +} + +func openRoomSessionsForUpdate(ctx context.Context, tx *sql.Tx, appCode string, roomID string, userID int64) ([]roomSessionRow, error) { + return scanSessions(tx.QueryContext(ctx, ` + SELECT app_code, room_session_id, user_id, room_id, status, is_robot, joined_at_ms, last_room_version + FROM user_room_sessions + WHERE app_code = ? AND user_id = ? AND room_id = ? AND status = ? + ORDER BY joined_at_ms ASC, room_session_id ASC + FOR UPDATE + `, appCode, userID, roomID, roomtimedomain.SessionStatusOpen)) +} + +func scanSessions(rows *sql.Rows, err error) ([]roomSessionRow, error) { + if err != nil { + return nil, err + } + defer rows.Close() + sessions := []roomSessionRow{} + for rows.Next() { + var session roomSessionRow + if err := rows.Scan(&session.AppCode, &session.RoomSessionID, &session.UserID, &session.RoomID, &session.Status, &session.IsRobot, &session.JoinedAtMs, &session.LastRoomVersion); err != nil { + return nil, err + } + sessions = append(sessions, session) + } + return sessions, rows.Err() +} + +func matchOrphanLeave(ctx context.Context, tx *sql.Tx, event roomtimedomain.RoomPresenceEvent) (orphanLeaveRow, bool, error) { + var orphan orphanLeaveRow + err := tx.QueryRowContext(ctx, ` + SELECT event_id, left_at_ms + FROM user_room_orphan_leaves + WHERE app_code = ? AND room_id = ? AND user_id = ? AND left_at_ms >= ? + ORDER BY left_at_ms ASC + LIMIT 1 + FOR UPDATE + `, event.AppCode, event.RoomID, event.UserID, event.OccurredAtMs).Scan(&orphan.EventID, &orphan.LeftAtMs) + if err == sql.ErrNoRows { + return orphanLeaveRow{}, false, nil + } + if err != nil { + return orphanLeaveRow{}, false, err + } + return orphan, true, nil +} + +func insertRoomSession(ctx context.Context, tx *sql.Tx, session roomSessionRow, event roomtimedomain.RoomPresenceEvent, status string) error { + _, err := tx.ExecContext(ctx, ` + INSERT INTO user_room_sessions ( + app_code, room_session_id, user_id, room_id, status, is_robot, + joined_at_ms, ended_at_ms, end_reason, room_online_ms, + opened_event_id, closed_event_id, last_event_id, last_room_version, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, NULL, '', 0, ?, '', ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + last_event_id = VALUES(last_event_id), + last_room_version = GREATEST(last_room_version, VALUES(last_room_version)), + updated_at_ms = VALUES(updated_at_ms) + `, session.AppCode, session.RoomSessionID, session.UserID, session.RoomID, status, session.IsRobot, + session.JoinedAtMs, event.EventID, event.EventID, event.RoomVersion, event.OccurredAtMs, event.OccurredAtMs) + return err +} + +func insertEventConsumption(ctx context.Context, tx *sql.Tx, event roomtimedomain.RoomPresenceEvent) error { + _, err := tx.ExecContext(ctx, ` + INSERT INTO user_room_event_consumption ( + app_code, event_id, event_type, room_id, user_id, status, skip_reason, + created_at_ms, consumed_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, 'processing', '', ?, NULL, ?) + `, event.AppCode, event.EventID, event.EventType, event.RoomID, event.UserID, event.OccurredAtMs, event.OccurredAtMs) + return err +} + +func finishEventConsumption(ctx context.Context, tx *sql.Tx, event roomtimedomain.RoomPresenceEvent, status string, reason string) error { + _, err := tx.ExecContext(ctx, ` + UPDATE user_room_event_consumption + SET status = ?, skip_reason = ?, consumed_at_ms = ?, updated_at_ms = ? + WHERE app_code = ? AND event_id = ? + `, status, strings.TrimSpace(reason), event.OccurredAtMs, event.OccurredAtMs, event.AppCode, event.EventID) + return err +} + +func insertUserOutbox(ctx context.Context, tx *sql.Tx, appCode string, eventID string, eventType string, aggregateType string, aggregateID int64, createdAtMs int64, payload map[string]any) error { + payloadBytes, err := json.Marshal(payload) + if err != nil { + return err + } + _, err = tx.ExecContext(ctx, ` + INSERT IGNORE INTO user_outbox (app_code, event_id, event_type, aggregate_type, aggregate_id, status, payload_json, created_at_ms, updated_at_ms) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) + `, appcode.Normalize(appCode), eventID, eventType, aggregateType, aggregateID, userOutboxStatusPending, string(payloadBytes), createdAtMs, createdAtMs) + return err +} + +func normalizeRoomPresenceEvent(event roomtimedomain.RoomPresenceEvent) roomtimedomain.RoomPresenceEvent { + event.AppCode = appcode.Normalize(event.AppCode) + event.EventID = strings.TrimSpace(event.EventID) + event.EventType = strings.TrimSpace(event.EventType) + event.RoomID = strings.TrimSpace(event.RoomID) + return event +} + +func normalizeCompensationOptions(options roomtimedomain.CompensationOptions) roomtimedomain.CompensationOptions { + if options.NowMs <= 0 { + options.NowMs = time.Now().UnixMilli() + } + if options.BatchSize <= 0 { + options.BatchSize = defaultCompensationBatchSize + } + if options.OpenSessionMaxAgeMs <= 0 { + options.OpenSessionMaxAgeMs = defaultOpenSessionCompensationMs + } + return options +} + +type dayDuration struct { + DurationMs int64 + FirstAtMs int64 + LastAtMs int64 +} + +func splitByUTCDay(startMs int64, endMs int64) map[string]dayDuration { + parts := map[string]dayDuration{} + if endMs <= startMs { + return parts + } + for cursor := startMs; cursor < endMs; { + cursorTime := time.UnixMilli(cursor).UTC() + dayStart := time.Date(cursorTime.Year(), cursorTime.Month(), cursorTime.Day(), 0, 0, 0, 0, time.UTC) + nextDayMs := dayStart.AddDate(0, 0, 1).UnixMilli() + segmentEnd := minInt64(endMs, nextDayMs) + date := dayStart.Format("2006-01-02") + part := parts[date] + if part.FirstAtMs == 0 || cursor < part.FirstAtMs { + part.FirstAtMs = cursor + } + if segmentEnd > part.LastAtMs { + part.LastAtMs = segmentEnd + } + part.DurationMs += segmentEnd - cursor + parts[date] = part + cursor = segmentEnd + } + return parts +} + +func isDuplicate(err error) bool { + var mysqlErr *mysqldriver.MySQLError + return errors.As(err, &mysqlErr) && mysqlErr.Number == 1062 +} + +func minInt64(a int64, b int64) int64 { + if a < b { + return a + } + return b +} + +func maxInt64(a int64, b int64) int64 { + if a > b { + return a + } + return b +} diff --git a/services/user-service/internal/storage/mysql/roomtime/repository_test.go b/services/user-service/internal/storage/mysql/roomtime/repository_test.go new file mode 100644 index 00000000..94081d22 --- /dev/null +++ b/services/user-service/internal/storage/mysql/roomtime/repository_test.go @@ -0,0 +1,224 @@ +package roomtime_test + +import ( + "context" + "database/sql" + "testing" + "time" + + roomtimedomain "hyapp/services/user-service/internal/domain/roomtime" + "hyapp/services/user-service/internal/testutil/mysqltest" +) + +func TestProcessJoinedAndLeftAggregatesDailyAndDeduplicates(t *testing.T) { + wrapped := mysqltest.NewRepository(t) + repo := wrapped.Repository.RoomTimeRepository() + ctx := context.Background() + base := time.Date(2026, 7, 1, 10, 0, 0, 0, time.UTC).UnixMilli() + + mustApply(t, repo, presenceEvent("evt-join", roomtimedomain.RoomUserJoinedEventType, "room-a", 20001, base)) + mustApply(t, repo, presenceEvent("evt-left", roomtimedomain.RoomUserLeftEventType, "room-a", 20001, base+11*60_000)) + + assertDailyStats(t, wrapped.RawDB(), 20001, "2026-07-01", 11*60_000, 1) + assertSessionEnded(t, wrapped.RawDB(), "evt-join", roomtimedomain.EndReasonLeft) + assertUserOutboxEvent(t, wrapped.RawDB(), "UserRoomDailyStatsUpdated:evt-join:2026-07-01", 1) + + duplicate, err := repo.ProcessRoomPresenceEvent(ctx, presenceEvent("evt-left", roomtimedomain.RoomUserLeftEventType, "room-a", 20001, base+11*60_000)) + if err != nil || !duplicate.Skipped || duplicate.Reason != "already_consumed" { + t.Fatalf("duplicate left should skip: result=%+v err=%v", duplicate, err) + } + assertDailyStats(t, wrapped.RawDB(), 20001, "2026-07-01", 11*60_000, 1) +} + +func TestProcessKickedClosesOpenSession(t *testing.T) { + wrapped := mysqltest.NewRepository(t) + repo := wrapped.Repository.RoomTimeRepository() + base := time.Date(2026, 7, 1, 12, 0, 0, 0, time.UTC).UnixMilli() + + mustApply(t, repo, presenceEvent("evt-kick-join", roomtimedomain.RoomUserJoinedEventType, "room-a", 20002, base)) + mustApply(t, repo, presenceEvent("evt-kick", roomtimedomain.RoomUserKickedEventType, "room-a", 20002, base+5*60_000)) + + assertSessionEnded(t, wrapped.RawDB(), "evt-kick-join", roomtimedomain.EndReasonKicked) + assertDailyStats(t, wrapped.RawDB(), 20002, "2026-07-01", 5*60_000, 1) +} + +func TestLeftBeforeJoinedBuffersOrphanAndSettlesOnJoin(t *testing.T) { + wrapped := mysqltest.NewRepository(t) + repo := wrapped.Repository.RoomTimeRepository() + ctx := context.Background() + base := time.Date(2026, 7, 1, 14, 0, 0, 0, time.UTC).UnixMilli() + + // Left 先到:没有 open 会话,暂存为孤儿离房。 + result, err := repo.ProcessRoomPresenceEvent(ctx, presenceEvent("evt-ooo-left", roomtimedomain.RoomUserLeftEventType, "room-a", 20003, base+7*60_000)) + if err != nil || !result.Skipped || result.Reason != "left_before_join_buffered" { + t.Fatalf("orphan left should buffer: result=%+v err=%v", result, err) + } + + // Joined 后到:直接生成闭合会话,时长取两个事实的间隔。 + joined, err := repo.ProcessRoomPresenceEvent(ctx, presenceEvent("evt-ooo-join", roomtimedomain.RoomUserJoinedEventType, "room-a", 20003, base)) + if err != nil || !joined.Closed || joined.Reason != "matched_orphan_left" { + t.Fatalf("joined should settle orphan left: result=%+v err=%v", joined, err) + } + assertSessionEnded(t, wrapped.RawDB(), "evt-ooo-join", roomtimedomain.EndReasonOrphanLeft) + assertDailyStats(t, wrapped.RawDB(), 20003, "2026-07-01", 7*60_000, 1) + + var orphans int + if err := wrapped.RawDB().QueryRowContext(ctx, ` + SELECT COUNT(*) FROM user_room_orphan_leaves WHERE app_code = 'lalu' AND user_id = 20003 + `).Scan(&orphans); err != nil { + t.Fatalf("query orphan leaves failed: %v", err) + } + if orphans != 0 { + t.Fatalf("matched orphan leave should be deleted, got %d rows", orphans) + } +} + +func TestJoinSupersedesLingeringOpenSessionInOtherRoom(t *testing.T) { + wrapped := mysqltest.NewRepository(t) + repo := wrapped.Repository.RoomTimeRepository() + base := time.Date(2026, 7, 1, 16, 0, 0, 0, time.UTC).UnixMilli() + + mustApply(t, repo, presenceEvent("evt-super-join-a", roomtimedomain.RoomUserJoinedEventType, "room-a", 20004, base)) + // room-a 的 Left 丢失,用户直接出现在 room-b:旧会话按新进房时刻闭合,避免双计。 + mustApply(t, repo, presenceEvent("evt-super-join-b", roomtimedomain.RoomUserJoinedEventType, "room-b", 20004, base+3*60_000)) + + assertSessionEnded(t, wrapped.RawDB(), "evt-super-join-a", roomtimedomain.EndReasonSupersededByJoin) + assertDailyStats(t, wrapped.RawDB(), 20004, "2026-07-01", 3*60_000, 1) + + mustApply(t, repo, presenceEvent("evt-super-left-b", roomtimedomain.RoomUserLeftEventType, "room-b", 20004, base+10*60_000)) + assertDailyStats(t, wrapped.RawDB(), 20004, "2026-07-01", 10*60_000, 2) +} + +func TestRobotSessionsCloseWithoutStatsFacts(t *testing.T) { + wrapped := mysqltest.NewRepository(t) + repo := wrapped.Repository.RoomTimeRepository() + ctx := context.Background() + base := time.Date(2026, 7, 1, 18, 0, 0, 0, time.UTC).UnixMilli() + + robotJoin := presenceEvent("evt-robot-join", roomtimedomain.RoomUserJoinedEventType, "room-a", 20005, base) + robotJoin.IsRobot = true + mustApply(t, repo, robotJoin) + mustApply(t, repo, presenceEvent("evt-robot-left", roomtimedomain.RoomUserLeftEventType, "room-a", 20005, base+9*60_000)) + + assertSessionEnded(t, wrapped.RawDB(), "evt-robot-join", roomtimedomain.EndReasonLeft) + var rows int + if err := wrapped.RawDB().QueryRowContext(ctx, ` + SELECT COUNT(*) FROM user_room_daily_stats WHERE app_code = 'lalu' AND user_id = 20005 + `).Scan(&rows); err != nil { + t.Fatalf("query daily stats failed: %v", err) + } + if rows != 0 { + t.Fatalf("robot session must not produce daily stats, got %d rows", rows) + } + assertUserOutboxEvent(t, wrapped.RawDB(), "UserRoomDailyStatsUpdated:evt-robot-join:2026-07-01", 0) +} + +func TestCrossDaySessionSplitsByUTCDay(t *testing.T) { + wrapped := mysqltest.NewRepository(t) + repo := wrapped.Repository.RoomTimeRepository() + base := time.Date(2026, 7, 1, 23, 50, 0, 0, time.UTC).UnixMilli() + + mustApply(t, repo, presenceEvent("evt-cross-join", roomtimedomain.RoomUserJoinedEventType, "room-a", 20006, base)) + mustApply(t, repo, presenceEvent("evt-cross-left", roomtimedomain.RoomUserLeftEventType, "room-a", 20006, base+30*60_000)) + + assertDailyStats(t, wrapped.RawDB(), 20006, "2026-07-01", 10*60_000, 1) + assertDailyStats(t, wrapped.RawDB(), 20006, "2026-07-02", 20*60_000, 1) + assertUserOutboxEvent(t, wrapped.RawDB(), "UserRoomDailyStatsUpdated:evt-cross-join:2026-07-01", 1) + assertUserOutboxEvent(t, wrapped.RawDB(), "UserRoomDailyStatsUpdated:evt-cross-join:2026-07-02", 1) +} + +func TestCompensateOpenSessionsClosesStaleSessionsAndPrunesOrphans(t *testing.T) { + wrapped := mysqltest.NewRepository(t) + repo := wrapped.Repository.RoomTimeRepository() + ctx := context.Background() + base := time.Date(2026, 7, 1, 8, 0, 0, 0, time.UTC).UnixMilli() + + mustApply(t, repo, presenceEvent("evt-comp-join", roomtimedomain.RoomUserJoinedEventType, "room-a", 20007, base)) + if _, err := repo.ProcessRoomPresenceEvent(ctx, presenceEvent("evt-comp-orphan", roomtimedomain.RoomUserLeftEventType, "room-b", 20008, base)); err != nil { + t.Fatalf("buffer orphan left failed: %v", err) + } + + result, err := repo.CompensateOpenSessions(ctx, roomtimedomain.CompensationOptions{ + NowMs: base + 30*60*60*1000, + BatchSize: 10, + OpenSessionMaxAgeMs: 24 * 60 * 60 * 1000, + }) + if err != nil { + t.Fatalf("CompensateOpenSessions failed: %v", err) + } + if result.ClosedCount != 1 || result.OrphanLeavesDeleted != 1 { + t.Fatalf("compensation result mismatch: %+v", result) + } + assertSessionEnded(t, wrapped.RawDB(), "evt-comp-join", roomtimedomain.CompensationReasonOpenSessionMaxWindow) + // 补偿闭合按 joined_at + max_age 封顶记时长,跨 7/1 与 7/2 两个 UTC 日。 + assertDailyStats(t, wrapped.RawDB(), 20007, "2026-07-01", 16*60*60*1000, 1) + assertDailyStats(t, wrapped.RawDB(), 20007, "2026-07-02", 8*60*60*1000, 1) +} + +func mustApply(t *testing.T, repo interface { + ProcessRoomPresenceEvent(context.Context, roomtimedomain.RoomPresenceEvent) (roomtimedomain.ApplyResult, error) +}, event roomtimedomain.RoomPresenceEvent) { + t.Helper() + result, err := repo.ProcessRoomPresenceEvent(context.Background(), event) + if err != nil || result.Skipped { + t.Fatalf("ProcessRoomPresenceEvent failed: event=%+v result=%+v err=%v", event, result, err) + } +} + +func presenceEvent(eventID string, eventType string, roomID string, userID int64, occurredAtMs int64) roomtimedomain.RoomPresenceEvent { + return roomtimedomain.RoomPresenceEvent{ + AppCode: "lalu", + EventID: eventID, + EventType: eventType, + RoomID: roomID, + RoomVersion: occurredAtMs, + OccurredAtMs: occurredAtMs, + UserID: userID, + } +} + +func assertDailyStats(t *testing.T, db *sql.DB, userID int64, statDate string, wantOnlineMs int64, wantSessions int64) { + t.Helper() + var onlineMs, sessions int64 + if err := db.QueryRowContext(context.Background(), ` + SELECT room_online_ms, session_count + FROM user_room_daily_stats + WHERE app_code = 'lalu' AND user_id = ? AND stat_date = ? + `, userID, statDate).Scan(&onlineMs, &sessions); err != nil { + t.Fatalf("query user_room_daily_stats user=%d date=%s failed: %v", userID, statDate, err) + } + if onlineMs != wantOnlineMs || sessions != wantSessions { + t.Fatalf("daily stats mismatch user=%d date=%s: online=%d sessions=%d, want online=%d sessions=%d", userID, statDate, onlineMs, sessions, wantOnlineMs, wantSessions) + } +} + +func assertSessionEnded(t *testing.T, db *sql.DB, roomSessionID string, reason string) { + t.Helper() + var status string + var endReason string + if err := db.QueryRowContext(context.Background(), ` + SELECT status, end_reason + FROM user_room_sessions + WHERE app_code = 'lalu' AND room_session_id = ? + `, roomSessionID).Scan(&status, &endReason); err != nil { + t.Fatalf("query user_room_sessions failed: %v", err) + } + if status != roomtimedomain.SessionStatusEnded || endReason != reason { + t.Fatalf("session %s terminal state mismatch: status=%s reason=%s want=%s", roomSessionID, status, endReason, reason) + } +} + +func assertUserOutboxEvent(t *testing.T, db *sql.DB, eventID string, want int) { + t.Helper() + var count int + if err := db.QueryRowContext(context.Background(), ` + SELECT COUNT(*) + FROM user_outbox + WHERE app_code = 'lalu' AND event_id = ? + `, eventID).Scan(&count); err != nil { + t.Fatalf("query user_outbox failed: %v", err) + } + if count != want { + t.Fatalf("user_outbox event %s count=%d, want %d", eventID, count, want) + } +} diff --git a/services/user-service/internal/storage/mysql/user/admin_ban.go b/services/user-service/internal/storage/mysql/user/admin_ban.go new file mode 100644 index 00000000..447a2dbb --- /dev/null +++ b/services/user-service/internal/storage/mysql/user/admin_ban.go @@ -0,0 +1,479 @@ +package user + +import ( + "context" + "database/sql" + "errors" + "strings" + + "hyapp/pkg/appcode" + "hyapp/pkg/idgen" + "hyapp/pkg/xerr" + userdomain "hyapp/services/user-service/internal/domain/user" + userservice "hyapp/services/user-service/internal/service/user" +) + +const adminBanStatusReasonPrefix = "admin_user_ban:" + +// CreateAdminUserBan 在一个事务内写封禁事实、切换 users.status、写审计并吊销 refresh session。 +// 目标已经因其他事实处于 banned 时只叠加事实,不重复写 banned->banned 日志;该约束也是历史永久封禁不被误恢复的判据。 +func (r *Repository) CreateAdminUserBan(ctx context.Context, command userservice.AdminUserBanCommand) (userservice.AdminUserBanPersistenceResult, error) { + if r == nil || r.db == nil { + return userservice.AdminUserBanPersistenceResult{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + appCode := appcode.FromContext(ctx) + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return userservice.AdminUserBanPersistenceResult{}, err + } + defer func() { _ = tx.Rollback() }() + + var oldStatus string + if err := tx.QueryRowContext(ctx, ` + SELECT status + FROM users + WHERE app_code = ? AND user_id = ? + FOR UPDATE`, appCode, command.TargetUserID).Scan(&oldStatus); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return userservice.AdminUserBanPersistenceResult{}, xerr.New(xerr.NotFound, "user not found") + } + return userservice.AdminUserBanPersistenceResult{}, err + } + if userdomain.Status(oldStatus) != userdomain.StatusActive && userdomain.Status(oldStatus) != userdomain.StatusBanned { + // disabled 是独立平台停用语义,不能用封禁事实覆盖;后台应先显式恢复后再封禁。 + return userservice.AdminUserBanPersistenceResult{}, xerr.New(xerr.InvalidArgument, "target user status cannot be banned") + } + + banID := idgen.New("admin_ban") + _, err = tx.ExecContext(ctx, ` + INSERT INTO admin_user_bans ( + app_code, ban_id, command_id, target_user_id, target_old_status, + expires_at_ms, status, reason, operator_admin_id, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, 'active', ?, ?, ?, ?)`, + appCode, banID, command.CommandID, command.TargetUserID, oldStatus, + command.ExpiresAtMs, command.Reason, command.OperatorAdminID, command.NowMs, command.NowMs, + ) + if err != nil { + if adminBanDuplicate(err) { + // 幂等命令可能在上一次调用中已经完整提交;回滚当前事务后读取既有事实和当前用户状态即可。 + _ = tx.Rollback() + ban, lookupErr := r.getAdminUserBanByCommand(ctx, command.CommandID) + if lookupErr != nil { + return userservice.AdminUserBanPersistenceResult{}, lookupErr + } + if ban.TargetUserID != command.TargetUserID || ban.OperatorAdminID != command.OperatorAdminID || ban.ExpiresAtMs != command.ExpiresAtMs || ban.Reason != command.Reason { + // command_id 是完整请求的幂等边界;同一 key 不能静默复用到另一位用户或另一种封禁期限。 + return userservice.AdminUserBanPersistenceResult{}, xerr.New(xerr.Conflict, "admin ban command payload does not match existing fact") + } + user, lookupErr := r.GetUser(ctx, ban.TargetUserID) + if lookupErr != nil { + return userservice.AdminUserBanPersistenceResult{}, lookupErr + } + return userservice.AdminUserBanPersistenceResult{Ban: ban, Status: userservice.UserStatusPersistenceResult{User: user}}, nil + } + return userservice.AdminUserBanPersistenceResult{}, err + } + + sessionIDs := make([]string, 0) + statusChanged := userdomain.Status(oldStatus) == userdomain.StatusActive + if statusChanged { + if _, err := tx.ExecContext(ctx, ` + UPDATE users SET status = 'banned', updated_at_ms = ? + WHERE app_code = ? AND user_id = ?`, command.NowMs, appCode, command.TargetUserID); err != nil { + return userservice.AdminUserBanPersistenceResult{}, err + } + if _, err := tx.ExecContext(ctx, ` + INSERT INTO user_status_change_logs ( + app_code, target_user_id, old_status, new_status, operator_type, + operator_user_id, reason, request_id, created_at_ms + ) VALUES (?, ?, ?, 'banned', 'admin', ?, ?, ?, ?)`, + appCode, command.TargetUserID, oldStatus, command.OperatorAdminID, + adminBanStatusReasonPrefix+banID, command.RequestID, command.NowMs, + ); err != nil { + return userservice.AdminUserBanPersistenceResult{}, err + } + var revokeErr error + sessionIDs, revokeErr = revokeActiveUserSessions(ctx, tx, appCode, command.TargetUserID, command.OperatorAdminID, command.RequestID, command.NowMs) + if revokeErr != nil { + return userservice.AdminUserBanPersistenceResult{}, revokeErr + } + } + + if err := tx.Commit(); err != nil { + return userservice.AdminUserBanPersistenceResult{}, err + } + ban, err := r.getAdminUserBan(ctx, banID) + if err != nil { + return userservice.AdminUserBanPersistenceResult{}, err + } + user, err := r.GetUser(ctx, command.TargetUserID) + if err != nil { + return userservice.AdminUserBanPersistenceResult{}, err + } + return userservice.AdminUserBanPersistenceResult{ + Ban: ban, + Status: userservice.UserStatusPersistenceResult{User: user, RevokedSessionIDs: sessionIDs}, + StatusChanged: statusChanged, + }, nil +} + +func (r *Repository) ReleaseAdminUserBan(ctx context.Context, command userservice.ReleaseAdminUserBanCommand) (userservice.AdminUserBanRelease, error) { + return r.releaseAdminUserBan(ctx, command) +} + +func (r *Repository) ExpireAdminUserBans(ctx context.Context, nowMS int64, limit int32) ([]userservice.AdminUserBanRelease, error) { + if r == nil || r.db == nil { + return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + rows, err := r.db.QueryContext(ctx, ` + SELECT ban_id, target_user_id + FROM admin_user_bans + WHERE app_code = ? AND status = 'active' AND expires_at_ms > 0 AND expires_at_ms <= ? + ORDER BY expires_at_ms ASC, ban_id ASC + LIMIT ?`, appcode.FromContext(ctx), nowMS, limit) + if err != nil { + return nil, err + } + type pendingBan struct { + banID string + targetUserID int64 + } + pending := make([]pendingBan, 0) + for rows.Next() { + var item pendingBan + if err := rows.Scan(&item.banID, &item.targetUserID); err != nil { + _ = rows.Close() + return nil, err + } + pending = append(pending, item) + } + if err := rows.Close(); err != nil { + return nil, err + } + + releases := make([]userservice.AdminUserBanRelease, 0, len(pending)) + for _, item := range pending { + release, err := r.releaseAdminUserBan(ctx, userservice.ReleaseAdminUserBanCommand{ + BanID: item.banID, + TargetUserID: item.targetUserID, + Status: userservice.AdminUserBanStatusExpired, + Reason: "admin_user_ban_expired", + RequestID: "admin_user_ban_expire:" + item.banID, + NowMs: nowMS, + }) + if err != nil { + return releases, err + } + releases = append(releases, release) + } + return releases, nil +} + +func (r *Repository) releaseAdminUserBan(ctx context.Context, command userservice.ReleaseAdminUserBanCommand) (userservice.AdminUserBanRelease, error) { + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return userservice.AdminUserBanRelease{}, err + } + defer func() { _ = tx.Rollback() }() + + // 先锁定命令幂等事实,再选择具体 ban。空 ban_id 的重试会复用第一次解析出的 resolved_ban_id, + // 不会因为上一条已 released 而误释放下一条重叠管理员封禁。 + existingCommand, resolvedBanID, err := claimAdminBanReleaseCommand(ctx, tx, command) + if err != nil { + return userservice.AdminUserBanRelease{}, err + } + var ban userservice.AdminUserBan + if existingCommand { + ban, err = r.getAdminUserBanForUpdate(ctx, tx, resolvedBanID, command.TargetUserID) + } else if strings.TrimSpace(command.BanID) == "" { + // 后台摘要可能正在展示更晚到期的经理封禁;按 target 选最新管理员事实,使重叠场景仍能逐条手动释放。 + ban, err = r.getLatestActiveAdminUserBanForUpdate(ctx, tx, command.TargetUserID) + } else { + ban, err = r.getAdminUserBanForUpdate(ctx, tx, command.BanID, command.TargetUserID) + } + if err != nil { + return userservice.AdminUserBanRelease{}, err + } + if !existingCommand { + if _, err := tx.ExecContext(ctx, ` + UPDATE admin_user_ban_release_commands + SET resolved_ban_id = ?, updated_at_ms = ? + WHERE app_code = ? AND command_id = ?`, + ban.BanID, command.NowMs, appcode.FromContext(ctx), command.RequestID, + ); err != nil { + return userservice.AdminUserBanRelease{}, err + } + } + if ban.Status != userservice.AdminUserBanStatusActive { + if err := tx.Commit(); err != nil { + return userservice.AdminUserBanRelease{}, err + } + user, err := r.GetUser(ctx, ban.TargetUserID) + return userservice.AdminUserBanRelease{Ban: ban, User: user}, err + } + + currentStatus, err := lockUserStatus(ctx, tx, appcode.FromContext(ctx), ban.TargetUserID) + if err != nil { + return userservice.AdminUserBanRelease{}, err + } + if _, err := tx.ExecContext(ctx, ` + UPDATE admin_user_bans + SET status = ?, released_by_admin_id = ?, released_reason = ?, released_at_ms = ?, updated_at_ms = ? + WHERE app_code = ? AND ban_id = ?`, + command.Status, command.OperatorAdminID, command.Reason, command.NowMs, command.NowMs, + appcode.FromContext(ctx), ban.BanID, + ); err != nil { + return userservice.AdminUserBanRelease{}, err + } + ban.Status = command.Status + ban.ReleasedByAdminID = command.OperatorAdminID + ban.ReleasedReason = command.Reason + ban.ReleasedAtMs = command.NowMs + ban.UpdatedAtMs = command.NowMs + + restored, err := restoreUserAfterManagedBanRelease(ctx, tx, managedBanRestoreCommand{ + TargetUserID: ban.TargetUserID, + CurrentStatus: currentStatus, + OperatorType: releaseOperatorType(command.Status), + OperatorID: command.OperatorAdminID, + Reason: "admin_user_unban:" + ban.BanID, + RequestID: command.RequestID, + NowMs: command.NowMs, + }) + if err != nil { + return userservice.AdminUserBanRelease{}, err + } + if err := tx.Commit(); err != nil { + return userservice.AdminUserBanRelease{}, err + } + user, err := r.GetUser(ctx, ban.TargetUserID) + if err != nil { + return userservice.AdminUserBanRelease{}, err + } + return userservice.AdminUserBanRelease{Ban: ban, User: user, Restored: restored}, nil +} + +// claimAdminBanReleaseCommand 把一次手动/自动释放固定为不可变命令载荷。 +// INSERT IGNORE 会在同一 command_id 的并发请求间形成行级串行化,第二个请求提交后只读取首个 resolved_ban_id。 +func claimAdminBanReleaseCommand(ctx context.Context, tx *sql.Tx, command userservice.ReleaseAdminUserBanCommand) (bool, string, error) { + commandID := strings.TrimSpace(command.RequestID) + if commandID == "" { + return false, "", xerr.New(xerr.InvalidArgument, "admin unban request_id is required") + } + requestedBanID := strings.TrimSpace(command.BanID) + result, err := tx.ExecContext(ctx, ` + INSERT IGNORE INTO admin_user_ban_release_commands ( + app_code, command_id, target_user_id, requested_ban_id, resolved_ban_id, + release_status, operator_admin_id, reason, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, '', ?, ?, ?, ?, ?)`, + appcode.FromContext(ctx), commandID, command.TargetUserID, requestedBanID, + command.Status, command.OperatorAdminID, command.Reason, command.NowMs, command.NowMs, + ) + if err != nil { + return false, "", err + } + inserted, err := result.RowsAffected() + if err != nil { + return false, "", err + } + if inserted == 1 { + return false, "", nil + } + + var targetUserID int64 + var storedRequestedBanID, resolvedBanID, releaseStatus, reason string + var operatorAdminID int64 + if err := tx.QueryRowContext(ctx, ` + SELECT target_user_id, requested_ban_id, resolved_ban_id, release_status, operator_admin_id, reason + FROM admin_user_ban_release_commands + WHERE app_code = ? AND command_id = ? + FOR UPDATE`, appcode.FromContext(ctx), commandID).Scan( + &targetUserID, &storedRequestedBanID, &resolvedBanID, &releaseStatus, &operatorAdminID, &reason, + ); err != nil { + return false, "", err + } + if targetUserID != command.TargetUserID || storedRequestedBanID != requestedBanID || + releaseStatus != command.Status || operatorAdminID != command.OperatorAdminID || reason != command.Reason { + return false, "", xerr.New(xerr.Conflict, "admin unban command payload does not match existing command") + } + if strings.TrimSpace(resolvedBanID) == "" { + return false, "", xerr.New(xerr.Conflict, "admin unban command has no resolved ban") + } + return true, resolvedBanID, nil +} + +type managedBanRestoreCommand struct { + TargetUserID int64 + CurrentStatus userdomain.Status + OperatorType string + OperatorID int64 + Reason string + RequestID string + NowMs int64 +} + +// restoreUserAfterManagedBanRelease 在持有 users 行锁时检查全部可管理封禁来源并恢复账号。 +// 最新 banned 日志必须来自 admin/manager 事实;历史无日志或其他平台封禁即使没有 active 事实也不会被自动恢复。 +func restoreUserAfterManagedBanRelease(ctx context.Context, tx *sql.Tx, command managedBanRestoreCommand) (bool, error) { + if command.CurrentStatus != userdomain.StatusBanned { + return false, nil + } + activeCount, err := countActiveManagedBans(ctx, tx, command.TargetUserID) + if err != nil || activeCount > 0 { + return false, err + } + managed, err := latestBanBelongsToManagedFact(ctx, tx, command.TargetUserID) + if err != nil || !managed { + return false, err + } + if _, err := tx.ExecContext(ctx, ` + UPDATE users SET status = 'active', updated_at_ms = ? + WHERE app_code = ? AND user_id = ? AND status = 'banned'`, + command.NowMs, appcode.FromContext(ctx), command.TargetUserID, + ); err != nil { + return false, err + } + if _, err := tx.ExecContext(ctx, ` + INSERT INTO user_status_change_logs ( + app_code, target_user_id, old_status, new_status, operator_type, + operator_user_id, reason, request_id, created_at_ms + ) VALUES (?, ?, 'banned', 'active', ?, ?, ?, ?, ?)`, + appcode.FromContext(ctx), command.TargetUserID, command.OperatorType, + command.OperatorID, command.Reason, command.RequestID, command.NowMs, + ); err != nil { + return false, err + } + return true, nil +} + +func lockUserStatus(ctx context.Context, tx *sql.Tx, appCode string, userID int64) (userdomain.Status, error) { + var status string + if err := tx.QueryRowContext(ctx, ` + SELECT status FROM users WHERE app_code = ? AND user_id = ? FOR UPDATE`, appCode, userID).Scan(&status); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return "", xerr.New(xerr.NotFound, "user not found") + } + return "", err + } + return userdomain.Status(status), nil +} + +func countActiveManagedBans(ctx context.Context, tx *sql.Tx, targetUserID int64) (int64, error) { + var count int64 + err := tx.QueryRowContext(ctx, ` + SELECT + (SELECT COUNT(*) FROM manager_user_blocks WHERE app_code = ? AND target_user_id = ? AND status = 'active') + + (SELECT COUNT(*) FROM admin_user_bans WHERE app_code = ? AND target_user_id = ? AND status = 'active')`, + appcode.FromContext(ctx), targetUserID, appcode.FromContext(ctx), targetUserID, + ).Scan(&count) + return count, err +} + +func latestBanBelongsToManagedFact(ctx context.Context, tx *sql.Tx, targetUserID int64) (bool, error) { + var reason string + err := tx.QueryRowContext(ctx, ` + SELECT reason + FROM user_status_change_logs + WHERE app_code = ? AND target_user_id = ? AND new_status = 'banned' + ORDER BY created_at_ms DESC, id DESC + LIMIT 1`, appcode.FromContext(ctx), targetUserID).Scan(&reason) + if errors.Is(err, sql.ErrNoRows) { + return false, nil + } + if err != nil { + return false, err + } + return strings.HasPrefix(reason, "manager_center_block:") || strings.HasPrefix(reason, adminBanStatusReasonPrefix), nil +} + +func releaseOperatorType(status string) string { + if status == userservice.AdminUserBanStatusExpired || status == userservice.ManagerUserBlockStatusExpired { + return userservice.OperatorTypeSystem + } + return userservice.OperatorTypeAdmin +} + +func revokeActiveUserSessions(ctx context.Context, tx *sql.Tx, appCode string, targetUserID int64, operatorUserID int64, requestID string, nowMs int64) ([]string, error) { + rows, err := tx.QueryContext(ctx, ` + SELECT session_id + FROM auth_sessions + WHERE app_code = ? AND user_id = ? AND expires_at_ms > ? AND revoked_at_ms IS NULL + FOR UPDATE`, appCode, targetUserID, nowMs) + if err != nil { + return nil, err + } + sessionIDs := make([]string, 0) + for rows.Next() { + var sessionID string + if err := rows.Scan(&sessionID); err != nil { + _ = rows.Close() + return nil, err + } + sessionIDs = append(sessionIDs, sessionID) + } + if err := rows.Close(); err != nil { + return nil, err + } + _, err = tx.ExecContext(ctx, ` + UPDATE auth_sessions + SET revoked_at_ms = ?, revoked_reason = 'USER_BANNED', revoked_request_id = ?, revoked_by = ?, updated_at_ms = ? + WHERE app_code = ? AND user_id = ? AND revoked_at_ms IS NULL`, + nowMs, requestID, revokedBy(operatorUserID), nowMs, appCode, targetUserID) + return sessionIDs, err +} + +func (r *Repository) getAdminUserBan(ctx context.Context, banID string) (userservice.AdminUserBan, error) { + return scanAdminUserBan(r.db.QueryRowContext(ctx, adminBanSelectSQL()+` WHERE app_code = ? AND ban_id = ?`, appcode.FromContext(ctx), banID)) +} + +func (r *Repository) getAdminUserBanByCommand(ctx context.Context, commandID string) (userservice.AdminUserBan, error) { + return scanAdminUserBan(r.db.QueryRowContext(ctx, adminBanSelectSQL()+` WHERE app_code = ? AND command_id = ?`, appcode.FromContext(ctx), commandID)) +} + +func (r *Repository) getAdminUserBanForUpdate(ctx context.Context, tx *sql.Tx, banID string, targetUserID int64) (userservice.AdminUserBan, error) { + return scanAdminUserBan(tx.QueryRowContext(ctx, adminBanSelectSQL()+` + WHERE app_code = ? AND ban_id = ? AND target_user_id = ? FOR UPDATE`, + appcode.FromContext(ctx), banID, targetUserID)) +} + +func (r *Repository) getLatestActiveAdminUserBanForUpdate(ctx context.Context, tx *sql.Tx, targetUserID int64) (userservice.AdminUserBan, error) { + return scanAdminUserBan(tx.QueryRowContext(ctx, adminBanSelectSQL()+` + WHERE app_code = ? AND target_user_id = ? AND status = 'active' + ORDER BY created_at_ms DESC, ban_id DESC + LIMIT 1 FOR UPDATE`, appcode.FromContext(ctx), targetUserID)) +} + +func adminBanSelectSQL() string { + return `SELECT ban_id, command_id, target_user_id, target_old_status, expires_at_ms, + status, reason, operator_admin_id, created_at_ms, updated_at_ms, + released_by_admin_id, released_reason, released_at_ms + FROM admin_user_bans` +} + +type adminBanScanner interface { + Scan(dest ...any) error +} + +func scanAdminUserBan(scanner adminBanScanner) (userservice.AdminUserBan, error) { + var ban userservice.AdminUserBan + var oldStatus string + if err := scanner.Scan( + &ban.BanID, &ban.CommandID, &ban.TargetUserID, &oldStatus, &ban.ExpiresAtMs, + &ban.Status, &ban.Reason, &ban.OperatorAdminID, &ban.CreatedAtMs, &ban.UpdatedAtMs, + &ban.ReleasedByAdminID, &ban.ReleasedReason, &ban.ReleasedAtMs, + ); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return userservice.AdminUserBan{}, xerr.New(xerr.NotFound, "admin user ban not found") + } + return userservice.AdminUserBan{}, err + } + ban.TargetOldStatus = userdomain.Status(oldStatus) + return ban, nil +} + +func adminBanDuplicate(err error) bool { + if err == nil { + return false + } + return strings.Contains(err.Error(), "Duplicate entry") || strings.Contains(err.Error(), "Error 1062") +} diff --git a/services/user-service/internal/storage/mysql/user/admin_ban_test.go b/services/user-service/internal/storage/mysql/user/admin_ban_test.go new file mode 100644 index 00000000..9940bfdf --- /dev/null +++ b/services/user-service/internal/storage/mysql/user/admin_ban_test.go @@ -0,0 +1,295 @@ +package user_test + +import ( + "context" + "testing" + + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + userdomain "hyapp/services/user-service/internal/domain/user" + userservice "hyapp/services/user-service/internal/service/user" + "hyapp/services/user-service/internal/testutil/mysqltest" +) + +func TestAdminUserBanOverlapRestoresOnlyAfterLastManagedFact(t *testing.T) { + repo := mysqltest.NewRepository(t) + ctx := appcode.WithContext(context.Background(), "lalu") + createAdminBanTestUser(t, repo, 18001, "188001", userdomain.StatusActive) + storage := repo.Repository.UserRepository() + + first, err := storage.CreateAdminUserBan(ctx, userservice.AdminUserBanCommand{ + CommandID: "admin-ban-first", TargetUserID: 18001, ExpiresAtMs: 2_000, + OperatorAdminID: 9001, Reason: "first", RequestID: "req-first", NowMs: 1_000, + }) + if err != nil { + t.Fatalf("create first admin ban failed: %v", err) + } + second, err := storage.CreateAdminUserBan(ctx, userservice.AdminUserBanCommand{ + CommandID: "admin-ban-second", TargetUserID: 18001, ExpiresAtMs: 0, + OperatorAdminID: 9002, Reason: "second", RequestID: "req-second", NowMs: 1_100, + }) + if err != nil { + t.Fatalf("create overlapping admin ban failed: %v", err) + } + if !first.StatusChanged || second.StatusChanged { + t.Fatalf("only the first ban may transition user status: first=%+v second=%+v", first, second) + } + if _, err := storage.SetUserStatus(ctx, userservice.UserStatusCommand{ + AppCode: "lalu", TargetUserID: 18001, Status: userdomain.StatusActive, + OperatorType: userservice.OperatorTypeAdmin, OperatorUserID: 9003, RequestID: "bypass", NowMs: 1_150, + }); xerr.CodeOf(err) != xerr.Conflict { + t.Fatalf("generic active status must not bypass active ban facts, err=%v", err) + } + + firstRelease, err := storage.ReleaseAdminUserBan(ctx, userservice.ReleaseAdminUserBanCommand{ + BanID: first.Ban.BanID, TargetUserID: 18001, OperatorAdminID: 9001, + Status: userservice.AdminUserBanStatusReleased, Reason: "release-first", RequestID: "release-first", NowMs: 1_200, + }) + if err != nil { + t.Fatalf("release first admin ban failed: %v", err) + } + if firstRelease.Restored || firstRelease.User.Status != userdomain.StatusBanned { + t.Fatalf("remaining admin ban must keep user banned: %+v", firstRelease) + } + + secondRelease, err := storage.ReleaseAdminUserBan(ctx, userservice.ReleaseAdminUserBanCommand{ + BanID: second.Ban.BanID, TargetUserID: 18001, OperatorAdminID: 9002, + Status: userservice.AdminUserBanStatusReleased, Reason: "release-second", RequestID: "release-second", NowMs: 1_300, + }) + if err != nil { + t.Fatalf("release second admin ban failed: %v", err) + } + if !secondRelease.Restored || secondRelease.User.Status != userdomain.StatusActive { + t.Fatalf("last managed ban release must restore active user: %+v", secondRelease) + } +} + +func TestAdminUserBanReleaseWithoutIDSelectsLatestAdminFact(t *testing.T) { + repo := mysqltest.NewRepository(t) + ctx := appcode.WithContext(context.Background(), "lalu") + createAdminBanTestUser(t, repo, 18007, "188007", userdomain.StatusActive) + storage := repo.Repository.UserRepository() + first, err := storage.CreateAdminUserBan(ctx, userservice.AdminUserBanCommand{ + CommandID: "admin-ban-select-first", TargetUserID: 18007, ExpiresAtMs: 8_000, + OperatorAdminID: 9001, Reason: "first", RequestID: "select-first", NowMs: 6_000, + }) + if err != nil { + t.Fatalf("create first admin ban failed: %v", err) + } + second, err := storage.CreateAdminUserBan(ctx, userservice.AdminUserBanCommand{ + CommandID: "admin-ban-select-second", TargetUserID: 18007, ExpiresAtMs: 0, + OperatorAdminID: 9002, Reason: "second", RequestID: "select-second", NowMs: 6_100, + }) + if err != nil { + t.Fatalf("create second admin ban failed: %v", err) + } + release, err := storage.ReleaseAdminUserBan(ctx, userservice.ReleaseAdminUserBanCommand{ + TargetUserID: 18007, OperatorAdminID: 9003, Status: userservice.AdminUserBanStatusReleased, + Reason: "release-latest", RequestID: "release-latest", NowMs: 6_200, + }) + if err != nil { + t.Fatalf("release latest admin ban failed: %v", err) + } + if release.Ban.BanID != second.Ban.BanID || release.Restored || release.User.Status != userdomain.StatusBanned { + t.Fatalf("latest fact must be released while older fact keeps ban: release=%+v first=%+v", release, first.Ban) + } + // 同一 request_id 代表同一次解封命令;重试必须返回原结果,不能继续释放第一条重叠封禁。 + retry, err := storage.ReleaseAdminUserBan(ctx, userservice.ReleaseAdminUserBanCommand{ + TargetUserID: 18007, OperatorAdminID: 9003, Status: userservice.AdminUserBanStatusReleased, + Reason: "release-latest", RequestID: "release-latest", NowMs: 6_300, + }) + if err != nil { + t.Fatalf("retry latest admin ban release failed: %v", err) + } + if retry.Ban.BanID != second.Ban.BanID || retry.Restored || retry.User.Status != userdomain.StatusBanned { + t.Fatalf("retry must reuse resolved ban and leave older fact active: retry=%+v first=%+v", retry, first.Ban) + } + finalRelease, err := storage.ReleaseAdminUserBan(ctx, userservice.ReleaseAdminUserBanCommand{ + TargetUserID: 18007, OperatorAdminID: 9003, Status: userservice.AdminUserBanStatusReleased, + Reason: "release-remaining", RequestID: "release-remaining", NowMs: 6_400, + }) + if err != nil { + t.Fatalf("release remaining admin ban failed: %v", err) + } + if finalRelease.Ban.BanID != first.Ban.BanID || !finalRelease.Restored || finalRelease.User.Status != userdomain.StatusActive { + t.Fatalf("new command must release remaining fact and restore user: %+v", finalRelease) + } +} + +func TestAdminUserBanDoesNotRestoreLegacyBannedUser(t *testing.T) { + repo := mysqltest.NewRepository(t) + ctx := appcode.WithContext(context.Background(), "lalu") + createAdminBanTestUser(t, repo, 18002, "188002", userdomain.StatusBanned) + storage := repo.Repository.UserRepository() + + persisted, err := storage.CreateAdminUserBan(ctx, userservice.AdminUserBanCommand{ + CommandID: "legacy-overlay", TargetUserID: 18002, OperatorAdminID: 9001, + Reason: "legacy-overlay", RequestID: "legacy-overlay", NowMs: 2_000, + }) + if err != nil { + t.Fatalf("create admin fact over legacy ban failed: %v", err) + } + if persisted.StatusChanged { + t.Fatalf("legacy banned user must not get a synthetic banned->banned transition: %+v", persisted) + } + + release, err := storage.ReleaseAdminUserBan(ctx, userservice.ReleaseAdminUserBanCommand{ + BanID: persisted.Ban.BanID, TargetUserID: 18002, OperatorAdminID: 9001, + Status: userservice.AdminUserBanStatusReleased, Reason: "manual-release", RequestID: "manual-release", NowMs: 2_100, + }) + if err != nil { + t.Fatalf("release legacy overlay failed: %v", err) + } + if release.Restored || release.User.Status != userdomain.StatusBanned { + t.Fatalf("legacy ban must remain permanent after overlay release: %+v", release) + } +} + +func TestManagerAndAdminBanOverlapRestoresOnlyAfterBothSourcesRelease(t *testing.T) { + repo := mysqltest.NewRepository(t) + ctx := appcode.WithContext(context.Background(), "lalu") + createAdminBanTestUser(t, repo, 18004, "188004", userdomain.StatusActive) + storage := repo.Repository.UserRepository() + target, err := storage.GetUser(ctx, 18004) + if err != nil { + t.Fatalf("get manager block target failed: %v", err) + } + managerBlock, err := storage.CreateManagerUserBlock(ctx, userservice.ManagerUserBlockCommand{ + CommandID: "manager-block", ManagerUserID: 7001, TargetUserID: 18004, + BlockedUntilMS: 8_000, Reason: "manager", RequestID: "manager-block", NowMS: 3_000, + }, target) + if err != nil { + t.Fatalf("create manager block fact failed: %v", err) + } + if _, err := storage.SetUserStatus(ctx, userservice.UserStatusCommand{ + AppCode: "lalu", TargetUserID: 18004, Status: userdomain.StatusBanned, + OperatorType: userservice.OperatorTypeAppUser, OperatorUserID: 7001, + Reason: "manager_center_block:" + managerBlock.BlockID, RequestID: "manager-block", NowMs: 3_000, + }); err != nil { + t.Fatalf("apply manager block status failed: %v", err) + } + adminBan, err := storage.CreateAdminUserBan(ctx, userservice.AdminUserBanCommand{ + CommandID: "admin-over-manager", TargetUserID: 18004, ExpiresAtMs: 9_000, + OperatorAdminID: 9001, Reason: "admin", RequestID: "admin-over-manager", NowMs: 3_100, + }) + if err != nil { + t.Fatalf("create admin overlap failed: %v", err) + } + + managerRelease, err := storage.ReleaseManagerUserBlock(ctx, userservice.ReleaseManagerUserBlockCommand{ + ManagerUserID: 7001, BlockID: managerBlock.BlockID, Status: userservice.ManagerUserBlockStatusReleased, + Reason: "manager-release", RequestID: "manager-release", NowMS: 3_200, + }) + if err != nil { + t.Fatalf("release manager block failed: %v", err) + } + if managerRelease.ShouldRestore || managerRelease.User.Status != userdomain.StatusBanned { + t.Fatalf("active admin ban must prevent manager release from restoring user: %+v", managerRelease) + } + + adminRelease, err := storage.ReleaseAdminUserBan(ctx, userservice.ReleaseAdminUserBanCommand{ + BanID: adminBan.Ban.BanID, TargetUserID: 18004, OperatorAdminID: 9001, + Status: userservice.AdminUserBanStatusReleased, Reason: "admin-release", RequestID: "admin-release", NowMs: 3_300, + }) + if err != nil { + t.Fatalf("release admin block failed: %v", err) + } + if !adminRelease.Restored || adminRelease.User.Status != userdomain.StatusActive { + t.Fatalf("last manager/admin source release must restore user: %+v", adminRelease) + } +} + +func TestExpireAdminUserBansSkipsPermanentAndRestoresTimedBan(t *testing.T) { + repo := mysqltest.NewRepository(t) + ctx := appcode.WithContext(context.Background(), "lalu") + createAdminBanTestUser(t, repo, 18005, "188005", userdomain.StatusActive) + createAdminBanTestUser(t, repo, 18006, "188006", userdomain.StatusActive) + storage := repo.Repository.UserRepository() + if _, err := storage.CreateAdminUserBan(ctx, userservice.AdminUserBanCommand{ + CommandID: "permanent-ban", TargetUserID: 18005, ExpiresAtMs: 0, + OperatorAdminID: 9001, RequestID: "permanent-ban", NowMs: 4_000, + }); err != nil { + t.Fatalf("create permanent ban failed: %v", err) + } + if _, err := storage.CreateAdminUserBan(ctx, userservice.AdminUserBanCommand{ + CommandID: "timed-ban", TargetUserID: 18006, ExpiresAtMs: 4_500, + OperatorAdminID: 9001, RequestID: "timed-ban", NowMs: 4_000, + }); err != nil { + t.Fatalf("create timed ban failed: %v", err) + } + + releases, err := storage.ExpireAdminUserBans(ctx, 5_000, 100) + if err != nil { + t.Fatalf("expire timed bans failed: %v", err) + } + if len(releases) != 1 || releases[0].Ban.TargetUserID != 18006 || !releases[0].Restored { + t.Fatalf("expiry must release only timed ban: %+v", releases) + } + permanentUser, err := storage.GetUser(ctx, 18005) + if err != nil || permanentUser.Status != userdomain.StatusBanned { + t.Fatalf("permanent ban must remain banned: user=%+v err=%v", permanentUser, err) + } +} + +func TestBatchGetUserAdminProfilesUsesSuccessfulLoginAndActiveRoles(t *testing.T) { + repo := mysqltest.NewRepository(t) + ctx := appcode.WithContext(context.Background(), "lalu") + createAdminBanTestUser(t, repo, 18003, "188003", userdomain.StatusActive) + db := repo.RawDB() + if _, err := db.Exec(`UPDATE users SET birth_date = '2000-02-03', register_device = 'Pixel 9' WHERE app_code = 'lalu' AND user_id = 18003`); err != nil { + t.Fatalf("seed admin profile user fields failed: %v", err) + } + if _, err := db.Exec(` + INSERT INTO login_audit (app_code, request_id, user_id, login_type, channel, platform, result, blocked, block_reason, created_at_ms) + VALUES ('lalu', 'success-login', 18003, 'password', 'account', 'android', 'success', 0, '', 3000), + ('lalu', 'failed-login', 18003, 'password', 'account', 'android', 'failed', 0, '', 4000)`); err != nil { + t.Fatalf("seed admin profile login facts failed: %v", err) + } + if _, err := db.Exec(` + INSERT INTO host_profiles (app_code, user_id, status, current_agency_id, current_membership_id, source, first_became_host_at_ms, created_at_ms, updated_at_ms) + VALUES ('lalu', 18003, 'active', NULL, NULL, 'admin_add_host', 3000, 3000, 3000)`); err != nil { + t.Fatalf("seed admin profile host role failed: %v", err) + } + if _, err := db.Exec(` + INSERT INTO manager_profiles (app_code, user_id, status, contact_info, created_by_admin_id, created_at_ms, updated_at_ms) + VALUES ('lalu', 18003, 'active', '', 9001, 3000, 3000)`); err != nil { + t.Fatalf("seed admin profile manager role failed: %v", err) + } + + profiles, err := repo.Repository.UserRepository().BatchGetUserAdminProfiles(ctx, []int64{18003}, 5_000) + if err != nil { + t.Fatalf("batch admin profile failed: %v", err) + } + profile := profiles[18003] + if profile.BirthDate != "2000-02-03" || profile.RegisterDevice != "Pixel 9" || profile.LastSuccessLoginAtMs != 3_000 { + t.Fatalf("admin profile base/login facts mismatch: %+v", profile) + } + if len(profile.Roles) != 2 || profile.Roles[0] != userdomain.AdminRoleHost || profile.Roles[1] != userdomain.AdminRoleManager { + t.Fatalf("admin profile roles mismatch: %+v", profile.Roles) + } +} + +func createAdminBanTestUser(t *testing.T, repo *mysqltest.Repository, userID int64, displayUserID string, status userdomain.Status) { + t.Helper() + err := repo.CreateUserWithIdentity(appcode.WithContext(context.Background(), "lalu"), userdomain.User{ + AppCode: "lalu", + UserID: userID, + DefaultDisplayUserID: displayUserID, + CurrentDisplayUserID: displayUserID, + CurrentDisplayUserIDKind: userdomain.DisplayUserIDKindDefault, + Username: "admin-ban-user", + Status: status, + CreatedAtMs: 100, + UpdatedAtMs: 100, + }, userdomain.Identity{ + AppCode: "lalu", + UserID: userID, + DisplayUserID: displayUserID, + DefaultDisplayUserID: displayUserID, + DisplayUserIDKind: userdomain.DisplayUserIDKindDefault, + Status: userdomain.DisplayUserIDStatusActive, + }) + if err != nil { + t.Fatalf("create admin ban test user failed: %v", err) + } +} diff --git a/services/user-service/internal/storage/mysql/user/admin_profile.go b/services/user-service/internal/storage/mysql/user/admin_profile.go new file mode 100644 index 00000000..74438035 --- /dev/null +++ b/services/user-service/internal/storage/mysql/user/admin_profile.go @@ -0,0 +1,252 @@ +package user + +import ( + "context" + "fmt" + "strings" + + "hyapp/pkg/appcode" + userdomain "hyapp/services/user-service/internal/domain/user" +) + +// BatchGetUserAdminProfiles 聚合 user-service 同库内的用户、登录、角色和封禁事实。 +// 该查询不读取 wallet/activity 等 owner 数据;admin-server 会分别批量读取并组装最终 DTO。 +func (r *Repository) BatchGetUserAdminProfiles(ctx context.Context, userIDs []int64, _ int64) (map[int64]userdomain.AdminProfile, error) { + users, err := r.BatchGetUsers(ctx, userIDs) + if err != nil { + return nil, err + } + profiles := make(map[int64]userdomain.AdminProfile, len(users)) + for userID, item := range users { + profiles[userID] = userdomain.AdminProfile{ + User: item, + BirthDate: item.BirthDate, + RegisterDevice: item.RegisterDevice, + Roles: make([]string, 0, 6), + } + } + if len(profiles) == 0 { + return profiles, nil + } + + placeholders, idArgs := adminProfileIDArgs(userIDs) + if err := r.hydrateAdminLastSuccessLogin(ctx, profiles, placeholders, idArgs); err != nil { + return nil, err + } + if err := r.hydrateAdminRoles(ctx, profiles, placeholders, idArgs); err != nil { + return nil, err + } + if err := r.hydrateAdminLastOperations(ctx, profiles, placeholders, idArgs); err != nil { + return nil, err + } + if err := r.hydrateAdminBanSummaries(ctx, profiles, placeholders, idArgs); err != nil { + return nil, err + } + return profiles, nil +} + +func (r *Repository) hydrateAdminLastSuccessLogin(ctx context.Context, profiles map[int64]userdomain.AdminProfile, placeholders string, idArgs []any) error { + args := append([]any{appcode.FromContext(ctx)}, idArgs...) + rows, err := r.db.QueryContext(ctx, fmt.Sprintf(` + SELECT user_id, MAX(created_at_ms) + FROM login_audit + WHERE app_code = ? AND result = 'success' AND user_id IN (%s) + GROUP BY user_id`, placeholders), args...) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + var userID, loggedInAtMs int64 + if err := rows.Scan(&userID, &loggedInAtMs); err != nil { + return err + } + profile, ok := profiles[userID] + if ok { + profile.LastSuccessLoginAtMs = loggedInAtMs + profiles[userID] = profile + } + } + return rows.Err() +} + +func (r *Repository) hydrateAdminRoles(ctx context.Context, profiles map[int64]userdomain.AdminProfile, placeholders string, idArgs []any) error { + args := append([]any{appcode.FromContext(ctx)}, idArgs...) + rows, err := r.db.QueryContext(ctx, fmt.Sprintf(` + SELECT u.user_id, + EXISTS(SELECT 1 FROM host_profiles h WHERE h.app_code = u.app_code AND h.user_id = u.user_id AND h.status = 'active'), + EXISTS(SELECT 1 FROM agencies a WHERE a.app_code = u.app_code AND a.active_owner_user_id = u.user_id), + EXISTS(SELECT 1 FROM bd_profiles b WHERE b.app_code = u.app_code AND b.user_id = u.user_id AND b.status = 'active'), + EXISTS(SELECT 1 FROM bd_leader_profiles bl WHERE bl.app_code = u.app_code AND bl.user_id = u.user_id AND bl.status = 'active'), + EXISTS(SELECT 1 FROM coin_seller_profiles c WHERE c.app_code = u.app_code AND c.user_id = u.user_id AND c.status = 'active'), + EXISTS(SELECT 1 FROM manager_profiles m WHERE m.app_code = u.app_code AND m.user_id = u.user_id AND m.status = 'active') + FROM users u + WHERE u.app_code = ? AND u.user_id IN (%s)`, placeholders), args...) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + var userID int64 + var host, agency, bd, bdLeader, coinSeller, manager bool + if err := rows.Scan(&userID, &host, &agency, &bd, &bdLeader, &coinSeller, &manager); err != nil { + return err + } + profile, ok := profiles[userID] + if !ok { + continue + } + // 固定顺序让 CSV、列表和详情在相同事实下始终产生一致展示,避免 map/set 顺序漂移。 + profile.Roles = appendAdminRole(profile.Roles, host, userdomain.AdminRoleHost) + profile.Roles = appendAdminRole(profile.Roles, agency, userdomain.AdminRoleAgency) + profile.Roles = appendAdminRole(profile.Roles, bd, userdomain.AdminRoleBD) + profile.Roles = appendAdminRole(profile.Roles, bdLeader, userdomain.AdminRoleBDLeader) + profile.Roles = appendAdminRole(profile.Roles, coinSeller, userdomain.AdminRoleCoinSeller) + profile.Roles = appendAdminRole(profile.Roles, manager, userdomain.AdminRoleManager) + profiles[userID] = profile + } + return rows.Err() +} + +func (r *Repository) hydrateAdminLastOperations(ctx context.Context, profiles map[int64]userdomain.AdminProfile, placeholders string, idArgs []any) error { + args := make([]any, 0, len(idArgs)+2) + args = append(args, appcode.FromContext(ctx)) + args = append(args, idArgs...) + args = append(args, appcode.FromContext(ctx)) + rows, err := r.db.QueryContext(ctx, fmt.Sprintf(` + SELECT log.target_user_id, log.operator_type, log.operator_user_id, log.reason, log.created_at_ms + FROM user_status_change_logs log + INNER JOIN ( + SELECT target_user_id, MAX(id) AS latest_id + FROM user_status_change_logs + WHERE app_code = ? AND target_user_id IN (%s) + GROUP BY target_user_id + ) latest ON latest.latest_id = log.id + WHERE log.app_code = ?`, placeholders), args...) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + var userID, operatorUserID, operatedAtMs int64 + var operatorType, reason string + if err := rows.Scan(&userID, &operatorType, &operatorUserID, &reason, &operatedAtMs); err != nil { + return err + } + profile, ok := profiles[userID] + if ok { + profile.LastOperatorType = operatorType + profile.LastOperatorUserID = operatorUserID + profile.LastOperationReason = reason + profile.LastOperationAtMs = operatedAtMs + profiles[userID] = profile + } + } + return rows.Err() +} + +func (r *Repository) hydrateAdminBanSummaries(ctx context.Context, profiles map[int64]userdomain.AdminProfile, placeholders string, idArgs []any) error { + args := make([]any, 0, len(idArgs)*2+2) + args = append(args, appcode.FromContext(ctx)) + args = append(args, idArgs...) + args = append(args, appcode.FromContext(ctx)) + args = append(args, idArgs...) + rows, err := r.db.QueryContext(ctx, fmt.Sprintf(` + SELECT 'admin', ban_id, target_user_id, expires_at_ms, operator_admin_id, reason, created_at_ms + FROM admin_user_bans + WHERE app_code = ? AND status = 'active' AND target_user_id IN (%s) + UNION ALL + SELECT 'manager', block_id, target_user_id, blocked_until_ms, manager_user_id, reason, created_at_ms + FROM manager_user_blocks + WHERE app_code = ? AND status = 'active' AND target_user_id IN (%s)`, placeholders, placeholders), args...) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + var source, banID, reason string + var targetUserID, expiresAtMs, operatorUserID, createdAtMs int64 + if err := rows.Scan(&source, &banID, &targetUserID, &expiresAtMs, &operatorUserID, &reason, &createdAtMs); err != nil { + return err + } + profile, ok := profiles[targetUserID] + if !ok { + continue + } + profile.Ban = mergeActiveBan(profile.Ban, userdomain.ActiveBanSummary{ + Active: true, + Source: source, + BanID: banID, + Permanent: expiresAtMs == 0, + ExpiresAtMs: expiresAtMs, + UserStatus: profile.User.Status, + OperatorType: source, + OperatorUserID: operatorUserID, + Reason: reason, + CreatedAtMs: createdAtMs, + ActiveBanCount: 1, + }) + profiles[targetUserID] = profile + } + if err := rows.Err(); err != nil { + return err + } + + for userID, profile := range profiles { + if profile.Ban.Active || (profile.User.Status != userdomain.StatusBanned && profile.User.Status != userdomain.StatusDisabled) { + continue + } + // 历史 banned/disabled 没有新事实表记录时一律视为永久;cron 绝不能仅凭时间猜测并恢复这些账号。 + profile.Ban = userdomain.ActiveBanSummary{ + Active: true, + Source: userdomain.BanSourceLegacy, + Permanent: true, + UserStatus: profile.User.Status, + OperatorType: profile.LastOperatorType, + OperatorUserID: profile.LastOperatorUserID, + Reason: profile.LastOperationReason, + CreatedAtMs: profile.LastOperationAtMs, + ActiveBanCount: 1, + } + profiles[userID] = profile + } + return nil +} + +func adminProfileIDArgs(userIDs []int64) (string, []any) { + placeholders := make([]string, 0, len(userIDs)) + args := make([]any, 0, len(userIDs)) + for _, userID := range userIDs { + placeholders = append(placeholders, "?") + args = append(args, userID) + } + return strings.Join(placeholders, ","), args +} + +func appendAdminRole(roles []string, active bool, role string) []string { + if active { + return append(roles, role) + } + return roles +} + +func mergeActiveBan(current userdomain.ActiveBanSummary, candidate userdomain.ActiveBanSummary) userdomain.ActiveBanSummary { + if !current.Active { + return candidate + } + current.ActiveBanCount += candidate.ActiveBanCount + // 任一永久封禁都会让聚合视图永久;多个永久事实取最新一条作为可操作 ban_id 和审计展示。 + if candidate.Permanent && (!current.Permanent || candidate.CreatedAtMs > current.CreatedAtMs) { + candidate.ActiveBanCount = current.ActiveBanCount + return candidate + } + if current.Permanent { + return current + } + // 全部是限时事实时,账号只有在最晚一条也到期后才能恢复,因此摘要展示最晚截止时间。 + if candidate.ExpiresAtMs > current.ExpiresAtMs || (candidate.ExpiresAtMs == current.ExpiresAtMs && candidate.CreatedAtMs > current.CreatedAtMs) { + candidate.ActiveBanCount = current.ActiveBanCount + return candidate + } + return current +} diff --git a/services/user-service/internal/storage/mysql/user/admin_profile_test.go b/services/user-service/internal/storage/mysql/user/admin_profile_test.go new file mode 100644 index 00000000..553db376 --- /dev/null +++ b/services/user-service/internal/storage/mysql/user/admin_profile_test.go @@ -0,0 +1,47 @@ +package user + +import ( + "reflect" + "testing" + + userdomain "hyapp/services/user-service/internal/domain/user" +) + +func TestMergeActiveBanUsesPermanentFactAndPreservesCount(t *testing.T) { + finite := userdomain.ActiveBanSummary{ + Active: true, Source: userdomain.BanSourceManager, BanID: "manager-1", + ExpiresAtMs: 2_000, CreatedAtMs: 100, ActiveBanCount: 1, + } + permanent := userdomain.ActiveBanSummary{ + Active: true, Source: userdomain.BanSourceAdmin, BanID: "admin-1", + Permanent: true, CreatedAtMs: 200, ActiveBanCount: 1, + } + + merged := mergeActiveBan(finite, permanent) + if !merged.Permanent || merged.BanID != "admin-1" || merged.ActiveBanCount != 2 { + t.Fatalf("permanent ban must govern aggregate: %+v", merged) + } +} + +func TestMergeActiveBanUsesLatestFiniteExpiry(t *testing.T) { + first := userdomain.ActiveBanSummary{Active: true, BanID: "first", ExpiresAtMs: 3_000, CreatedAtMs: 100, ActiveBanCount: 1} + second := userdomain.ActiveBanSummary{Active: true, BanID: "second", ExpiresAtMs: 5_000, CreatedAtMs: 50, ActiveBanCount: 1} + + merged := mergeActiveBan(first, second) + if merged.BanID != "second" || merged.ExpiresAtMs != 5_000 || merged.ActiveBanCount != 2 { + t.Fatalf("latest finite expiry must govern aggregate: %+v", merged) + } +} + +func TestAppendAdminRoleKeepsStableDisplayOrder(t *testing.T) { + roles := make([]string, 0, 6) + roles = appendAdminRole(roles, true, userdomain.AdminRoleHost) + roles = appendAdminRole(roles, true, userdomain.AdminRoleAgency) + roles = appendAdminRole(roles, false, userdomain.AdminRoleBD) + roles = appendAdminRole(roles, true, userdomain.AdminRoleManager) + + want := []string{userdomain.AdminRoleHost, userdomain.AdminRoleAgency, userdomain.AdminRoleManager} + if !reflect.DeepEqual(roles, want) { + t.Fatalf("role order mismatch: got=%v want=%v", roles, want) + } +} diff --git a/services/user-service/internal/storage/mysql/user/moderation.go b/services/user-service/internal/storage/mysql/user/moderation.go index 8c69e19d..8b44c166 100644 --- a/services/user-service/internal/storage/mysql/user/moderation.go +++ b/services/user-service/internal/storage/mysql/user/moderation.go @@ -41,6 +41,16 @@ func (r *Repository) SetUserStatus(ctx context.Context, command userservice.User } return userservice.UserStatusPersistenceResult{}, err } + if command.Status == userdomain.StatusActive { + activeBanCount, err := countActiveManagedBans(ctx, tx, command.TargetUserID) + if err != nil { + return userservice.UserStatusPersistenceResult{}, err + } + if activeBanCount > 0 { + // 所有恢复入口都必须尊重 admin/manager 独立封禁事实;不能通过旧 SetUserStatus(active) 绕过新状态机。 + return userservice.UserStatusPersistenceResult{}, xerr.New(xerr.Conflict, "user still has active ban facts") + } + } _, err = tx.ExecContext(ctx, ` UPDATE users @@ -163,7 +173,7 @@ func (r *Repository) ListManagerUserBlocks(ctx context.Context, managerUserID in } func (r *Repository) ReleaseManagerUserBlock(ctx context.Context, command userservice.ReleaseManagerUserBlockCommand) (userservice.ManagerUserBlockRelease, error) { - return r.releaseManagerUserBlock(ctx, command.BlockID, command.ManagerUserID, command.Status, command.Reason, command.NowMS) + return r.releaseManagerUserBlock(ctx, command.BlockID, command.ManagerUserID, command.Status, command.Reason, command.RequestID, command.NowMS) } func (r *Repository) ExpireManagerUserBlocks(ctx context.Context, nowMS int64, limit int32) ([]userservice.ManagerUserBlockRelease, error) { @@ -202,7 +212,7 @@ func (r *Repository) ExpireManagerUserBlocks(ctx context.Context, nowMS int64, l releases := make([]userservice.ManagerUserBlockRelease, 0, len(pending)) for _, item := range pending { // 逐条释放而不是批量 UPDATE,是为了给每个目标用户单独计算是否还存在其他 active 经理封禁。 - release, err := r.releaseManagerUserBlock(ctx, item.blockID, item.managerUserID, userservice.ManagerUserBlockStatusExpired, "manager_center_block_expired", nowMS) + release, err := r.releaseManagerUserBlock(ctx, item.blockID, item.managerUserID, userservice.ManagerUserBlockStatusExpired, "manager_center_block_expired", "manager_block_expire:"+item.blockID, nowMS) if err != nil { return releases, err } @@ -211,7 +221,7 @@ func (r *Repository) ExpireManagerUserBlocks(ctx context.Context, nowMS int64, l return releases, nil } -func (r *Repository) releaseManagerUserBlock(ctx context.Context, blockID string, managerUserID int64, status string, reason string, nowMS int64) (userservice.ManagerUserBlockRelease, error) { +func (r *Repository) releaseManagerUserBlock(ctx context.Context, blockID string, managerUserID int64, status string, reason string, requestID string, nowMS int64) (userservice.ManagerUserBlockRelease, error) { tx, err := r.db.BeginTx(ctx, nil) if err != nil { return userservice.ManagerUserBlockRelease{}, err @@ -225,7 +235,12 @@ func (r *Repository) releaseManagerUserBlock(ctx context.Context, blockID string if err := tx.Commit(); err != nil { return userservice.ManagerUserBlockRelease{}, err } - return userservice.ManagerUserBlockRelease{Block: block}, nil + user, err := r.GetUser(ctx, block.TargetUserID) + return userservice.ManagerUserBlockRelease{Block: block, User: user}, err + } + currentStatus, err := lockUserStatus(ctx, tx, appcode.FromContext(ctx), block.TargetUserID) + if err != nil { + return userservice.ManagerUserBlockRelease{}, err } _, err = tx.ExecContext(ctx, ` UPDATE manager_user_blocks @@ -238,21 +253,29 @@ func (r *Repository) releaseManagerUserBlock(ctx context.Context, blockID string } block.Status = status block.UpdatedAtMS = nowMS - activeCount, err := r.countActiveManagerBlocks(ctx, tx, block.TargetUserID) - if err != nil { - return userservice.ManagerUserBlockRelease{}, err - } - // 只在“没有其他经理封禁 + 原状态是 active + 最近一次 ban 由经理封禁写入”时恢复,避免误解后台封禁。 - latestManagerBan, err := r.latestBanBelongsToManagerBlock(ctx, tx, block.TargetUserID) + restored, err := restoreUserAfterManagedBanRelease(ctx, tx, managedBanRestoreCommand{ + TargetUserID: block.TargetUserID, + CurrentStatus: currentStatus, + OperatorType: managerReleaseOperatorType(status), + OperatorID: managerUserID, + Reason: managerReleaseStatusReason(status, block.BlockID), + RequestID: requestID, + NowMs: nowMS, + }) if err != nil { return userservice.ManagerUserBlockRelease{}, err } if err := tx.Commit(); err != nil { return userservice.ManagerUserBlockRelease{}, err } + user, err := r.GetUser(ctx, block.TargetUserID) + if err != nil { + return userservice.ManagerUserBlockRelease{}, err + } return userservice.ManagerUserBlockRelease{ Block: block, - ShouldRestore: activeCount == 0 && block.TargetOldStatus == userdomain.StatusActive && latestManagerBan, + User: user, + ShouldRestore: restored, }, nil } @@ -275,34 +298,18 @@ func (r *Repository) getManagerUserBlockForUpdate(ctx context.Context, tx *sql.T return scanManagerUserBlock(row) } -func (r *Repository) countActiveManagerBlocks(ctx context.Context, tx *sql.Tx, targetUserID int64) (int64, error) { - var count int64 - err := tx.QueryRowContext(ctx, ` - SELECT COUNT(*) - FROM manager_user_blocks - WHERE app_code = ? AND target_user_id = ? AND status = 'active'`, - appcode.FromContext(ctx), targetUserID, - ).Scan(&count) - return count, err +func managerReleaseOperatorType(status string) string { + if status == userservice.ManagerUserBlockStatusExpired { + return userservice.OperatorTypeSystem + } + return userservice.OperatorTypeAppUser } -func (r *Repository) latestBanBelongsToManagerBlock(ctx context.Context, tx *sql.Tx, targetUserID int64) (bool, error) { - var reason string - err := tx.QueryRowContext(ctx, ` - SELECT reason - FROM user_status_change_logs - WHERE app_code = ? AND target_user_id = ? AND new_status = 'banned' - ORDER BY created_at_ms DESC, id DESC - LIMIT 1`, - appcode.FromContext(ctx), targetUserID, - ).Scan(&reason) - if errors.Is(err, sql.ErrNoRows) { - return false, nil +func managerReleaseStatusReason(status string, blockID string) string { + if status == userservice.ManagerUserBlockStatusExpired { + return "manager_center_block_expired:" + blockID } - if err != nil { - return false, err - } - return strings.HasPrefix(reason, "manager_center_block:"), nil + return "manager_center_unblock:" + blockID } func managerBlockSelectSQL() string { diff --git a/services/user-service/internal/testutil/mysqltest/mysqltest.go b/services/user-service/internal/testutil/mysqltest/mysqltest.go index 8d1864ca..eeae803f 100644 --- a/services/user-service/internal/testutil/mysqltest/mysqltest.go +++ b/services/user-service/internal/testutil/mysqltest/mysqltest.go @@ -129,6 +129,11 @@ func (r *Repository) BatchGetUsers(ctx context.Context, userIDs []int64) (map[in return r.Repository.UserRepository().BatchGetUsers(ctx, userIDs) } +// BatchGetUserAdminProfiles 让跨包 MySQL 测试继续复用真实后台投影查询。 +func (r *Repository) BatchGetUserAdminProfiles(ctx context.Context, userIDs []int64, nowMs int64) (map[int64]userdomain.AdminProfile, error) { + return r.Repository.UserRepository().BatchGetUserAdminProfiles(ctx, userIDs, nowMs) +} + // BatchGetRoomBasicUsers 让测试 wrapper 继续满足房间首屏基础资料查询接口。 func (r *Repository) BatchGetRoomBasicUsers(ctx context.Context, userIDs []int64) (map[int64]userdomain.RoomBasicUser, error) { return r.Repository.UserRepository().BatchGetRoomBasicUsers(ctx, userIDs) diff --git a/services/user-service/internal/transport/grpc/admin_convert_test.go b/services/user-service/internal/transport/grpc/admin_convert_test.go new file mode 100644 index 00000000..4c27ebd8 --- /dev/null +++ b/services/user-service/internal/transport/grpc/admin_convert_test.go @@ -0,0 +1,63 @@ +package grpc + +import ( + "reflect" + "testing" + + hostdomain "hyapp/services/user-service/internal/domain/host" + userdomain "hyapp/services/user-service/internal/domain/user" + userservice "hyapp/services/user-service/internal/service/user" +) + +func TestToProtoUserAdminProfilePreservesOwnerFacts(t *testing.T) { + profile := userdomain.AdminProfile{ + User: userdomain.User{UserID: 10001, Status: userdomain.StatusBanned}, + BirthDate: "2000-02-03", + RegisterDevice: "Pixel 9", + LastSuccessLoginAtMs: 4_000, + Roles: []string{userdomain.AdminRoleHost, userdomain.AdminRoleManager}, + Ban: userdomain.ActiveBanSummary{ + Active: true, Source: userdomain.BanSourceAdmin, BanID: "admin-ban-1", + Permanent: true, UserStatus: userdomain.StatusBanned, OperatorType: "admin", + OperatorUserID: 9001, ActiveBanCount: 2, + }, + LastOperatorType: "admin", + LastOperatorUserID: 9001, + LastOperationReason: "admin_user_ban:admin-ban-1", + LastOperationAtMs: 4_000, + } + + got := toProtoUserAdminProfile(profile) + if got.GetUser().GetUserId() != 10001 || got.GetBirth() != profile.BirthDate || got.GetRegisterDevice() != profile.RegisterDevice { + t.Fatalf("admin profile base projection mismatch: %+v", got) + } + if !reflect.DeepEqual(got.GetRoles(), profile.Roles) || !got.GetBan().GetPermanent() || got.GetBan().GetActiveBanCount() != 2 { + t.Fatalf("admin profile role/ban projection mismatch: %+v", got) + } +} + +func TestToProtoAdminUserBanMarksZeroExpiryPermanent(t *testing.T) { + got := toProtoAdminUserBan(userservice.AdminUserBan{ + BanID: "admin-ban-1", TargetUserID: 10001, ExpiresAtMs: 0, Status: userservice.AdminUserBanStatusActive, + }) + if got == nil || !got.GetPermanent() || got.GetExpiresAtMs() != 0 { + t.Fatalf("zero expiry must be exposed as permanent: %+v", got) + } +} + +func TestRoleNamesFromSummaryKeepsStableMultiRoleOrder(t *testing.T) { + roles := roleNamesFromSummary(hostdomain.UserRoleSummary{ + IsHost: true, IsAgency: true, IsBD: true, IsBDLeader: true, IsCoinSeller: true, IsManager: true, + }) + want := []string{ + userdomain.AdminRoleHost, + userdomain.AdminRoleAgency, + userdomain.AdminRoleBD, + userdomain.AdminRoleBDLeader, + userdomain.AdminRoleCoinSeller, + userdomain.AdminRoleManager, + } + if !reflect.DeepEqual(roles, want) { + t.Fatalf("role order mismatch: got=%v want=%v", roles, want) + } +} diff --git a/services/user-service/internal/transport/grpc/convert.go b/services/user-service/internal/transport/grpc/convert.go index 3b534d04..b567ab40 100644 --- a/services/user-service/internal/transport/grpc/convert.go +++ b/services/user-service/internal/transport/grpc/convert.go @@ -126,6 +126,61 @@ func toProtoManagerUserBlock(block userservice.ManagerUserBlock) *userv1.Manager } } +func toProtoAdminUserBan(ban userservice.AdminUserBan) *userv1.AdminUserBan { + if ban.BanID == "" { + return nil + } + return &userv1.AdminUserBan{ + BanId: ban.BanID, + CommandId: ban.CommandID, + TargetUserId: ban.TargetUserID, + ExpiresAtMs: ban.ExpiresAtMs, + Permanent: ban.ExpiresAtMs == 0, + Status: ban.Status, + Reason: ban.Reason, + OperatorAdminId: ban.OperatorAdminID, + CreatedAtMs: ban.CreatedAtMs, + UpdatedAtMs: ban.UpdatedAtMs, + ReleasedByAdminId: ban.ReleasedByAdminID, + ReleasedReason: ban.ReleasedReason, + ReleasedAtMs: ban.ReleasedAtMs, + } +} + +func toProtoUserAdminProfile(profile userdomain.AdminProfile) *userv1.UserAdminProfile { + return &userv1.UserAdminProfile{ + User: toProtoUser(profile.User), + Birth: profile.BirthDate, + RegisterDevice: profile.RegisterDevice, + LastSuccessLoginAtMs: profile.LastSuccessLoginAtMs, + Roles: append([]string(nil), profile.Roles...), + Ban: toProtoActiveUserBanSummary(profile.Ban), + LastOperatorType: profile.LastOperatorType, + LastOperatorUserId: profile.LastOperatorUserID, + LastOperationReason: profile.LastOperationReason, + LastOperationAtMs: profile.LastOperationAtMs, + } +} + +func toProtoActiveUserBanSummary(summary userdomain.ActiveBanSummary) *userv1.ActiveUserBanSummary { + if !summary.Active { + return nil + } + return &userv1.ActiveUserBanSummary{ + Active: true, + Source: summary.Source, + BanId: summary.BanID, + Permanent: summary.Permanent, + ExpiresAtMs: summary.ExpiresAtMs, + UserStatus: toProtoStatus(summary.UserStatus), + OperatorType: summary.OperatorType, + OperatorUserId: summary.OperatorUserID, + Reason: summary.Reason, + CreatedAtMs: summary.CreatedAtMs, + ActiveBanCount: summary.ActiveBanCount, + } +} + func toProtoInviteOverview(overview invitedomain.Overview) *userv1.InviteOverview { if overview.MyInviteCode == "" && !overview.InviteEnabled && overview.InviteCount == 0 && overview.ValidInviteCount == 0 && overview.ValidInviteThresholdCoin == 0 { return nil @@ -553,9 +608,33 @@ func toProtoUserRoleSummary(summary hostdomain.UserRoleSummary) *userv1.UserRole BdStatus: summary.BDStatus, CoinSellerStatus: summary.CoinSellerStatus, PendingRoleInvitations: summary.PendingRoleInvitations, + Roles: roleNamesFromSummary(summary), } } +func roleNamesFromSummary(summary hostdomain.UserRoleSummary) []string { + roles := make([]string, 0, 6) + if summary.IsHost { + roles = append(roles, userdomain.AdminRoleHost) + } + if summary.IsAgency { + roles = append(roles, userdomain.AdminRoleAgency) + } + if summary.IsBD { + roles = append(roles, userdomain.AdminRoleBD) + } + if summary.IsBDLeader { + roles = append(roles, userdomain.AdminRoleBDLeader) + } + if summary.IsCoinSeller { + roles = append(roles, userdomain.AdminRoleCoinSeller) + } + if summary.IsManager { + roles = append(roles, userdomain.AdminRoleManager) + } + return roles +} + // toProtoAgencyMembership 把 Agency membership 事实转换为内部 gRPC 投影。 func toProtoAgencyMembership(membership hostdomain.AgencyMembership) *userv1.AgencyMembership { if membership.MembershipID == 0 { diff --git a/services/user-service/internal/transport/grpc/cron.go b/services/user-service/internal/transport/grpc/cron.go index 0aac7845..c6d8a721 100644 --- a/services/user-service/internal/transport/grpc/cron.go +++ b/services/user-service/internal/transport/grpc/cron.go @@ -9,6 +9,7 @@ import ( userdomain "hyapp/services/user-service/internal/domain/user" authservice "hyapp/services/user-service/internal/service/auth" mictimeservice "hyapp/services/user-service/internal/service/mictime" + roomtimeservice "hyapp/services/user-service/internal/service/roomtime" userservice "hyapp/services/user-service/internal/service/user" ) @@ -82,6 +83,28 @@ func (s *Server) CompensateMicOpenSessions(ctx context.Context, req *userv1.Cron }, nil } +// CompensateRoomOpenSessions 关闭异常长时间未收到 Left/Kicked 事件的用户在房统计 session,不反写 Room Cell。 +func (s *Server) CompensateRoomOpenSessions(ctx context.Context, req *userv1.CronBatchRequest) (*userv1.CronBatchResponse, error) { + ctx = contextWithApp(ctx, req.GetMeta()) + if s.roomTimeSvc == nil { + return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "room time service is not configured")) + } + result, err := s.roomTimeSvc.ProcessOpenSessionCompensationBatch(ctx, roomtimeservice.CompensationWorkerOptions{ + WorkerID: req.GetWorkerId(), + BatchSize: int(req.GetBatchSize()), + OpenSessionMaxAge: durationFromMillis(req.GetOpenSessionMaxAgeMs()), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &userv1.CronBatchResponse{ + ClaimedCount: int32(result.ClosedCount), + ProcessedCount: int32(result.ClosedCount + result.OrphanLeavesDeleted), + SuccessCount: int32(result.ClosedCount), + HasMore: result.ClosedCount >= normalizedBatchSize(req.GetBatchSize(), 200), + }, nil +} + // ExpireManagerUserBlocks 释放到期的经理封禁记录;真正是否恢复 users.status 由 user-service 内部封禁来源判断。 func (s *Server) ExpireManagerUserBlocks(ctx context.Context, req *userv1.CronBatchRequest) (*userv1.CronBatchResponse, error) { ctx = contextWithApp(ctx, req.GetMeta()) @@ -100,6 +123,24 @@ func (s *Server) ExpireManagerUserBlocks(ctx context.Context, req *userv1.CronBa }, nil } +// ExpireAdminUserBans 释放到期的后台管理员限时封禁;永久封禁和最终恢复判断都由 user-service 持有。 +func (s *Server) ExpireAdminUserBans(ctx context.Context, req *userv1.CronBatchRequest) (*userv1.CronBatchResponse, error) { + ctx = contextWithApp(ctx, req.GetMeta()) + if s.userSvc == nil { + return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "user service is not configured")) + } + processed, err := s.userSvc.ExpireAdminUserBans(ctx, req.GetBatchSize()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &userv1.CronBatchResponse{ + ClaimedCount: int32(processed), + ProcessedCount: int32(processed), + SuccessCount: int32(processed), + HasMore: processed >= normalizedBatchSize(req.GetBatchSize(), 100), + }, nil +} + // RefreshCPIntimacyLeaderboard 重建 CP 亲密值排行榜 Redis zset;cron-service 只负责调度和租约。 func (s *Server) RefreshCPIntimacyLeaderboard(ctx context.Context, req *userv1.CronBatchRequest) (*userv1.CronBatchResponse, error) { // cron-service 每个 app_code 单独触发一次;这里把 app_code 放进 context 后,MySQL 查询和 Redis key 都会按租户隔离。 diff --git a/services/user-service/internal/transport/grpc/host.go b/services/user-service/internal/transport/grpc/host.go index 6c2dbce8..df17b043 100644 --- a/services/user-service/internal/transport/grpc/host.go +++ b/services/user-service/internal/transport/grpc/host.go @@ -104,7 +104,7 @@ func (s *Server) InviteAgency(ctx context.Context, req *userv1.InviteAgencyReque return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) } ctx = contextWithApp(ctx, req.GetMeta()) - // 邀请人的 BD 身份和目标用户的区域/身份冲突都由业务事务校验。 + // 邀请人的 BD 身份、App 级区域策略和目标身份冲突都由业务事务校验。 invitation, err := s.hostSvc.InviteAgency(ctx, hostservice.InviteAgencyInput{ CommandID: req.GetCommandId(), InviterUserID: req.GetInviterUserId(), diff --git a/services/user-service/internal/transport/grpc/server.go b/services/user-service/internal/transport/grpc/server.go index b334646a..0d5bbe37 100644 --- a/services/user-service/internal/transport/grpc/server.go +++ b/services/user-service/internal/transport/grpc/server.go @@ -14,6 +14,7 @@ import ( cpservice "hyapp/services/user-service/internal/service/cp" hostservice "hyapp/services/user-service/internal/service/host" mictimeservice "hyapp/services/user-service/internal/service/mictime" + roomtimeservice "hyapp/services/user-service/internal/service/roomtime" userservice "hyapp/services/user-service/internal/service/user" ) @@ -58,6 +59,8 @@ type Server struct { hostSvc *hostservice.Service // micTimeSvc 承载用户维度麦位在线时长聚合查询。 micTimeSvc *mictimeservice.Service + // roomTimeSvc 承载用户维度在房时长会话补偿。 + roomTimeSvc *roomtimeservice.Service // cpSvc 承载 CP/兄弟/姐妹申请、关系和房间送礼消费用例。 cpSvc *cpservice.Service } @@ -81,6 +84,11 @@ func (s *Server) SetMicTimeService(micTimeSvc *mictimeservice.Service) { s.micTimeSvc = micTimeSvc } +// SetRoomTimeService 挂载可选的在房时长 read model,避免破坏现有测试构造函数签名。 +func (s *Server) SetRoomTimeService(roomTimeSvc *roomtimeservice.Service) { + s.roomTimeSvc = roomTimeSvc +} + // SetCPService 挂载 CP 关系 service,保持 NewServer 老测试构造方式兼容。 func (s *Server) SetCPService(cpSvc *cpservice.Service) { s.cpSvc = cpSvc @@ -457,6 +465,41 @@ func (s *Server) SetUserStatus(ctx context.Context, req *userv1.SetUserStatusReq return toProtoSetUserStatusResponse(result), nil } +// AdminBanUser 创建后台管理员永久或限时封禁;expires_at_ms=0 明确表示永久。 +func (s *Server) AdminBanUser(ctx context.Context, req *userv1.AdminBanUserRequest) (*userv1.AdminBanUserResponse, error) { + ctx = contextWithApp(ctx, req.GetMeta()) + ban, status, err := s.userSvc.AdminBanUser(ctx, userservice.AdminUserBanCommand{ + CommandID: req.GetCommandId(), + TargetUserID: req.GetTargetUserId(), + ExpiresAtMs: req.GetExpiresAtMs(), + OperatorAdminID: req.GetOperatorAdminId(), + Reason: req.GetReason(), + RequestID: req.GetMeta().GetRequestId(), + NowMs: req.GetMeta().GetSentAtMs(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &userv1.AdminBanUserResponse{Ban: toProtoAdminUserBan(ban), Status: toProtoSetUserStatusResponse(status)}, nil +} + +// AdminUnbanUser 释放指定或该用户最新的管理员封禁事实;仍有其他管理员或经理封禁时用户继续保持 banned。 +func (s *Server) AdminUnbanUser(ctx context.Context, req *userv1.AdminUnbanUserRequest) (*userv1.AdminUnbanUserResponse, error) { + ctx = contextWithApp(ctx, req.GetMeta()) + ban, status, err := s.userSvc.AdminUnbanUser(ctx, userservice.ReleaseAdminUserBanCommand{ + BanID: req.GetBanId(), + TargetUserID: req.GetTargetUserId(), + OperatorAdminID: req.GetOperatorAdminId(), + Reason: req.GetReason(), + RequestID: req.GetMeta().GetRequestId(), + NowMs: req.GetMeta().GetSentAtMs(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &userv1.AdminUnbanUserResponse{Ban: toProtoAdminUserBan(ban), Status: toProtoSetUserStatusResponse(status)}, nil +} + // CreateManagerUserBlock 创建经理中心封禁记录,并同步把目标账号置为 banned。 func (s *Server) CreateManagerUserBlock(ctx context.Context, req *userv1.CreateManagerUserBlockRequest) (*userv1.CreateManagerUserBlockResponse, error) { ctx = contextWithApp(ctx, req.GetMeta()) @@ -499,6 +542,7 @@ func (s *Server) UnblockManagerUser(ctx context.Context, req *userv1.UnblockMana BlockID: req.GetBlockId(), ManagerUserID: req.GetManagerUserId(), Reason: req.GetReason(), + RequestID: req.GetMeta().GetRequestId(), NowMS: req.GetMeta().GetSentAtMs(), }) if err != nil { @@ -674,6 +718,20 @@ func (s *Server) BatchGetUsers(ctx context.Context, req *userv1.BatchGetUsersReq return &userv1.BatchGetUsersResponse{Users: result}, nil } +// BatchGetUserAdminProfiles 返回后台列表需要的用户、登录、身份和封禁 owner 事实。 +func (s *Server) BatchGetUserAdminProfiles(ctx context.Context, req *userv1.BatchGetUserAdminProfilesRequest) (*userv1.BatchGetUserAdminProfilesResponse, error) { + ctx = contextWithApp(ctx, req.GetMeta()) + profiles, err := s.userSvc.BatchGetUserAdminProfiles(ctx, req.GetUserIds()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + result := make(map[int64]*userv1.UserAdminProfile, len(profiles)) + for userID, profile := range profiles { + result[userID] = toProtoUserAdminProfile(profile) + } + return &userv1.BatchGetUserAdminProfilesResponse{Profiles: result}, nil +} + // BatchGetRoomBasicUsers 批量返回房间首屏最小用户展示资料。 func (s *Server) BatchGetRoomBasicUsers(ctx context.Context, req *userv1.BatchGetRoomBasicUsersRequest) (*userv1.BatchGetRoomBasicUsersResponse, error) { ctx = contextWithApp(ctx, req.GetMeta()) 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 dc4d2500..cecd19ea 100644 --- a/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql +++ b/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql @@ -1517,6 +1517,27 @@ CREATE TABLE IF NOT EXISTS red_packet_user_daily_counters ( PRIMARY KEY (app_code, user_id, send_day) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='红包用户每日发送计数表'; +-- vip_program_configs 是 VIP 行为的唯一 App 级策略来源。购买、发放和权益查询必须读取该表, +-- 禁止在服务代码中用 app_code 分支复制 Lalu/Fami 两套状态机。 +CREATE TABLE IF NOT EXISTS vip_program_configs ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', + program_type VARCHAR(32) NOT NULL COMMENT '体系类型:legacy_timed/tiered_privilege_v1', + level_count INT NOT NULL COMMENT '该 App 可配置等级数量', + same_level_expiry_policy VARCHAR(32) NOT NULL COMMENT '同级续费有效期策略:extend_remaining', + upgrade_expiry_policy VARCHAR(32) NOT NULL COMMENT '升级有效期策略:extend_remaining/replace_from_now', + downgrade_purchase_policy VARCHAR(32) NOT NULL COMMENT '降级购买策略:reject', + benefit_inheritance_policy VARCHAR(32) NOT NULL COMMENT '权益矩阵策略:当前固定 target_only,每级保存完整集合', + grant_mode VARCHAR(32) NOT NULL COMMENT '后台赠送语义:direct_membership/trial_card', + trial_card_enabled BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否允许体验卡背包和佩戴流程', + status VARCHAR(32) NOT NULL COMMENT '业务状态:active/disabled', + config_version BIGINT NOT NULL DEFAULT 1 COMMENT '配置版本;订单和会员状态持久化该快照版本', + updated_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '最后更新管理员 ID', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code), + KEY idx_vip_program_status (status, updated_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='按 App 配置的 VIP 体系规则'; + CREATE TABLE IF NOT EXISTS vip_levels ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', level INT NOT NULL COMMENT '等级', @@ -1548,6 +1569,8 @@ CREATE TABLE IF NOT EXISTS user_vip_memberships ( level INT NOT NULL COMMENT '等级', name VARCHAR(64) NOT NULL DEFAULT '' COMMENT '名称', status VARCHAR(32) NOT NULL COMMENT '业务状态', + program_type VARCHAR(32) NOT NULL DEFAULT 'legacy_timed' COMMENT '激活时使用的 VIP 体系快照', + config_version BIGINT NOT NULL DEFAULT 1 COMMENT '激活时使用的 VIP 配置版本', started_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '开始时间,UTC epoch ms', expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '过期时间,UTC epoch ms', created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', @@ -1556,6 +1579,36 @@ CREATE TABLE IF NOT EXISTS user_vip_memberships ( KEY idx_user_vip_expiry (app_code, status, expires_at_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户 VIP 成员关系表'; +-- 用户偏好和 VIP 资格分离:没有记录时运行时默认两项开启;首次 PATCH 才物化。 +-- 主键包含 app_code,确保同一 user_id 在 Fami/Lalu 可独立设置。 +CREATE TABLE IF NOT EXISTS user_vip_settings ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', + 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 '是否开启上线全服通知', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, user_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户按 App 隔离的 VIP 功能开关'; + +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_vip_memberships' AND COLUMN_NAME = 'program_type') = 0, + 'ALTER TABLE user_vip_memberships ADD COLUMN program_type VARCHAR(32) NOT NULL DEFAULT ''legacy_timed'' COMMENT ''激活时使用的 VIP 体系快照'' AFTER status', + '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_memberships' AND COLUMN_NAME = 'config_version') = 0, + 'ALTER TABLE user_vip_memberships ADD COLUMN config_version BIGINT NOT NULL DEFAULT 1 COMMENT ''激活时使用的 VIP 配置版本'' AFTER program_type', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + CREATE TABLE IF NOT EXISTS vip_purchase_orders ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', order_id VARCHAR(96) NOT NULL COMMENT '订单 ID', @@ -1563,7 +1616,13 @@ CREATE TABLE IF NOT EXISTS vip_purchase_orders ( user_id BIGINT NOT NULL COMMENT '用户 ID', target_level INT NOT NULL COMMENT '目标等级', previous_level INT NOT NULL COMMENT '原等级', + previous_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '购买前会员过期时间快照,UTC epoch ms', + new_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '购买后会员过期时间快照,UTC epoch ms', price_coin BIGINT NOT NULL COMMENT 'VIP 价格金币数', + duration_ms BIGINT NOT NULL DEFAULT 0 COMMENT '购买等级的有效期配置快照', + program_type VARCHAR(32) NOT NULL DEFAULT 'legacy_timed' COMMENT '订单执行的 VIP 体系快照', + config_version BIGINT NOT NULL DEFAULT 1 COMMENT '订单执行的 VIP 配置版本', + expiry_policy VARCHAR(32) NOT NULL DEFAULT 'extend_remaining' COMMENT '本单实际采用的有效期策略', status VARCHAR(32) NOT NULL COMMENT '业务状态', wallet_transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID', resource_grant_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '资源发放 ID', @@ -1575,6 +1634,60 @@ CREATE TABLE IF NOT EXISTS vip_purchase_orders ( KEY idx_vip_purchase_user_time (app_code, user_id, created_at_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 购买订单表'; +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'vip_purchase_orders' AND COLUMN_NAME = 'previous_expires_at_ms') = 0, + 'ALTER TABLE vip_purchase_orders ADD COLUMN previous_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''购买前会员过期时间快照,UTC epoch ms'' AFTER previous_level', + '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 = 'vip_purchase_orders' AND COLUMN_NAME = 'new_expires_at_ms') = 0, + 'ALTER TABLE vip_purchase_orders ADD COLUMN new_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''购买后会员过期时间快照,UTC epoch ms'' AFTER previous_expires_at_ms', + '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 = 'vip_purchase_orders' AND COLUMN_NAME = 'duration_ms') = 0, + 'ALTER TABLE vip_purchase_orders ADD COLUMN duration_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''购买等级的有效期配置快照'' AFTER price_coin', + '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 = 'vip_purchase_orders' AND COLUMN_NAME = 'program_type') = 0, + 'ALTER TABLE vip_purchase_orders ADD COLUMN program_type VARCHAR(32) NOT NULL DEFAULT ''legacy_timed'' COMMENT ''订单执行的 VIP 体系快照'' AFTER duration_ms', + '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 = 'vip_purchase_orders' AND COLUMN_NAME = 'config_version') = 0, + 'ALTER TABLE vip_purchase_orders ADD COLUMN config_version BIGINT NOT NULL DEFAULT 1 COMMENT ''订单执行的 VIP 配置版本'' AFTER program_type', + '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 = 'vip_purchase_orders' AND COLUMN_NAME = 'expiry_policy') = 0, + 'ALTER TABLE vip_purchase_orders ADD COLUMN expiry_policy VARCHAR(32) NOT NULL DEFAULT ''extend_remaining'' COMMENT ''本单实际采用的有效期策略'' AFTER config_version', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + CREATE TABLE IF NOT EXISTS user_vip_history ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', history_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '历史 ID', @@ -1582,11 +1695,228 @@ CREATE TABLE IF NOT EXISTS user_vip_history ( action VARCHAR(32) NOT NULL COMMENT '操作', previous_level INT NOT NULL COMMENT '原等级', new_level INT NOT NULL COMMENT '新等级', + previous_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '变更前过期时间快照,UTC epoch ms', + new_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '变更后过期时间快照,UTC epoch ms', + program_type VARCHAR(32) NOT NULL DEFAULT 'legacy_timed' COMMENT '变更使用的 VIP 体系快照', + config_version BIGINT NOT NULL DEFAULT 1 COMMENT '变更使用的 VIP 配置版本', order_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '订单 ID', created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', KEY idx_user_vip_history_user_time (app_code, user_id, created_at_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户 VIP 历史表'; +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_vip_history' AND COLUMN_NAME = 'previous_expires_at_ms') = 0, + 'ALTER TABLE user_vip_history ADD COLUMN previous_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''变更前过期时间快照,UTC epoch ms'' AFTER new_level', + '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_history' AND COLUMN_NAME = 'new_expires_at_ms') = 0, + 'ALTER TABLE user_vip_history ADD COLUMN new_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''变更后过期时间快照,UTC epoch ms'' AFTER previous_expires_at_ms', + '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_history' AND COLUMN_NAME = 'program_type') = 0, + 'ALTER TABLE user_vip_history ADD COLUMN program_type VARCHAR(32) NOT NULL DEFAULT ''legacy_timed'' COMMENT ''变更使用的 VIP 体系快照'' AFTER new_expires_at_ms', + '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_history' AND COLUMN_NAME = 'config_version') = 0, + 'ALTER TABLE user_vip_history ADD COLUMN config_version BIGINT NOT NULL DEFAULT 1 COMMENT ''变更使用的 VIP 配置版本'' AFTER program_type', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- 重复执行 initdb 也可能面对旧 history 有效期快照为 0 的开发库。只为没有任何完整 +-- 新格式 history 的当前会员补迁移基线;不 UPDATE 旧行,也不改写已有新格式历史语义。 +SET @vip_history_baseline_ms := CAST(UNIX_TIMESTAMP(UTC_TIMESTAMP(3)) * 1000 AS UNSIGNED); + +INSERT INTO user_vip_history ( + app_code, user_id, action, previous_level, new_level, previous_expires_at_ms, + new_expires_at_ms, program_type, config_version, order_id, created_at_ms +) +SELECT + memberships.app_code, + memberships.user_id, + 'migration_baseline', + 0, + memberships.level, + 0, + memberships.expires_at_ms, + memberships.program_type, + memberships.config_version, + 'vip_configurable_060_baseline', + @vip_history_baseline_ms +FROM user_vip_memberships AS memberships +WHERE memberships.level > 0 + AND memberships.expires_at_ms > 0 + AND NOT EXISTS ( + SELECT 1 + FROM user_vip_history AS complete_history + WHERE complete_history.app_code = memberships.app_code + AND complete_history.user_id = memberships.user_id + AND complete_history.new_level > 0 + AND complete_history.new_expires_at_ms > 0 + ) + AND NOT EXISTS ( + SELECT 1 + FROM user_vip_history AS existing_baseline + WHERE existing_baseline.app_code = memberships.app_code + AND existing_baseline.user_id = memberships.user_id + AND existing_baseline.order_id = 'vip_configurable_060_baseline' + ); + +-- vip_level_benefits 按“具体等级”保存完整权益集合。unlock_level 只保留 P1 来源信息, +-- 运行时不得靠它自动继承,以便后台将来可以显式调整任意等级的最终集合。 +CREATE TABLE IF NOT EXISTS vip_level_benefits ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', + level INT NOT NULL COMMENT '拥有该权益的具体 VIP 等级', + benefit_code VARCHAR(96) NOT NULL COMMENT '稳定权益编码,跨服务权限判断只使用该值', + name VARCHAR(128) NOT NULL COMMENT '权益展示名称', + benefit_type VARCHAR(32) NOT NULL COMMENT '权益类型:decoration/function', + unlock_level INT NOT NULL COMMENT 'P1 初始解锁等级,仅用于展示来源,不参与运行时继承', + status VARCHAR(32) NOT NULL COMMENT '业务状态:active/disabled', + trial_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '体验卡是否可获得;金币返现必须为 false', + resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '绑定资源 ID;0 表示尚未绑定或纯功能权益', + resource_type VARCHAR(32) NOT NULL DEFAULT '' COMMENT '绑定资源类型;空表示纯功能或待运营配置', + execution_scope VARCHAR(32) NOT NULL COMMENT '实际执行方:wallet/room/user/notice', + auto_equip BOOLEAN NOT NULL DEFAULT FALSE COMMENT '资源下发后是否自动佩戴最高等级样式', + sort_order INT NOT NULL DEFAULT 0 COMMENT '权益展示顺序', + metadata_json JSON NULL COMMENT '执行方扩展配置;初始 P1 权益不猜测参数', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, level, benefit_code), + KEY idx_vip_benefit_code (app_code, benefit_code, status, level), + KEY idx_vip_benefit_level_sort (app_code, level, status, sort_order) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 每等级完整权益矩阵'; + +-- user_vip_trial_cards 只保存体验卡的 VIP 元数据;卡片库存与当前佩戴仍分别复用 +-- user_resource_entitlements 和 user_resource_equipment,切换佩戴不会重置或作废其它卡片。 +CREATE TABLE IF NOT EXISTS user_vip_trial_cards ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', + trial_card_id VARCHAR(96) NOT NULL COMMENT '体验卡实例 ID', + command_id VARCHAR(128) NOT NULL COMMENT '发卡命令幂等 ID', + request_hash VARCHAR(128) NOT NULL COMMENT '发卡请求语义哈希', + user_id BIGINT NOT NULL COMMENT '持有用户 ID', + entitlement_id VARCHAR(96) NOT NULL COMMENT '通用背包权益实例 ID,也是佩戴入口标识', + resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '可选资源 ID;0 表示直接按等级和时长发卡', + level INT NOT NULL COMMENT '体验卡 VIP 等级快照', + name VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'VIP 等级名称快照', + status VARCHAR(32) NOT NULL COMMENT '卡片业务状态:active/revoked', + duration_ms BIGINT NOT NULL COMMENT '发卡时长快照;佩戴切换不改变该值', + effective_at_ms BIGINT NOT NULL COMMENT '卡片开始计时,UTC epoch ms', + expires_at_ms BIGINT NOT NULL COMMENT '卡片绝对过期时间,UTC epoch ms', + grant_source VARCHAR(32) NOT NULL COMMENT '发放来源', + source_grant_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '通用资源发放 ID', + operator_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '发放操作人用户 ID', + reason VARCHAR(256) NOT NULL DEFAULT '' COMMENT '发放原因', + program_type VARCHAR(32) NOT NULL COMMENT '发卡时 VIP 体系快照', + config_version BIGINT NOT NULL COMMENT '发卡时 VIP 配置版本', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, trial_card_id), + UNIQUE KEY uk_vip_trial_card_command (app_code, command_id), + UNIQUE KEY uk_vip_trial_card_entitlement (app_code, entitlement_id), + KEY idx_vip_trial_card_user (app_code, user_id, status, expires_at_ms), + KEY idx_vip_trial_card_resource (app_code, resource_id, status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 体验卡背包元数据'; + +-- VIP 购买、直发、体验卡和返现领取先锁定同一守卫键,再进入会员、账户或资源业务锁。守卫与业务事实同事务提交, +-- 既避免并发首发返回可变错误,也禁止 purchase/direct grant/trial grant 交叉复用 command_id。 +CREATE TABLE IF NOT EXISTS vip_command_locks ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', + command_id VARCHAR(128) NOT NULL COMMENT 'VIP 写命令幂等 ID', + biz_type VARCHAR(64) NOT NULL COMMENT '命令类型:vip_purchase/vip_grant/vip_trial_card_grant/vip_daily_coin_rebate', + request_hash VARCHAR(128) NOT NULL COMMENT '请求语义哈希', + created_at_ms BIGINT NOT NULL COMMENT '首次命令时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '最后写入时间,UTC epoch ms', + PRIMARY KEY (app_code, command_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 写命令串行化守卫'; + +-- vip_daily_coin_rebate_runs 固化单 App、单 UTC 日的金额矩阵和配置版本。分页只推进本表游标, +-- 不能在每页重新读取 vip_level_benefits,否则日切期间后台改价会让同一天用户拿到不同金额版本。 +CREATE TABLE IF NOT EXISTS vip_daily_coin_rebate_runs ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', + task_day CHAR(10) NOT NULL COMMENT 'UTC 日期,YYYY-MM-DD', + run_id VARCHAR(96) NOT NULL COMMENT '稳定批任务 ID', + day_start_ms BIGINT NOT NULL COMMENT 'UTC 当日开始,epoch ms', + day_end_ms BIGINT NOT NULL COMMENT 'UTC 次日开始,排他结束 epoch ms', + config_version BIGINT NOT NULL COMMENT '创建 run 时 VIP 配置版本', + level_amounts_json JSON NOT NULL COMMENT '等级到返现金额的不可变快照', + status VARCHAR(32) NOT NULL COMMENT 'running/completed', + last_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '已扫描会员游标', + scanned_count BIGINT NOT NULL DEFAULT 0 COMMENT '累计扫描会员数', + created_count BIGINT NOT NULL DEFAULT 0 COMMENT '累计创建返现数', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + completed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '完成时间,UTC epoch ms', + PRIMARY KEY (app_code, task_day), + UNIQUE KEY uk_vip_rebate_run_id (app_code, run_id), + KEY idx_vip_rebate_run_status (app_code, status, task_day) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 每日金币返现运行快照'; + +-- vip_daily_coin_rebates 是付费 VIP 日切资格事实。体验卡不写入此表;领取只允许在 +-- [available_at_ms, expires_at_ms) 内完成,并与 COIN 账户、分录和 outbox 同事务提交。 +CREATE TABLE IF NOT EXISTS vip_daily_coin_rebates ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', + rebate_id VARCHAR(96) NOT NULL COMMENT '返现事实 ID', + run_id VARCHAR(96) NOT NULL COMMENT '来源日 run ID', + task_day CHAR(10) NOT NULL COMMENT 'UTC 日期,YYYY-MM-DD', + user_id BIGINT NOT NULL COMMENT '领取用户 ID', + vip_level INT NOT NULL COMMENT 'UTC 日切时付费 VIP 等级快照', + vip_name VARCHAR(64) NOT NULL COMMENT 'VIP 名称快照', + coin_amount BIGINT NOT NULL COMMENT '返现金币正整数快照', + status VARCHAR(32) NOT NULL COMMENT 'claimable/claimed;expired 由查询层投影', + available_at_ms BIGINT NOT NULL COMMENT '领取开始,UTC epoch ms', + expires_at_ms BIGINT NOT NULL COMMENT '领取排他结束,UTC epoch ms', + config_version BIGINT NOT NULL COMMENT '来源 run 的 VIP 配置版本', + claimed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '实际领取时间,UTC epoch ms', + wallet_transaction_id VARCHAR(96) NOT NULL DEFAULT '' 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, rebate_id), + UNIQUE KEY uk_vip_rebate_user_day (app_code, task_day, user_id), + KEY idx_vip_rebate_user_day (app_code, user_id, task_day, rebate_id), + KEY idx_vip_rebate_expiry (app_code, status, expires_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 每日金币返现领取事实'; + +-- initdb 也允许在保留数据的开发库重复执行,因此同步补齐守卫,不能只覆盖全新空库。 +INSERT IGNORE INTO vip_command_locks ( + app_code, command_id, biz_type, request_hash, created_at_ms, updated_at_ms +) +SELECT app_code, command_id, biz_type, request_hash, created_at_ms, updated_at_ms +FROM wallet_transactions +WHERE biz_type IN ('vip_purchase', 'vip_grant', 'vip_daily_coin_rebate'); + +INSERT IGNORE INTO vip_command_locks ( + app_code, command_id, biz_type, request_hash, created_at_ms, updated_at_ms +) +SELECT app_code, command_id, 'vip_trial_card_grant', request_hash, created_at_ms, updated_at_ms +FROM user_vip_trial_cards; + +INSERT IGNORE INTO vip_program_configs ( + app_code, program_type, level_count, same_level_expiry_policy, upgrade_expiry_policy, + downgrade_purchase_policy, benefit_inheritance_policy, grant_mode, trial_card_enabled, + status, config_version, updated_by_admin_id, created_at_ms, updated_at_ms +) VALUES + ('lalu', 'legacy_timed', 10, 'extend_remaining', 'extend_remaining', + 'reject', 'target_only', 'direct_membership', FALSE, 'active', 1, 0, 0, 0), + ('fami', 'tiered_privilege_v1', 9, 'extend_remaining', 'replace_from_now', + 'reject', 'target_only', 'trial_card', TRUE, 'active', 1, 0, 0, 0); + INSERT IGNORE INTO vip_levels ( app_code, level, name, status, price_coin, duration_ms, reward_resource_group_id, required_recharge_coin_amount, sort_order, created_at_ms, updated_at_ms @@ -1600,7 +1930,126 @@ INSERT IGNORE INTO vip_levels ( ('lalu', 7, 'VIP7', 'disabled', 0, 604800000, 0, 0, 70, 0, 0), ('lalu', 8, 'VIP8', 'disabled', 0, 604800000, 0, 0, 80, 0, 0), ('lalu', 9, 'VIP9', 'disabled', 0, 604800000, 0, 0, 90, 0, 0), - ('lalu', 10, 'VIP10', 'disabled', 0, 604800000, 0, 0, 100, 0, 0); + ('lalu', 10, 'VIP10', 'disabled', 0, 604800000, 0, 0, 100, 0, 0), + -- Fami 的价格和资源组必须由运营后台配置;30 天仅满足后台正数校验且等级保持 disabled, + -- 不能把 Lalu 的任何商业参数复制为可购买默认值。 + ('fami', 1, 'VIP1', 'disabled', 0, 2592000000, 0, 0, 10, 0, 0), + ('fami', 2, 'VIP2', 'disabled', 0, 2592000000, 0, 0, 20, 0, 0), + ('fami', 3, 'VIP3', 'disabled', 0, 2592000000, 0, 0, 30, 0, 0), + ('fami', 4, 'VIP4', 'disabled', 0, 2592000000, 0, 0, 40, 0, 0), + ('fami', 5, 'VIP5', 'disabled', 0, 2592000000, 0, 0, 50, 0, 0), + ('fami', 6, 'VIP6', 'disabled', 0, 2592000000, 0, 0, 60, 0, 0), + ('fami', 7, 'VIP7', 'disabled', 0, 2592000000, 0, 0, 70, 0, 0), + ('fami', 8, 'VIP8', 'disabled', 0, 2592000000, 0, 0, 80, 0, 0), + ('fami', 9, 'VIP9', 'disabled', 0, 2592000000, 0, 0, 90, 0, 0); + +-- P1 权益按每个等级展开成完整集合:例如 VIP4 会实际写入 VIP1..VIP4 的全部权益。 +-- resource_id/resource_type 保持空,待运营绑定真实资源;体验卡仅排除每日金币返现。 +INSERT IGNORE INTO vip_level_benefits ( + app_code, level, benefit_code, name, benefit_type, unlock_level, status, trial_enabled, + resource_id, resource_type, execution_scope, auto_equip, sort_order, metadata_json, + created_at_ms, updated_at_ms +) +SELECT + 'fami', levels.level, benefits.benefit_code, benefits.name, benefits.benefit_type, + benefits.unlock_level, + CASE WHEN benefits.benefit_code = 'daily_coin_rebate' THEN 'disabled' ELSE 'active' END, + benefits.trial_enabled, 0, '', benefits.execution_scope, + benefits.auto_equip, benefits.sort_order, + CASE + WHEN benefits.benefit_code = 'online_global_notice' + THEN JSON_OBJECT('message', '欢迎进入Fami,祝你有美好的一天') + ELSE NULL + END, + 0, 0 +FROM ( + SELECT 1 AS level UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 + UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 +) AS levels +INNER JOIN ( + SELECT 'vip_badge_identity' AS benefit_code, 'VIP标识' AS name, 'function' AS benefit_type, 1 AS unlock_level, TRUE AS trial_enabled, 'user' AS execution_scope, FALSE AS auto_equip, 10 AS sort_order + UNION ALL SELECT 'vip_medal', 'VIP勋章', 'decoration', 1, TRUE, 'user', TRUE, 20 + UNION ALL SELECT 'avatar_frame', 'VIP头像框', 'decoration', 1, TRUE, 'user', TRUE, 30 + UNION ALL SELECT 'vip_title', 'VIP称号', 'function', 1, TRUE, 'user', FALSE, 40 + UNION ALL SELECT 'chat_bubble', 'VIP聊天气泡', 'decoration', 2, TRUE, 'room', TRUE, 50 + UNION ALL SELECT 'vip_gift', 'VIP礼物', 'function', 2, TRUE, 'room', FALSE, 60 + UNION ALL SELECT 'entry_effect', 'VIP进场通知', 'function', 2, TRUE, 'room', FALSE, 70 + UNION ALL SELECT 'visitor_history', '查看访客', 'function', 2, TRUE, 'user', FALSE, 80 + UNION ALL SELECT 'voice_wave', 'VIP声波纹', 'decoration', 3, TRUE, 'room', TRUE, 90 + UNION ALL SELECT 'profile_card', 'VIP资料卡皮肤', 'decoration', 3, TRUE, 'user', TRUE, 100 + UNION ALL SELECT 'custom_room_background', '自定义房间背景', 'function', 3, TRUE, 'room', FALSE, 110 + UNION ALL SELECT 'room_image_message', '房间发图', 'function', 3, TRUE, 'room', FALSE, 120 + UNION ALL SELECT 'animated_avatar', '动态头像', 'function', 4, TRUE, 'user', FALSE, 130 + UNION ALL SELECT 'animated_room_cover', '动态房间封面', 'function', 4, TRUE, 'room', FALSE, 140 + UNION ALL SELECT 'mic_skin', '麦克风皮肤', 'decoration', 4, TRUE, 'room', TRUE, 150 + UNION ALL SELECT 'room_border', '房间边框', 'decoration', 4, TRUE, 'room', TRUE, 160 + UNION ALL SELECT 'vehicle', 'VIP座驾', 'decoration', 4, TRUE, 'room', TRUE, 170 + UNION ALL SELECT 'colored_room_name', 'VIP彩色房间名称', 'function', 5, TRUE, 'room', FALSE, 180 + UNION ALL SELECT 'colored_nickname', 'VIP彩色昵称', 'function', 5, TRUE, 'user', FALSE, 190 + UNION ALL SELECT 'colored_id', 'VIP彩色ID', 'function', 5, TRUE, 'user', FALSE, 200 + UNION ALL SELECT 'gift_tray_skin', '送礼托盘皮肤', 'function', 5, TRUE, 'room', FALSE, 210 + UNION ALL SELECT 'hide_profile_data', '隐藏个人数据', 'function', 6, TRUE, 'user', FALSE, 220 + UNION ALL SELECT 'custom_avatar_frame', '定制头框', 'function', 6, TRUE, 'user', FALSE, 230 + UNION ALL SELECT 'leaderboard_invisible', '榜单隐身', 'function', 6, TRUE, 'user', FALSE, 240 + UNION ALL SELECT 'daily_coin_rebate', '金币返现', 'function', 6, FALSE, 'wallet', FALSE, 250 + UNION ALL SELECT 'custom_profile_card', '定制资料卡', 'function', 7, TRUE, 'user', FALSE, 260 + UNION ALL SELECT 'anonymous_profile_visit', '匿名访问主页', 'function', 7, TRUE, 'user', FALSE, 270 + UNION ALL SELECT 'custom_gift', '定制礼物', 'function', 7, TRUE, 'room', FALSE, 280 + -- 产品已确认该权益只在当前房间展示,编码和名称均不再使用“全服”。 + UNION ALL SELECT 'room_entry_notice', '进房高亮通知', 'function', 8, TRUE, 'room', FALSE, 290 + UNION ALL SELECT 'custom_pretty_id', '定制靓号', 'function', 8, TRUE, 'user', FALSE, 300 + UNION ALL SELECT 'custom_vehicle', '定制座驾', 'function', 8, TRUE, 'room', FALSE, 310 + UNION ALL SELECT 'anti_kick', '防踢', 'function', 9, TRUE, 'room', FALSE, 320 + UNION ALL SELECT 'anti_mute', '防禁言', 'function', 9, TRUE, 'room', FALSE, 330 + UNION ALL SELECT 'online_global_notice', '上线全服通知', 'function', 9, TRUE, 'notice', FALSE, 340 +) AS benefits ON benefits.unlock_level <= levels.level; + +-- 原型未给出各等级金额,不能猜默认值。未配置正 int64 金额前保持 disabled;运营填入 +-- metadata_json.coin_amount 并启用后,后台校验和日 run 创建都会再次严格校验。 +UPDATE vip_level_benefits +SET status = 'disabled', trial_enabled = FALSE +WHERE app_code = 'fami' + AND benefit_code = 'daily_coin_rebate' + AND ( + JSON_EXTRACT(metadata_json, '$.coin_amount') IS NULL + OR JSON_TYPE(JSON_EXTRACT(metadata_json, '$.coin_amount')) <> 'INTEGER' + OR CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.coin_amount')) AS DECIMAL(65, 0)) <= 0 + OR CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.coin_amount')) AS DECIMAL(65, 0)) > 9223372036854775807 + ); + +-- 老环境可能先执行过不含文案的 seed;这里只补空元数据,运营已配置的 App 文案必须保留。 +UPDATE vip_level_benefits +SET metadata_json = JSON_OBJECT('message', '欢迎进入Fami,祝你有美好的一天') +WHERE app_code = 'fami' + AND benefit_code = 'online_global_notice' + AND COALESCE(JSON_LENGTH(metadata_json), 0) = 0; + +-- Fami 的九种体验卡只预置可发放的背包资源和等级元数据,不预置素材、不固定 resource_id、 +-- 不猜测卡片时长;实际发放必须由 GrantVipTrialCard 显式提交 level+duration_ms。 +INSERT IGNORE INTO resources ( + app_code, resource_code, resource_type, name, status, grantable, manager_grant_enabled, + grant_strategy, wallet_asset_type, wallet_asset_amount, price_type, coin_price, gift_point_amount, + usage_scope_json, asset_url, preview_url, animation_url, metadata_json, sort_order, + created_by_user_id, updated_by_user_id, created_at_ms, updated_at_ms +) VALUES + ('fami', 'vip_trial_card_1', 'vip_trial_card', 'VIP1体验卡', 'active', TRUE, TRUE, + 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":1}', 10, 0, 0, 0, 0), + ('fami', 'vip_trial_card_2', 'vip_trial_card', 'VIP2体验卡', 'active', TRUE, TRUE, + 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":2}', 20, 0, 0, 0, 0), + ('fami', 'vip_trial_card_3', 'vip_trial_card', 'VIP3体验卡', 'active', TRUE, TRUE, + 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":3}', 30, 0, 0, 0, 0), + ('fami', 'vip_trial_card_4', 'vip_trial_card', 'VIP4体验卡', 'active', TRUE, TRUE, + 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":4}', 40, 0, 0, 0, 0), + ('fami', 'vip_trial_card_5', 'vip_trial_card', 'VIP5体验卡', 'active', TRUE, TRUE, + 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":5}', 50, 0, 0, 0, 0), + ('fami', 'vip_trial_card_6', 'vip_trial_card', 'VIP6体验卡', 'active', TRUE, TRUE, + 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":6}', 60, 0, 0, 0, 0), + ('fami', 'vip_trial_card_7', 'vip_trial_card', 'VIP7体验卡', 'active', TRUE, TRUE, + 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":7}', 70, 0, 0, 0, 0), + ('fami', 'vip_trial_card_8', 'vip_trial_card', 'VIP8体验卡', 'active', TRUE, TRUE, + 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":8}', 80, 0, 0, 0, 0), + ('fami', 'vip_trial_card_9', 'vip_trial_card', 'VIP9体验卡', 'active', TRUE, TRUE, + 'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":9}', 90, 0, 0, 0, 0); INSERT IGNORE INTO gift_type_configs ( app_code, type_code, name, tab_key, status, sort_order, diff --git a/services/wallet-service/internal/domain/ledger/vip.go b/services/wallet-service/internal/domain/ledger/vip.go index 18df3fd8..d173982b 100644 --- a/services/wallet-service/internal/domain/ledger/vip.go +++ b/services/wallet-service/internal/domain/ledger/vip.go @@ -4,6 +4,132 @@ import ( "strings" ) +const ( + // VipProgramTypeLegacyTimed 保持 Lalu 现有的剩余时间累加会员语义。 + VipProgramTypeLegacyTimed = "legacy_timed" + // VipProgramTypeTieredPrivilegeV1 是 Fami P1 的九级权益体系。 + VipProgramTypeTieredPrivilegeV1 = "tiered_privilege_v1" + // VipExpiryPolicyExtendRemaining 从当前有效截止时间继续累加购买时长。 + VipExpiryPolicyExtendRemaining = "extend_remaining" + // VipExpiryPolicyReplaceFromNow 表示高级购买立即丢弃低级剩余时间,并从当前时刻重新计时。 + VipExpiryPolicyReplaceFromNow = "replace_from_now" + // VipDowngradePurchasePolicyReject 禁止有效会员购买更低等级。 + VipDowngradePurchasePolicyReject = "reject" + // VipBenefitInheritanceTargetOnly 仅使用目标等级显式配置的权益集合。 + VipBenefitInheritanceTargetOnly = "target_only" + // VipGrantModeDirectMembership 将后台赠送直接写为真实会员。 + VipGrantModeDirectMembership = "direct_membership" + // VipGrantModeTrialCard 将后台赠送写入可自由佩戴的背包体验卡。 + VipGrantModeTrialCard = "trial_card" + // VipTrialCardResourceType 使体验卡复用通用背包和单选装备链路。 + VipTrialCardResourceType = "vip_trial_card" + // VipEffectiveSourceNone 表示没有有效付费会员或已佩戴体验卡。 + VipEffectiveSourceNone = "none" + // VipEffectiveSourcePaid 表示最终权益来自真实购买会员。 + VipEffectiveSourcePaid = "paid" + // VipEffectiveSourceTrial 表示最终权益来自当前佩戴体验卡。 + VipEffectiveSourceTrial = "trial" + // VipTrialCardStatusActive 表示卡片未被撤销;是否过期仍以 ExpiresAtMS 判定。 + VipTrialCardStatusActive = "active" + // VipTrialCardStatusRevoked 表示后台已撤销卡片及对应背包权益。 + VipTrialCardStatusRevoked = "revoked" + // VipBenefitTypeDecoration 表示需要下发或佩戴资源的视觉权益。 + VipBenefitTypeDecoration = "decoration" + // VipBenefitTypeFunction 表示由 owner service 执行的功能权限。 + VipBenefitTypeFunction = "function" + // VipExecutionScopeWallet 表示权益由 wallet-service 执行,例如金币返现。 + VipExecutionScopeWallet = "wallet" + // VipExecutionScopeRoom 表示权益由 Room Cell 所在 room-service 执行。 + VipExecutionScopeRoom = "room" + // VipExecutionScopeUser 表示权益由用户资料或访客 owner 执行。 + VipExecutionScopeUser = "user" + // VipExecutionScopeNotice 表示权益由通知投递链路执行。 + VipExecutionScopeNotice = "notice" + + // 以下编码是 P1 跨服务权限契约;数据库、钱包投影和各 owner service 必须使用同一稳定值。 + VipBenefitCodeBadgeIdentity = "vip_badge_identity" + VipBenefitCodeMedal = "vip_medal" + VipBenefitCodeAvatarFrame = "avatar_frame" + VipBenefitCodeTitle = "vip_title" + VipBenefitCodeChatBubble = "chat_bubble" + VipBenefitCodeGift = "vip_gift" + VipBenefitCodeEntryEffect = "entry_effect" + VipBenefitCodeVisitorHistory = "visitor_history" + VipBenefitCodeVoiceWave = "voice_wave" + VipBenefitCodeProfileCard = "profile_card" + VipBenefitCodeCustomRoomBackground = "custom_room_background" + VipBenefitCodeRoomImageMessage = "room_image_message" + VipBenefitCodeAnimatedAvatar = "animated_avatar" + VipBenefitCodeAnimatedRoomCover = "animated_room_cover" + VipBenefitCodeMicSkin = "mic_skin" + VipBenefitCodeRoomBorder = "room_border" + VipBenefitCodeVehicle = "vehicle" + VipBenefitCodeColoredRoomName = "colored_room_name" + VipBenefitCodeColoredNickname = "colored_nickname" + VipBenefitCodeColoredID = "colored_id" + VipBenefitCodeGiftTraySkin = "gift_tray_skin" + VipBenefitCodeHideProfileData = "hide_profile_data" + VipBenefitCodeCustomAvatarFrame = "custom_avatar_frame" + VipBenefitCodeLeaderboardInvisible = "leaderboard_invisible" + VipBenefitCodeDailyCoinRebate = "daily_coin_rebate" + VipBenefitCodeCustomProfileCard = "custom_profile_card" + VipBenefitCodeAnonymousProfileVisit = "anonymous_profile_visit" + VipBenefitCodeCustomGift = "custom_gift" + VipBenefitCodeRoomEntryNotice = "room_entry_notice" + VipBenefitCodeCustomPrettyID = "custom_pretty_id" + VipBenefitCodeCustomVehicle = "custom_vehicle" + VipBenefitCodeAntiKick = "anti_kick" + VipBenefitCodeAntiMute = "anti_mute" + VipBenefitCodeOnlineGlobalNotice = "online_global_notice" + + // VipDailyCoinRebateStatusClaimable 表示返现仍处于当天手动领取窗口。 + VipDailyCoinRebateStatusClaimable = "claimable" + // VipDailyCoinRebateStatusClaimed 表示金币已经原子入账,WalletTransactionID 必须非空。 + VipDailyCoinRebateStatusClaimed = "claimed" + // VipDailyCoinRebateStatusExpired 是查询层对超过 UTC 日终但未领取记录的只读投影。 + VipDailyCoinRebateStatusExpired = "expired" + // VipDailyCoinRebateRunStatusRunning 表示批任务仍需沿 last_user_id 继续分页。 + VipDailyCoinRebateRunStatusRunning = "running" + // VipDailyCoinRebateRunStatusCompleted 表示当日所有候选会员已经扫描完成。 + VipDailyCoinRebateRunStatusCompleted = "completed" +) + +// VipProgramConfig 是某 App 当前 VIP 状态机的完整规则,不允许调用方再按 app_code 猜规则。 +type VipProgramConfig struct { + AppCode string + ProgramType string + LevelCount int32 + SameLevelExpiryPolicy string + UpgradeExpiryPolicy string + DowngradePurchasePolicy string + BenefitInheritancePolicy string + GrantMode string + TrialCardEnabled bool + Status string + ConfigVersion int64 + UpdatedByAdminID int64 + CreatedAtMS int64 + UpdatedAtMS int64 +} + +// VipBenefit 是可跨服务投影和执行的权益事实;ResourceID=0 表示纯功能或尚未绑定资源。 +type VipBenefit struct { + BenefitCode string + Name string + BenefitType string + UnlockLevel int32 + Status string + TrialEnabled bool + ResourceID int64 + ResourceType string + ExecutionScope string + AutoEquip bool + SortOrder int32 + MetadataJSON string + CreatedAtMS int64 + UpdatedAtMS int64 +} + // VipRewardItem 是 VIP 资源组权益的轻量展示投影。 type VipRewardItem struct { ResourceID int64 @@ -34,17 +160,85 @@ type VipLevel struct { SortOrder int32 CreatedAtMS int64 UpdatedAtMS int64 + Benefits []VipBenefit + ConfigVersion int64 } // UserVip 是用户当前会员状态。是否有效以 ExpiresAtMS 和当前时间判断。 type UserVip struct { - UserID int64 - Level int32 - Name string - Active bool - StartedAtMS int64 - ExpiresAtMS int64 - UpdatedAtMS int64 + UserID int64 + Level int32 + Name string + Active bool + StartedAtMS int64 + ExpiresAtMS int64 + UpdatedAtMS int64 + ProgramType string + ConfigVersion int64 +} + +// VipTrialCard 把通用背包 entitlement 投影为 VIP 体验卡;装备切换只改变 Equipped, +// DurationMS、EffectiveAtMS 和 ExpiresAtMS 始终保留发卡时的绝对计时事实。 +type VipTrialCard struct { + TrialCardID string + EntitlementID string + ResourceID int64 + UserID int64 + Level int32 + Name string + Status string + Equipped bool + DurationMS int64 + EffectiveAtMS int64 + ExpiresAtMS int64 + RemainingDurationMS int64 + GrantSource string + SourceGrantID string + CreatedAtMS int64 + UpdatedAtMS int64 +} + +// VipUserSettings 是用户可关闭的 VIP 展示偏好。默认值必须由 wallet owner 统一构造, +// 不能让 room/gateway 因为数据库尚未物化记录而各自猜不同默认值。 +type VipUserSettings struct { + AppCode string + UserID int64 + RoomEntryNoticeEnabled bool + OnlineGlobalNoticeEnabled bool + UpdatedAtMS int64 +} + +// DefaultVipUserSettings 返回尚未物化时的产品默认:两项通知均开启,UpdatedAtMS=0。 +func DefaultVipUserSettings(appCode string, userID int64) VipUserSettings { + return VipUserSettings{ + AppCode: appCode, UserID: userID, + RoomEntryNoticeEnabled: true, OnlineGlobalNoticeEnabled: true, + } +} + +// AllowsBenefitSetting 只处理用户可关闭的两项权益;其它权益不受偏好表影响。 +func (settings VipUserSettings) AllowsBenefitSetting(benefitCode string) bool { + switch strings.ToLower(strings.TrimSpace(benefitCode)) { + case VipBenefitCodeRoomEntryNotice: + return settings.RoomEntryNoticeEnabled + case VipBenefitCodeOnlineGlobalNotice: + return settings.OnlineGlobalNoticeEnabled + default: + return true + } +} + +// VipState 是调用方唯一应消费的合并状态。EffectiveBenefits 已按真实/体验来源过滤, +// 尤其不会向体验卡返回 TrialEnabled=false 的金币返现资格;可关闭通知还需结合 UserSettings。 +type VipState struct { + PaidVip UserVip + EquippedTrialCard *VipTrialCard + EffectiveVip UserVip + EffectiveSource string + EffectiveBenefits []VipBenefit + EvaluatedAtMS int64 + ProgramConfig VipProgramConfig + UserSettings VipUserSettings } // PurchaseVipCommand 是 App 购买或升级 VIP 的账务命令。 @@ -63,6 +257,7 @@ type PurchaseVipReceipt struct { CoinSpent int64 CoinBalanceAfter int64 RewardItems []VipRewardItem + State VipState } // GrantVipCommand 是活动或后台发放 VIP 的统一入口命令。 @@ -81,6 +276,52 @@ type GrantVipReceipt struct { TransactionID string Vip UserVip RewardItems []VipRewardItem + State VipState +} + +// GrantVipTrialCardCommand 是直接按等级和绝对时长发放体验卡的幂等命令。 +// ResourceID=0 表示按 level 解析同 App 预置资源;非 0 时也必须匹配该等级的 vip_trial_card。 +type GrantVipTrialCardCommand struct { + AppCode string + CommandID string + TargetUserID int64 + Level int32 + DurationMS int64 + ResourceID int64 + GrantSource string + OperatorUserID int64 + Reason string +} + +// GrantVipTrialCardReceipt 返回新卡和重新计算后的有效 VIP 状态;发卡本身不自动佩戴。 +type GrantVipTrialCardReceipt struct { + TrialCard VipTrialCard + State VipState + ServerTimeMS int64 +} + +// EquipVipTrialCardCommand 以 entitlement 精确选择背包实例,避免同资源多卡时佩戴错对象。 +type EquipVipTrialCardCommand struct { + AppCode string + RequestID string + UserID int64 + EntitlementID string +} + +// UnequipVipTrialCardCommand 只清理 vip_trial_card 类型的装备事实,不回收或暂停任一卡片。 +type UnequipVipTrialCardCommand struct { + AppCode string + RequestID string + UserID int64 +} + +// CheckVipBenefitResult 是 owner service 执行单项特权时使用的服务端判断结果。 +type CheckVipBenefitResult struct { + Allowed bool + Benefit VipBenefit + State VipState + DenialReason string + EvaluatedAtMS int64 } // AdminVipLevelCommand 是后台保存 VIP 等级配置的完整事实输入。 @@ -93,6 +334,101 @@ type AdminVipLevelCommand struct { RewardResourceGroupID int64 RequiredRechargeCoinAmount int64 SortOrder int32 + Benefits []VipBenefit +} + +// AdminVipProgramConfigCommand 是后台保存 App 级 VIP 策略的审计输入。 +type AdminVipProgramConfigCommand struct { + Config VipProgramConfig + OperatorUserID int64 +} + +// UpdateVipUserSettingsCommand 使用指针表达 partial update;nil 字段必须保留数据库原值。 +type UpdateVipUserSettingsCommand struct { + AppCode string + UserID int64 + RoomEntryNoticeEnabled *bool + OnlineGlobalNoticeEnabled *bool +} + +// VipDailyCoinRebateRun 是单 App、单 UTC 日唯一的配置快照与分页游标。 +// LevelAmounts 只在创建 run 时从 active daily_coin_rebate 权益解析,后续分页禁止回读新配置。 +type VipDailyCoinRebateRun struct { + RunID string + TaskDay string + DayStartMS int64 + DayEndMS int64 + ConfigVersion int64 + LevelAmounts map[int32]int64 + LevelAmountsJSON string + Status string + LastUserID int64 + ScannedCount int64 + CreatedCount int64 + CreatedAtMS int64 + UpdatedAtMS int64 + CompletedAtMS int64 +} + +// VipDailyCoinRebate 是日切时生成、当天手动领取的付费 VIP 返现事实。 +type VipDailyCoinRebate struct { + RebateID string + UserID int64 + TaskDay string + VipLevel int32 + VipName string + CoinAmount int64 + Status string + AvailableAtMS int64 + ExpiresAtMS int64 + ConfigVersion int64 + ClaimedAtMS int64 + WalletTransactionID string + CreatedAtMS int64 + UpdatedAtMS int64 +} + +// ProcessVipDailyCoinRebateBatchCommand 由 cron 适配器构造;NowMS 仅由 wallet-service 注入, +// repository 不信任调度方的本地时钟。 +type ProcessVipDailyCoinRebateBatchCommand struct { + AppCode string + TaskDay string + BatchSize int + NowMS int64 +} + +// ProcessVipDailyCoinRebateBatchResult 返回本页计数与持久 run,调度方据 HasMore 继续触发。 +type ProcessVipDailyCoinRebateBatchResult struct { + Run VipDailyCoinRebateRun + ScannedCount int + CreatedCount int + HasMore bool +} + +// ListVipDailyCoinRebateStatusesQuery 是用户侧返现历史分页查询;状态在读取时按 NowMS 投影。 +type ListVipDailyCoinRebateStatusesQuery struct { + AppCode string + UserID int64 + Page int + PageSize int + RebateIDs []string + NowMS int64 +} + +// ClaimVipDailyCoinRebateCommand 只包含调用方可控主键;金额、等级和窗口全部从锁内返现行读取。 +type ClaimVipDailyCoinRebateCommand struct { + AppCode string + CommandID string + UserID int64 + RebateID string + NowMS int64 +} + +// ClaimVipDailyCoinRebateReceipt 是幂等稳定回执;同 command 重放必须返回同一交易和账后余额。 +type ClaimVipDailyCoinRebateReceipt struct { + Rebate VipDailyCoinRebate + TransactionID string + CoinBalance AssetBalance } func NormalizeVipGrantSource(source string) string { diff --git a/services/wallet-service/internal/domain/ledger/wallet_query.go b/services/wallet-service/internal/domain/ledger/wallet_query.go index ecc3e4c8..e037011a 100644 --- a/services/wallet-service/internal/domain/ledger/wallet_query.go +++ b/services/wallet-service/internal/domain/ledger/wallet_query.go @@ -53,6 +53,16 @@ type RechargeBillSummary struct { CoinSeller RechargeBillSummaryBucket } +// UserRechargeStats 是用户维度的累计充值读模型;字段直接对应 wallet_user_recharge_stats 聚合行。 +type UserRechargeStats struct { + UserID int64 + RechargeCount int64 + TotalCoinAmount int64 + TotalUSDMinorAmount int64 + FirstRechargedAtMS int64 + UpdatedAtMS int64 +} + // ListRechargeBillsQuery 是后台查询所有充值渠道账单的筛选条件。 type ListRechargeBillsQuery struct { AppCode string diff --git a/services/wallet-service/internal/domain/resource/constants.go b/services/wallet-service/internal/domain/resource/constants.go index 343d1137..36cc7f89 100644 --- a/services/wallet-service/internal/domain/resource/constants.go +++ b/services/wallet-service/internal/domain/resource/constants.go @@ -12,6 +12,9 @@ const ( TypeMicSeatIcon = "mic_seat_icon" TypeMicSeatAnimation = "mic_seat_animation" TypeEmojiPack = "emoji_pack" + // TypeVIPTrialCard 是可在背包中独立计时、单选佩戴的 VIP 体验卡。 + // VIP 等级和有效期事实仍由 user_vip_trial_cards 保存,资源目录只负责素材和通用背包展示。 + TypeVIPTrialCard = "vip_trial_card" StatusActive = "active" StatusDisabled = "disabled" diff --git a/services/wallet-service/internal/domain/resource/entitlement.go b/services/wallet-service/internal/domain/resource/entitlement.go index 8dd46f4c..fd8e908b 100644 --- a/services/wallet-service/internal/domain/resource/entitlement.go +++ b/services/wallet-service/internal/domain/resource/entitlement.go @@ -25,6 +25,9 @@ type ListUserResourcesQuery struct { } type EquipUserResourceCommand struct { + // RequestID 在通用背包命中 VIP 体验卡时作为专用状态机的 outbox 幂等事件键; + // 普通装扮仍不把 request_id 当业务幂等键。 + RequestID string AppCode string UserID int64 ResourceID int64 @@ -32,6 +35,8 @@ type EquipUserResourceCommand struct { } type UnequipUserResourceCommand struct { + // RequestID 仅在 vip_trial_card 委托专用卸下流程时用于发布完整 VIP 状态变更事件。 + RequestID string AppCode string UserID int64 ResourceType string diff --git a/services/wallet-service/internal/domain/resource/resource.go b/services/wallet-service/internal/domain/resource/resource.go index 36593fcd..3ee2be1b 100644 --- a/services/wallet-service/internal/domain/resource/resource.go +++ b/services/wallet-service/internal/domain/resource/resource.go @@ -101,7 +101,7 @@ func NormalizeGrantSource(value string) string { func ValidResourceType(value string) bool { switch strings.ToLower(strings.TrimSpace(value)) { - case TypeAvatarFrame, TypeProfileCard, TypeCoin, TypeVehicle, TypeChatBubble, TypeBadge, TypeFloatingScreen, TypeGift, TypeMicSeatIcon, TypeMicSeatAnimation, TypeEmojiPack: + case TypeAvatarFrame, TypeProfileCard, TypeCoin, TypeVehicle, TypeChatBubble, TypeBadge, TypeFloatingScreen, TypeGift, TypeMicSeatIcon, TypeMicSeatAnimation, TypeEmojiPack, TypeVIPTrialCard: return true default: return false diff --git a/services/wallet-service/internal/domain/resource/resource_test.go b/services/wallet-service/internal/domain/resource/resource_test.go index 59c5769e..b0f58380 100644 --- a/services/wallet-service/internal/domain/resource/resource_test.go +++ b/services/wallet-service/internal/domain/resource/resource_test.go @@ -15,3 +15,9 @@ func TestRoomAndEmojiAssetsAreValidResourceTypes(t *testing.T) { } } } + +func TestVIPTrialCardIsValidResourceType(t *testing.T) { + if !ValidResourceType(TypeVIPTrialCard) { + t.Fatalf("vip_trial_card must be accepted as a configured resource type") + } +} diff --git a/services/wallet-service/internal/service/wallet/ports/repository.go b/services/wallet-service/internal/service/wallet/ports/repository.go index 00b5ff5c..711dfe91 100644 --- a/services/wallet-service/internal/service/wallet/ports/repository.go +++ b/services/wallet-service/internal/service/wallet/ports/repository.go @@ -97,6 +97,7 @@ type GameLedgerStore interface { type RechargeStore interface { ListRechargeBills(ctx context.Context, query ledger.ListRechargeBillsQuery) ([]ledger.RechargeBill, int64, error) SummarizeRechargeBills(ctx context.Context, query ledger.ListRechargeBillsQuery) (ledger.RechargeBillSummary, error) + BatchGetUserRechargeStats(ctx context.Context, userIDs []int64) ([]ledger.UserRechargeStats, error) GetRechargeBillOverview(ctx context.Context, query ledger.ListRechargeBillsQuery, tzOffsetMinutes int32) (ledger.RechargeBillOverview, error) ListGooglePaymentOrderRefs(ctx context.Context, appCode string, transactionIDs []string) (map[string]ledger.GooglePaymentOrderRef, error) ListPendingGooglePaymentOrderRefs(ctx context.Context, limit int, nowMS int64) ([]ledger.GooglePaymentOrderRef, error) @@ -133,14 +134,31 @@ type ExternalRechargeStore interface { ListExternalRechargeOrdersForReconcile(ctx context.Context, appCode string, limit int) ([]ledger.ExternalRechargeOrder, error) } -// VIPStore 管理 VIP 购买、发放和后台等级配置。 +// VIPStore 管理 VIP 购买、发放、每日返现和后台等级配置。 type VIPStore interface { - ListVipPackages(ctx context.Context, userID int64) (ledger.UserVip, []ledger.VipLevel, error) + // ListVipPackages 在同一个数据库快照中返回最终 VIP 状态和套餐,避免配置切换时拼出跨版本响应。 + ListVipPackages(ctx context.Context, userID int64) (ledger.VipState, []ledger.VipLevel, error) GetMyVip(ctx context.Context, userID int64) (ledger.UserVip, error) + // GetVipProgramConfig 返回单 App 的显式状态机和权益目录,调用方不得按 app_code 复制规则分支。 + GetVipProgramConfig(ctx context.Context) (ledger.VipProgramConfig, []ledger.VipBenefit, error) + // GetVipState 是 paid membership、当前佩戴体验卡和最终权益的唯一合并读模型。 + GetVipState(ctx context.Context, userID int64) (ledger.VipState, error) + CheckVipBenefit(ctx context.Context, userID int64, benefitCode string) (ledger.CheckVipBenefitResult, error) PurchaseVip(ctx context.Context, command ledger.PurchaseVipCommand) (ledger.PurchaseVipReceipt, error) GrantVip(ctx context.Context, command ledger.GrantVipCommand) (ledger.GrantVipReceipt, error) - ListAdminVipLevels(ctx context.Context) ([]ledger.VipLevel, error) - UpdateAdminVipLevels(ctx context.Context, levels []ledger.AdminVipLevelCommand, operatorUserID int64) ([]ledger.VipLevel, error) + GrantVipTrialCard(ctx context.Context, command ledger.GrantVipTrialCardCommand) (ledger.GrantVipTrialCardReceipt, error) + EquipVipTrialCard(ctx context.Context, command ledger.EquipVipTrialCardCommand) (ledger.VipTrialCard, ledger.VipState, error) + UnequipVipTrialCard(ctx context.Context, command ledger.UnequipVipTrialCardCommand) (bool, ledger.VipState, error) + // ListAdminVipLevels 把 program 与完整等级配置作为一个不可拆分的后台读模型返回。 + ListAdminVipLevels(ctx context.Context) (ledger.VipProgramConfig, []ledger.VipLevel, error) + UpdateAdminVipLevels(ctx context.Context, levels []ledger.AdminVipLevelCommand, operatorUserID int64) (ledger.VipProgramConfig, []ledger.VipLevel, error) + UpdateAdminVipProgramConfig(ctx context.Context, command ledger.AdminVipProgramConfigCommand) (ledger.VipProgramConfig, error) + UpdateVipUserSettings(ctx context.Context, command ledger.UpdateVipUserSettingsCommand) (ledger.VipUserSettings, error) + // ProcessVipDailyCoinRebateBatch 创建或复用 UTC 日快照,并在同一事务推进唯一分页游标。 + ProcessVipDailyCoinRebateBatch(ctx context.Context, command ledger.ProcessVipDailyCoinRebateBatchCommand) (ledger.ProcessVipDailyCoinRebateBatchResult, error) + GetMyCurrentVipDailyCoinRebate(ctx context.Context, userID int64, nowMS int64) (ledger.VipDailyCoinRebate, bool, error) + ListMyVipDailyCoinRebateStatuses(ctx context.Context, query ledger.ListVipDailyCoinRebateStatusesQuery) ([]ledger.VipDailyCoinRebate, int64, error) + ClaimVipDailyCoinRebate(ctx context.Context, command ledger.ClaimVipDailyCoinRebateCommand) (ledger.ClaimVipDailyCoinRebateReceipt, error) } // RedPacketStore 管理红包配置、创建、领取、查询和退款补偿。 diff --git a/services/wallet-service/internal/service/wallet/recharge.go b/services/wallet-service/internal/service/wallet/recharge.go index 39880e69..87a7fdd0 100644 --- a/services/wallet-service/internal/service/wallet/recharge.go +++ b/services/wallet-service/internal/service/wallet/recharge.go @@ -34,6 +34,16 @@ func (s *Service) GetRechargeBillSummary(ctx context.Context, query ledger.ListR return s.repository.SummarizeRechargeBills(ctx, query) } +// BatchGetUserRechargeStats 返回后台详情需要的累计充值聚合;缺失用户不返回占位行,由调用方按 0 展示。 +func (s *Service) BatchGetUserRechargeStats(ctx context.Context, appCode string, userIDs []int64) ([]ledger.UserRechargeStats, error) { + if s.repository == nil { + return nil, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + appCode = appcode.Normalize(appCode) + ctx = appcode.WithContext(ctx, appCode) + return s.repository.BatchGetUserRechargeStats(ctx, userIDs) +} + // GetRechargeBillOverview 汇总财务概览的按日趋势、区域分布与谷歌实付覆盖度;筛选口径与账单列表一致。 func (s *Service) GetRechargeBillOverview(ctx context.Context, query ledger.ListRechargeBillsQuery, tzOffsetMinutes int32) (ledger.RechargeBillOverview, error) { if s.repository == nil { diff --git a/services/wallet-service/internal/service/wallet/resource.go b/services/wallet-service/internal/service/wallet/resource.go index f80d9ecb..43a57bd7 100644 --- a/services/wallet-service/internal/service/wallet/resource.go +++ b/services/wallet-service/internal/service/wallet/resource.go @@ -6,6 +6,7 @@ import ( "hyapp/pkg/appcode" "hyapp/pkg/xerr" + "hyapp/services/wallet-service/internal/domain/ledger" resourcedomain "hyapp/services/wallet-service/internal/domain/resource" ) @@ -261,6 +262,52 @@ func (s *Service) EquipUserResource(ctx context.Context, command resourcedomain. } command.AppCode = appcode.Normalize(command.AppCode) ctx = appcode.WithContext(ctx, command.AppCode) + if command.UserID <= 0 || command.ResourceID <= 0 { + return resourcedomain.UserResourceEntitlement{}, xerr.New(xerr.InvalidArgument, "user_id and resource_id are required") + } + resource, err := s.repository.GetResource(ctx, command.ResourceID) + if err != nil { + return resourcedomain.UserResourceEntitlement{}, err + } + if resourcedomain.NormalizeResourceType(resource.ResourceType) == resourcedomain.TypeVIPTrialCard { + // 体验卡在 UI 上仍是普通背包物品,但其装备动作会改变最终 VIP 权益。 + // 因此通用入口必须委托专用状态机,不能直接写 equipment 而绕过 App 开关和 VipEffectiveChanged outbox。 + command.RequestID = strings.TrimSpace(command.RequestID) + command.EntitlementID = strings.TrimSpace(command.EntitlementID) + if command.RequestID == "" || command.EntitlementID == "" { + return resourcedomain.UserResourceEntitlement{}, xerr.New(xerr.InvalidArgument, "request_id and entitlement_id are required for vip_trial_card") + } + items, listErr := s.repository.ListUserResources(ctx, resourcedomain.ListUserResourcesQuery{ + AppCode: command.AppCode, + UserID: command.UserID, + ResourceType: resourcedomain.TypeVIPTrialCard, + ActiveOnly: true, + }) + if listErr != nil { + return resourcedomain.UserResourceEntitlement{}, listErr + } + var selected *resourcedomain.UserResourceEntitlement + for index := range items { + if items[index].EntitlementID == command.EntitlementID && items[index].ResourceID == command.ResourceID { + selected = &items[index] + break + } + } + if selected == nil { + return resourcedomain.UserResourceEntitlement{}, xerr.New(xerr.NotFound, "vip trial card entitlement not found") + } + if _, _, err := s.EquipVipTrialCard(ctx, ledger.EquipVipTrialCardCommand{ + AppCode: command.AppCode, + RequestID: command.RequestID, + UserID: command.UserID, + EntitlementID: command.EntitlementID, + }); err != nil { + return resourcedomain.UserResourceEntitlement{}, err + } + // 专用事务已经再次校验 entitlement 并提交装备/outbox;这里复用预读完整资源投影满足通用 API 返回契约。 + selected.Equipped = true + return *selected, nil + } return s.repository.EquipUserResource(ctx, command) } @@ -270,6 +317,23 @@ func (s *Service) UnequipUserResource(ctx context.Context, command resourcedomai } command.AppCode = appcode.Normalize(command.AppCode) ctx = appcode.WithContext(ctx, command.AppCode) + command.ResourceType = resourcedomain.NormalizeResourceType(command.ResourceType) + if command.ResourceType == resourcedomain.TypeVIPTrialCard { + // 和装备相同,通用卸下必须发布 VIP 有效态变化,不能只删除通用装备指针。 + unequipped, state, err := s.UnequipVipTrialCard(ctx, ledger.UnequipVipTrialCardCommand{ + AppCode: command.AppCode, + RequestID: strings.TrimSpace(command.RequestID), + UserID: command.UserID, + }) + if err != nil { + return resourcedomain.UnequipUserResourceResult{}, err + } + return resourcedomain.UnequipUserResourceResult{ + ResourceType: command.ResourceType, + Unequipped: unequipped, + UpdatedAtMS: state.EvaluatedAtMS, + }, nil + } return s.repository.UnequipUserResource(ctx, command) } diff --git a/services/wallet-service/internal/service/wallet/service_test.go b/services/wallet-service/internal/service/wallet/service_test.go index fef098f5..550dad28 100644 --- a/services/wallet-service/internal/service/wallet/service_test.go +++ b/services/wallet-service/internal/service/wallet/service_test.go @@ -6253,6 +6253,17 @@ func TestPurchaseVipRenewalAlignsRewardEntitlementExpiry(t *testing.T) { // TestGrantVipUsesUnifiedActivationAndNoticeOutbox 验证后台和活动赠送 VIP 走统一激活入口并写 IM outbox。 func TestGrantVipUsesUnifiedActivationAndNoticeOutbox(t *testing.T) { repository := mysqltest.NewRepository(t) + // initdb 不为 Lalu 猜测默认礼包资源;本用例要验证“发放 VIP 同时发放礼包”, + // 因此必须显式构造资源组,不依赖历史测试库残留或运营配置。 + repository.SeedVIPRewardGroup(1, 71003, []mysqltest.VipRewardResourceSeed{ + { + ResourceID: 7100301, + ResourceCode: "vip_grant_test_frame", + ResourceType: resourcedomain.TypeAvatarFrame, + Name: "VIP Grant Test Frame", + GrantStrategy: resourcedomain.GrantStrategyExtendExpiry, + }, + }) svc := walletservice.New(repository) adminGrant, err := svc.GrantVip(context.Background(), ledger.GrantVipCommand{ @@ -6336,7 +6347,7 @@ func TestVipLevelSixIgnoresLegacyRechargeThreshold(t *testing.T) { repository.SetBalance(51002, 50000) svc := walletservice.New(repository) - currentLevels, err := svc.ListAdminVipLevels(context.Background()) + _, currentLevels, err := svc.ListAdminVipLevels(context.Background()) if err != nil { t.Fatalf("ListAdminVipLevels failed: %v", err) } @@ -6364,7 +6375,7 @@ func TestVipLevelSixIgnoresLegacyRechargeThreshold(t *testing.T) { } commands = append(commands, command) } - if _, err := svc.UpdateAdminVipLevels(context.Background(), commands, 9001); err != nil { + if _, _, err := svc.UpdateAdminVipLevels(context.Background(), commands, 9001); err != nil { t.Fatalf("UpdateAdminVipLevels failed: %v", err) } repository.SetVIPLevelRechargeThreshold(6, 5000) diff --git a/services/wallet-service/internal/service/wallet/vip.go b/services/wallet-service/internal/service/wallet/vip.go index c2995c45..751fe8d4 100644 --- a/services/wallet-service/internal/service/wallet/vip.go +++ b/services/wallet-service/internal/service/wallet/vip.go @@ -8,13 +8,13 @@ import ( "strings" ) -// ListVipPackages 返回可购买 VIP 包和当前会员状态。 -func (s *Service) ListVipPackages(ctx context.Context, userID int64) (ledger.UserVip, []ledger.VipLevel, error) { +// ListVipPackages 返回同一配置快照下的最终 VIP 状态和可购买套餐。 +func (s *Service) ListVipPackages(ctx context.Context, userID int64) (ledger.VipState, []ledger.VipLevel, error) { if userID <= 0 { - return ledger.UserVip{}, nil, xerr.New(xerr.InvalidArgument, "user_id is required") + return ledger.VipState{}, nil, xerr.New(xerr.InvalidArgument, "user_id is required") } if s.repository == nil { - return ledger.UserVip{}, nil, xerr.New(xerr.Unavailable, "wallet repository is not configured") + return ledger.VipState{}, nil, xerr.New(xerr.Unavailable, "wallet repository is not configured") } ctx = appcode.WithContext(ctx, appcode.FromContext(ctx)) return s.repository.ListVipPackages(ctx, userID) @@ -32,11 +32,50 @@ func (s *Service) GetMyVip(ctx context.Context, userID int64) (ledger.UserVip, e return s.repository.GetMyVip(ctx, userID) } +// GetVipProgramConfig 返回当前 App 的完整 VIP 规则和权益目录;不存在配置时直接失败, +// 避免业务在缺少迁移或错误 app_code 时悄悄回退到另一套体系。 +func (s *Service) GetVipProgramConfig(ctx context.Context) (ledger.VipProgramConfig, []ledger.VipBenefit, error) { + if s.repository == nil { + return ledger.VipProgramConfig{}, nil, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + ctx = appcode.WithContext(ctx, appcode.FromContext(ctx)) + return s.repository.GetVipProgramConfig(ctx) +} + +// GetVipState 统一返回付费、体验卡和最终生效状态,客户端与 owner service 都不能自行按等级合并。 +func (s *Service) GetVipState(ctx context.Context, userID int64) (ledger.VipState, error) { + if userID <= 0 { + return ledger.VipState{}, xerr.New(xerr.InvalidArgument, "user_id is required") + } + if s.repository == nil { + return ledger.VipState{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + ctx = appcode.WithContext(ctx, appcode.FromContext(ctx)) + return s.repository.GetVipState(ctx, userID) +} + +// CheckVipBenefit 是房间、用户资料和通知 owner 执行单项权益时的服务端判定入口。 +func (s *Service) CheckVipBenefit(ctx context.Context, userID int64, benefitCode string) (ledger.CheckVipBenefitResult, error) { + benefitCode = strings.ToLower(strings.TrimSpace(benefitCode)) + if userID <= 0 || benefitCode == "" { + return ledger.CheckVipBenefitResult{}, xerr.New(xerr.InvalidArgument, "user_id and benefit_code are required") + } + if s.repository == nil { + return ledger.CheckVipBenefitResult{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + ctx = appcode.WithContext(ctx, appcode.FromContext(ctx)) + return s.repository.CheckVipBenefit(ctx, userID, benefitCode) +} + // PurchaseVip 执行 VIP 购买、升级或续期;降级由 repository 在锁内按当前会员状态拒绝。 func (s *Service) PurchaseVip(ctx context.Context, command ledger.PurchaseVipCommand) (ledger.PurchaseVipReceipt, error) { + command.CommandID = strings.TrimSpace(command.CommandID) if command.CommandID == "" || command.UserID <= 0 || command.Level <= 0 { return ledger.PurchaseVipReceipt{}, xerr.New(xerr.InvalidArgument, "vip purchase command is incomplete") } + if len(command.CommandID) > 128 { + return ledger.PurchaseVipReceipt{}, xerr.New(xerr.InvalidArgument, "command_id is too long") + } if s.repository == nil { return ledger.PurchaseVipReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") } @@ -47,6 +86,7 @@ func (s *Service) PurchaseVip(ctx context.Context, command ledger.PurchaseVipCom // GrantVip 是活动和后台赠送 VIP 的统一入口;购买仍走 PurchaseVip 完成扣费。 func (s *Service) GrantVip(ctx context.Context, command ledger.GrantVipCommand) (ledger.GrantVipReceipt, error) { + command.CommandID = strings.TrimSpace(command.CommandID) if command.CommandID == "" || command.TargetUserID <= 0 || command.Level <= 0 { return ledger.GrantVipReceipt{}, xerr.New(xerr.InvalidArgument, "vip grant command is incomplete") } @@ -70,7 +110,7 @@ func (s *Service) GrantVip(ctx context.Context, command ledger.GrantVipCommand) if command.Reason == "" { command.Reason = command.GrantSource } - if len(command.Reason) > 512 { + if len(command.Reason) > 256 { return ledger.GrantVipReceipt{}, xerr.New(xerr.InvalidArgument, "reason is too long") } if s.repository == nil { @@ -81,22 +121,91 @@ func (s *Service) GrantVip(ctx context.Context, command ledger.GrantVipCommand) return s.repository.GrantVip(ctx, command) } -// ListAdminVipLevels 返回后台 VIP 配置页的 10 级配置快照。 -func (s *Service) ListAdminVipLevels(ctx context.Context) ([]ledger.VipLevel, error) { +// GrantVipTrialCard 发放独立绝对计时的背包卡片;发卡不自动佩戴,避免后台操作改变用户当前展示。 +func (s *Service) GrantVipTrialCard(ctx context.Context, command ledger.GrantVipTrialCardCommand) (ledger.GrantVipTrialCardReceipt, error) { + command.CommandID = strings.TrimSpace(command.CommandID) + command.Reason = strings.TrimSpace(command.Reason) + command.GrantSource = ledger.NormalizeVipGrantSource(command.GrantSource) + if command.CommandID == "" || command.TargetUserID <= 0 || command.Level <= 0 || command.DurationMS <= 0 { + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.InvalidArgument, "vip trial card command is incomplete") + } + if len(command.CommandID) > 128 || len(command.Reason) > 256 || command.ResourceID < 0 { + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.InvalidArgument, "vip trial card command is invalid") + } + switch command.GrantSource { + case ledger.VipGrantSourceAdmin, ledger.VipGrantSourceManagerCenter: + if command.OperatorUserID <= 0 { + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.InvalidArgument, "operator_user_id is required") + } + case ledger.VipGrantSourceActivity: + if command.OperatorUserID < 0 { + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.InvalidArgument, "operator_user_id is invalid") + } + default: + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.InvalidArgument, "vip grant_source is invalid") + } + if command.Reason == "" { + command.Reason = command.GrantSource + } if s.repository == nil { - return nil, xerr.New(xerr.Unavailable, "wallet repository is not configured") + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + command.AppCode = appcode.Normalize(command.AppCode) + ctx = appcode.WithContext(ctx, command.AppCode) + return s.repository.GrantVipTrialCard(ctx, command) +} + +// EquipVipTrialCard 只切换通用装备指针,任一卡片的 effective/expires 时间都不会变化。 +func (s *Service) EquipVipTrialCard(ctx context.Context, command ledger.EquipVipTrialCardCommand) (ledger.VipTrialCard, ledger.VipState, error) { + command.RequestID = strings.TrimSpace(command.RequestID) + command.EntitlementID = strings.TrimSpace(command.EntitlementID) + if command.RequestID == "" || command.UserID <= 0 || command.EntitlementID == "" { + return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.InvalidArgument, "vip trial equip command is incomplete") + } + if len(command.RequestID) > 128 || len(command.EntitlementID) > 96 { + return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.InvalidArgument, "vip trial equip command is invalid") + } + if s.repository == nil { + return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + command.AppCode = appcode.Normalize(command.AppCode) + ctx = appcode.WithContext(ctx, command.AppCode) + return s.repository.EquipVipTrialCard(ctx, command) +} + +// UnequipVipTrialCard 清理当前体验卡装备记录,最终状态立即回落到仍有效的付费会员。 +func (s *Service) UnequipVipTrialCard(ctx context.Context, command ledger.UnequipVipTrialCardCommand) (bool, ledger.VipState, error) { + command.RequestID = strings.TrimSpace(command.RequestID) + if command.RequestID == "" || command.UserID <= 0 { + return false, ledger.VipState{}, xerr.New(xerr.InvalidArgument, "vip trial unequip command is incomplete") + } + if len(command.RequestID) > 128 { + return false, ledger.VipState{}, xerr.New(xerr.InvalidArgument, "request_id is too long") + } + if s.repository == nil { + return false, ledger.VipState{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + command.AppCode = appcode.Normalize(command.AppCode) + ctx = appcode.WithContext(ctx, command.AppCode) + return s.repository.UnequipVipTrialCard(ctx, command) +} + +// ListAdminVipLevels 返回后台 VIP program 与动态等级的同一数据库快照。 +func (s *Service) ListAdminVipLevels(ctx context.Context) (ledger.VipProgramConfig, []ledger.VipLevel, error) { + if s.repository == nil { + return ledger.VipProgramConfig{}, nil, xerr.New(xerr.Unavailable, "wallet repository is not configured") } ctx = appcode.WithContext(ctx, appcode.FromContext(ctx)) return s.repository.ListAdminVipLevels(ctx) } // UpdateAdminVipLevels 保存后台 VIP 等级配置;完整校验下沉到 repository,保证和购买事务一致。 -func (s *Service) UpdateAdminVipLevels(ctx context.Context, levels []ledger.AdminVipLevelCommand, operatorUserID int64) ([]ledger.VipLevel, error) { +func (s *Service) UpdateAdminVipLevels(ctx context.Context, levels []ledger.AdminVipLevelCommand, operatorUserID int64) (ledger.VipProgramConfig, []ledger.VipLevel, error) { if operatorUserID <= 0 { - return nil, xerr.New(xerr.InvalidArgument, "operator_user_id is required") + return ledger.VipProgramConfig{}, nil, xerr.New(xerr.InvalidArgument, "operator_user_id is required") } if s.repository == nil { - return nil, xerr.New(xerr.Unavailable, "wallet repository is not configured") + return ledger.VipProgramConfig{}, nil, xerr.New(xerr.Unavailable, "wallet repository is not configured") } normalized := make([]ledger.AdminVipLevelCommand, 0, len(levels)) for _, level := range levels { @@ -107,3 +216,30 @@ func (s *Service) UpdateAdminVipLevels(ctx context.Context, levels []ledger.Admi ctx = appcode.WithContext(ctx, appcode.FromContext(ctx)) return s.repository.UpdateAdminVipLevels(ctx, normalized, operatorUserID) } + +// UpdateAdminVipProgramConfig 保存 App 级状态机配置;版本递增与字段白名单由 repository 在锁内处理。 +func (s *Service) UpdateAdminVipProgramConfig(ctx context.Context, command ledger.AdminVipProgramConfigCommand) (ledger.VipProgramConfig, error) { + if command.OperatorUserID <= 0 { + return ledger.VipProgramConfig{}, xerr.New(xerr.InvalidArgument, "operator_user_id is required") + } + if s.repository == nil { + return ledger.VipProgramConfig{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + command.Config.AppCode = appcode.Normalize(command.Config.AppCode) + ctx = appcode.WithContext(ctx, command.Config.AppCode) + return s.repository.UpdateAdminVipProgramConfig(ctx, command) +} + +// 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) { + return ledger.VipUserSettings{}, xerr.New(xerr.InvalidArgument, "vip user settings update is incomplete") + } + if s.repository == nil { + return ledger.VipUserSettings{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + command.AppCode = appcode.Normalize(command.AppCode) + ctx = appcode.WithContext(ctx, command.AppCode) + return s.repository.UpdateVipUserSettings(ctx, command) +} 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 new file mode 100644 index 00000000..016f9d05 --- /dev/null +++ b/services/wallet-service/internal/service/wallet/vip_configurable_integration_test.go @@ -0,0 +1,405 @@ +package wallet_test + +import ( + "context" + "strings" + "testing" + "time" + + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + "hyapp/services/wallet-service/internal/domain/ledger" + resourcedomain "hyapp/services/wallet-service/internal/domain/resource" + walletservice "hyapp/services/wallet-service/internal/service/wallet" + "hyapp/services/wallet-service/internal/testutil/mysqltest" +) + +// TestFamiVIPReplaceAndTrialCardSwitch 使用真实 MySQL repository 验证 P1 最容易回归的三条状态边界: +// 高级购买丢弃剩余时间、体验卡可跨等级自由切换且旧卡不改期、体验卡排除金币返现。 +func TestFamiVIPReplaceAndTrialCardSwitch(t *testing.T) { + repository := mysqltest.NewRepository(t) + service := walletservice.New(repository) + ctx := appcode.WithContext(context.Background(), "fami") + _, levels, err := service.ListAdminVipLevels(ctx) + if err != nil { + t.Fatalf("list Fami VIP levels failed: %v", err) + } + if len(levels) != 9 { + t.Fatalf("Fami must expose 9 configurable levels, got %d", len(levels)) + } + durationMS := int64(30 * 24 * time.Hour / time.Millisecond) + commands := make([]ledger.AdminVipLevelCommand, 0, len(levels)) + for _, level := range levels { + for index := range level.Benefits { + if level.Benefits[index].BenefitCode == ledger.VipBenefitCodeDailyCoinRebate { + // 模拟后台误把体验返现打开;保存与运行时都必须把这项硬规则收敛为 false。 + level.Benefits[index].TrialEnabled = true + level.Benefits[index].Status = ledger.VipStatusActive + level.Benefits[index].MetadataJSON = `{"coin_amount":100}` + } + } + commands = append(commands, ledger.AdminVipLevelCommand{ + Level: level.Level, + Name: level.Name, + Status: ledger.VipStatusActive, + PriceCoin: 100, + DurationMS: durationMS, + RewardResourceGroupID: 0, + SortOrder: level.SortOrder, + Benefits: level.Benefits, + }) + } + if _, _, err := service.UpdateAdminVipLevels(ctx, commands, 9001); err != nil { + t.Fatalf("enable Fami VIP levels failed: %v", err) + } + + const userID int64 = 880001 + repository.SetBalanceForApp("fami", userID, 10_000) + first, err := service.PurchaseVip(ctx, ledger.PurchaseVipCommand{AppCode: "fami", CommandID: "fami-vip-3", UserID: userID, Level: 3}) + if err != nil { + t.Fatalf("purchase Fami VIP3 failed: %v", err) + } + // command_id 与 user_id 只在 app_code 内幂等;Lalu 使用相同值必须形成独立订单和状态。 + laluCtx := appcode.WithContext(context.Background(), "lalu") + repository.SetBalanceForApp("lalu", userID, 10_000) + laluPurchase, err := service.PurchaseVip(laluCtx, ledger.PurchaseVipCommand{AppCode: "lalu", CommandID: "fami-vip-3", UserID: userID, Level: 3}) + if err != nil { + t.Fatalf("same command in Lalu app scope failed: %v", err) + } + if laluPurchase.State.ProgramConfig.ProgramType != ledger.VipProgramTypeLegacyTimed || laluPurchase.OrderID == first.OrderID { + t.Fatalf("VIP purchase must stay app-scoped: fami=%+v lalu=%+v", first, laluPurchase) + } + upgrade, err := service.PurchaseVip(ctx, ledger.PurchaseVipCommand{AppCode: "fami", CommandID: "fami-vip-4", UserID: userID, Level: 4}) + if err != nil { + t.Fatalf("upgrade Fami VIP4 failed: %v", err) + } + if upgrade.Vip.ExpiresAtMS >= first.Vip.ExpiresAtMS+durationMS/2 { + t.Fatalf("Fami upgrade incorrectly retained VIP3 remainder: first=%d upgrade=%d", first.Vip.ExpiresAtMS, upgrade.Vip.ExpiresAtMS) + } + if got := upgrade.Vip.ExpiresAtMS - upgrade.Vip.UpdatedAtMS; got < durationMS-2_000 || got > durationMS+2_000 { + t.Fatalf("Fami upgrade must reset to one configured duration, got %d want %d", got, durationMS) + } + replayedFirst, err := service.PurchaseVip(ctx, ledger.PurchaseVipCommand{AppCode: "fami", CommandID: "fami-vip-3", UserID: userID, Level: 3}) + if err != nil { + t.Fatalf("replay original VIP3 purchase failed: %v", err) + } + if replayedFirst.Vip.Level != 3 || replayedFirst.Vip.ExpiresAtMS != first.Vip.ExpiresAtMS || replayedFirst.State.PaidVip.Level != 4 { + t.Fatalf("idempotent receipt must keep original order snapshot and current state separately: first=%+v replay=%+v", first, replayedFirst) + } + paid, err := service.PurchaseVip(ctx, ledger.PurchaseVipCommand{AppCode: "fami", CommandID: "fami-vip-6", UserID: userID, Level: 6}) + if err != nil { + t.Fatalf("upgrade Fami VIP6 failed: %v", err) + } + if paid.State.PaidVip.Level != 6 { + t.Fatalf("paid VIP state mismatch: %+v", paid.State) + } + + card3, err := service.GrantVipTrialCard(ctx, ledger.GrantVipTrialCardCommand{ + AppCode: "fami", CommandID: "trial-vip-3", TargetUserID: userID, Level: 3, + DurationMS: int64(14 * 24 * time.Hour / time.Millisecond), GrantSource: ledger.VipGrantSourceAdmin, + OperatorUserID: 9001, Reason: "test trial 3", + }) + if err != nil { + t.Fatalf("grant VIP3 trial card failed: %v", err) + } + card6, err := service.GrantVipTrialCard(ctx, ledger.GrantVipTrialCardCommand{ + AppCode: "fami", CommandID: "trial-vip-6", TargetUserID: userID, Level: 6, + DurationMS: int64(20 * 24 * time.Hour / time.Millisecond), GrantSource: ledger.VipGrantSourceAdmin, + OperatorUserID: 9001, Reason: "test trial 6", + }) + if err != nil { + t.Fatalf("grant VIP6 trial card failed: %v", err) + } + if _, err := service.GrantResource(ctx, resourcedomain.GrantResourceCommand{ + AppCode: "fami", CommandID: "generic-trial-bypass", TargetUserID: userID, + ResourceID: card6.TrialCard.ResourceID, Quantity: 1, DurationMS: durationMS, + Reason: "must use dedicated vip trial grant", OperatorUserID: 9001, GrantSource: resourcedomain.GrantSourceAdmin, + }); !xerr.IsCode(err, xerr.InvalidArgument) { + t.Fatalf("generic resource grant must not bypass VIP trial metadata, got %v", err) + } + if card3.State.EffectiveSource != ledger.VipEffectiveSourcePaid || card6.State.EffectiveSource != ledger.VipEffectiveSourcePaid { + t.Fatalf("granting a card must not auto-equip it: card3=%+v card6=%+v", card3.State, card6.State) + } + + // repository 仍保留通用 equipment 能力供专用状态机内部复用,但必须拒绝外层直接调用,避免绕过 program 与 VIP outbox。 + if _, err := repository.EquipUserResource(ctx, resourcedomain.EquipUserResourceCommand{ + AppCode: "fami", RequestID: "raw-equip-trial-3", UserID: userID, + ResourceID: card3.TrialCard.ResourceID, EntitlementID: card3.TrialCard.EntitlementID, + }); !xerr.IsCode(err, xerr.InvalidArgument) || !strings.Contains(err.Error(), "VIP trial-card state machine") { + t.Fatalf("raw repository equip must reject vip_trial_card bypass, got %v", err) + } + if _, err := repository.UnequipUserResource(ctx, resourcedomain.UnequipUserResourceCommand{ + AppCode: "fami", RequestID: "raw-unequip-trial", UserID: userID, ResourceType: resourcedomain.TypeVIPTrialCard, + }); !xerr.IsCode(err, xerr.InvalidArgument) || !strings.Contains(err.Error(), "VIP trial-card state machine") { + t.Fatalf("raw repository unequip must reject vip_trial_card bypass, got %v", err) + } + + // 通用背包入口必须委托专用状态机,因此体验卡开关关闭时不能偷偷写入 equipment。 + disabledProgram := card3.State.ProgramConfig + disabledProgram.GrantMode = ledger.VipGrantModeDirectMembership + disabledProgram.TrialCardEnabled = false + if _, err := service.UpdateAdminVipProgramConfig(ctx, ledger.AdminVipProgramConfigCommand{Config: disabledProgram, OperatorUserID: 9001}); err != nil { + t.Fatalf("disable trial cards before generic equip failed: %v", err) + } + 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) { + 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 { + t.Fatalf("disabled generic trial equip must not mutate equipment, got %d rows", got) + } + disabledProgram.GrantMode = ledger.VipGrantModeTrialCard + disabledProgram.TrialCardEnabled = true + if _, err := service.UpdateAdminVipProgramConfig(ctx, ledger.AdminVipProgramConfigCommand{Config: disabledProgram, OperatorUserID: 9001}); err != nil { + t.Fatalf("restore trial cards before generic equip failed: %v", err) + } + + resourceEventsBefore := repository.CountRows("wallet_outbox", "app_code = ? AND user_id = ? AND event_type = ?", "fami", userID, "UserResourceChanged") + vipEventsBefore := repository.CountRows("wallet_outbox", "app_code = ? AND user_id = ? AND event_type = ?", "fami", userID, "VipEffectiveChanged") + genericCard3, err := service.EquipUserResource(ctx, resourcedomain.EquipUserResourceCommand{ + AppCode: "fami", RequestID: "generic-equip-trial-3", UserID: userID, + ResourceID: card3.TrialCard.ResourceID, EntitlementID: card3.TrialCard.EntitlementID, + }) + if err != nil { + t.Fatalf("generic backpack equip VIP3 trial card failed: %v", err) + } + if !genericCard3.Equipped || genericCard3.EntitlementID != card3.TrialCard.EntitlementID { + t.Fatalf("generic backpack response must return the selected equipped entitlement: %+v", genericCard3) + } + if got := repository.CountRows("wallet_outbox", "app_code = ? AND user_id = ? AND event_type = ?", "fami", userID, "UserResourceChanged"); got != resourceEventsBefore+1 { + t.Fatalf("generic trial equip must publish UserResourceChanged exactly once: before=%d after=%d", resourceEventsBefore, got) + } + if got := repository.CountRows("wallet_outbox", "app_code = ? AND user_id = ? AND event_type = ?", "fami", userID, "VipEffectiveChanged"); got != vipEventsBefore+1 { + t.Fatalf("generic trial equip must publish VipEffectiveChanged exactly once: before=%d after=%d", vipEventsBefore, got) + } + state3, err := service.GetVipState(ctx, userID) + if err != nil { + t.Fatalf("get state after generic VIP3 trial equip failed: %v", err) + } + if state3.EffectiveSource != ledger.VipEffectiveSourceTrial || state3.EffectiveVip.Level != 3 || state3.PaidVip.Level != 6 { + t.Fatalf("lower trial card must freely overlay paid VIP without destroying it: %+v", state3) + } + _, err = service.EquipUserResource(ctx, resourcedomain.EquipUserResourceCommand{ + AppCode: "fami", RequestID: "generic-equip-trial-6", UserID: userID, + ResourceID: card6.TrialCard.ResourceID, EntitlementID: card6.TrialCard.EntitlementID, + }) + if err != nil { + t.Fatalf("generic backpack switch to VIP6 trial card failed: %v", err) + } + state6, err := service.GetVipState(ctx, userID) + if err != nil { + t.Fatalf("get state after generic VIP6 trial equip failed: %v", err) + } + if state6.EffectiveVip.Level != 6 || state6.EquippedTrialCard == nil || state6.EquippedTrialCard.EntitlementID != card6.TrialCard.EntitlementID { + t.Fatalf("trial card switch mismatch: %+v", state6) + } + card3Again, _, err := service.EquipVipTrialCard(ctx, ledger.EquipVipTrialCardCommand{ + AppCode: "fami", RequestID: "equip-trial-3-again", UserID: userID, EntitlementID: card3.TrialCard.EntitlementID, + }) + if err != nil { + t.Fatalf("re-equip VIP3 trial card failed: %v", err) + } + if card3Again.ExpiresAtMS != card3.TrialCard.ExpiresAtMS { + t.Fatalf("switching cards must preserve the old card absolute expiry: first=%d again=%d", card3.TrialCard.ExpiresAtMS, card3Again.ExpiresAtMS) + } + if _, _, err := service.EquipVipTrialCard(ctx, ledger.EquipVipTrialCardCommand{ + AppCode: "fami", RequestID: "equip-trial-6-again", UserID: userID, EntitlementID: card6.TrialCard.EntitlementID, + }); err != nil { + t.Fatalf("re-equip VIP6 trial card failed: %v", err) + } + trialRebate, err := service.CheckVipBenefit(ctx, userID, ledger.VipBenefitCodeDailyCoinRebate) + if err != nil { + t.Fatalf("check trial rebate failed: %v", err) + } + if trialRebate.Allowed { + t.Fatalf("trial card must not receive daily coin rebate: %+v", trialRebate) + } + // App 级体验卡开关只控制是否参与 effective 合并,不能删除用户背包事实;关闭后应立即回落付费 VIP。 + trialProgram := trialRebate.State.ProgramConfig + trialProgram.GrantMode = ledger.VipGrantModeDirectMembership + trialProgram.TrialCardEnabled = false + if _, err := service.UpdateAdminVipProgramConfig(ctx, ledger.AdminVipProgramConfigCommand{Config: trialProgram, OperatorUserID: 9001}); err != nil { + t.Fatalf("disable Fami trial-card program failed: %v", err) + } + trialOffState, err := service.GetVipState(ctx, userID) + if err != nil { + t.Fatalf("get VIP state with trial cards disabled failed: %v", err) + } + if trialOffState.EquippedTrialCard == nil || trialOffState.EffectiveSource != ledger.VipEffectiveSourcePaid || trialOffState.EffectiveVip.Level != 6 { + t.Fatalf("disabled trial cards must remain raw inventory and fall back to paid VIP: %+v", trialOffState) + } + trialProgram.GrantMode = ledger.VipGrantModeTrialCard + trialProgram.TrialCardEnabled = true + if _, err := service.UpdateAdminVipProgramConfig(ctx, ledger.AdminVipProgramConfigCommand{Config: trialProgram, OperatorUserID: 9001}); err != nil { + t.Fatalf("restore Fami trial-card program failed: %v", err) + } + restoredTrialState, err := service.GetVipState(ctx, userID) + if err != nil || restoredTrialState.EffectiveSource != ledger.VipEffectiveSourceTrial || restoredTrialState.EquippedTrialCard == nil { + t.Fatalf("restored trial-card switch must reuse the original equipped card: state=%+v err=%v", restoredTrialState, err) + } + programOff := restoredTrialState.ProgramConfig + programOff.Status = ledger.VipStatusDisabled + if _, err := service.UpdateAdminVipProgramConfig(ctx, ledger.AdminVipProgramConfigCommand{Config: programOff, OperatorUserID: 9001}); err != nil { + t.Fatalf("disable Fami VIP program failed: %v", err) + } + disabledState, err := service.GetVipState(ctx, userID) + if err != nil || disabledState.PaidVip.Level != 6 || disabledState.EquippedTrialCard == nil || disabledState.EffectiveSource != ledger.VipEffectiveSourceNone || disabledState.EffectiveVip.Active { + t.Fatalf("disabled program must expose raw facts without authorizing VIP: state=%+v err=%v", disabledState, err) + } + programOff.Status = ledger.VipStatusActive + if _, err := service.UpdateAdminVipProgramConfig(ctx, ledger.AdminVipProgramConfigCommand{Config: programOff, OperatorUserID: 9001}); err != nil { + t.Fatalf("restore Fami VIP program failed: %v", err) + } + unequipResult, err := service.UnequipUserResource(ctx, resourcedomain.UnequipUserResourceCommand{ + AppCode: "fami", RequestID: "generic-unequip-trial", UserID: userID, ResourceType: resourcedomain.TypeVIPTrialCard, + }) + unequipped := unequipResult.Unequipped + if err != nil || !unequipped { + t.Fatalf("generic backpack unequip trial card failed: result=%+v err=%v", unequipResult, err) + } + paidState, err := service.GetVipState(ctx, userID) + if err != nil { + t.Fatalf("get state after generic trial unequip failed: %v", err) + } + if paidState.EffectiveSource != ledger.VipEffectiveSourcePaid || paidState.EffectiveVip.Level != 6 { + t.Fatalf("unequip must fall back to paid VIP6: %+v", paidState) + } + paidRebate, err := service.CheckVipBenefit(ctx, userID, ledger.VipBenefitCodeDailyCoinRebate) + if err != nil || !paidRebate.Allowed { + t.Fatalf("paid VIP6 must retain configured rebate benefit: allowed=%v err=%v result=%+v", paidRebate.Allowed, err, paidRebate) + } +} + +// TestVipPurchaseConcurrentReplayWithExactBalance 验证幂等守卫发生在账户/会员锁之前: +// 两个并发首发即使余额只够一单,也都返回同一成功回执,而不是让后到请求误报余额不足。 +func TestVipPurchaseConcurrentReplayWithExactBalance(t *testing.T) { + repository := mysqltest.NewRepository(t) + service := walletservice.New(repository) + ctx := appcode.WithContext(context.Background(), "lalu") + const userID int64 = 880003 + const commandID = "vip-concurrent-exact-balance" + repository.SetBalanceForApp("lalu", userID, 1_000) + + type purchaseResult struct { + receipt ledger.PurchaseVipReceipt + err error + } + start := make(chan struct{}) + results := make(chan purchaseResult, 2) + for range 2 { + go func() { + <-start + receipt, err := service.PurchaseVip(ctx, ledger.PurchaseVipCommand{ + AppCode: "lalu", CommandID: commandID, UserID: userID, Level: 1, + }) + results <- purchaseResult{receipt: receipt, err: err} + }() + } + close(start) + first := <-results + second := <-results + if first.err != nil || second.err != nil { + t.Fatalf("concurrent VIP replay must return two successes: first=%v second=%v", first.err, second.err) + } + if first.receipt.OrderID == "" || first.receipt.OrderID != second.receipt.OrderID || first.receipt.TransactionID != second.receipt.TransactionID { + t.Fatalf("concurrent VIP replay returned different receipts: first=%+v second=%+v", first.receipt, second.receipt) + } + 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 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) + } + if got := repository.CountRows("vip_command_locks", "app_code = ? AND command_id = ?", "lalu", commandID); got != 1 { + t.Fatalf("concurrent replay persisted %d VIP command guards, want 1", got) + } +} + +// TestVipConfigurationListsDoNotExhaustPool 覆盖曾经的连接池自锁:主 levels rows 未关闭时, +// 每个请求再从 r.db 借连接查权益,20 个并发会占满池后相互等待。当前实现先关闭游标并在原事务内装配。 +func TestVipConfigurationListsDoNotExhaustPool(t *testing.T) { + repository := mysqltest.NewRepository(t) + service := walletservice.New(repository) + base := appcode.WithContext(context.Background(), "fami") + ctx, cancel := context.WithTimeout(base, 5*time.Second) + defer cancel() + + start := make(chan struct{}) + results := make(chan error, 24) + for index := range 24 { + go func(index int) { + <-start + if index%2 == 0 { + _, _, err := service.ListAdminVipLevels(ctx) + results <- err + return + } + _, _, err := service.ListVipPackages(ctx, int64(990000+index)) + results <- err + }(index) + } + close(start) + for range 24 { + if err := <-results; err != nil { + t.Fatalf("concurrent VIP list failed before pool drain: %v", err) + } + } +} + +func TestVipProgramCanCreateAndResizeAppLevels(t *testing.T) { + repository := mysqltest.NewRepository(t) + service := walletservice.New(repository) + ctx := appcode.WithContext(context.Background(), "future_app") + base := ledger.VipProgramConfig{ + AppCode: "future_app", + ProgramType: ledger.VipProgramTypeTieredPrivilegeV1, + LevelCount: 2, + SameLevelExpiryPolicy: ledger.VipExpiryPolicyExtendRemaining, + UpgradeExpiryPolicy: ledger.VipExpiryPolicyReplaceFromNow, + DowngradePurchasePolicy: ledger.VipDowngradePurchasePolicyReject, + BenefitInheritancePolicy: ledger.VipBenefitInheritanceTargetOnly, + GrantMode: ledger.VipGrantModeTrialCard, + TrialCardEnabled: true, + Status: ledger.VipStatusActive, + } + created, err := service.UpdateAdminVipProgramConfig(ctx, ledger.AdminVipProgramConfigCommand{Config: base, OperatorUserID: 9001}) + if err != nil { + t.Fatalf("create VIP program for a new app failed: %v", err) + } + if created.ConfigVersion != 1 { + t.Fatalf("new VIP program version mismatch: %+v", created) + } + _, levels, err := service.ListAdminVipLevels(ctx) + if err != nil || len(levels) != 2 || levels[0].Status != ledger.VipStatusDisabled || levels[1].DurationMS <= 0 { + t.Fatalf("new program must materialize disabled structural levels: levels=%+v err=%v", levels, err) + } + base.LevelCount = 3 + if _, err := service.UpdateAdminVipProgramConfig(ctx, ledger.AdminVipProgramConfigCommand{Config: base, OperatorUserID: 9001}); err != nil { + t.Fatalf("grow VIP program level_count failed: %v", err) + } + _, levels, err = service.ListAdminVipLevels(ctx) + if err != nil || len(levels) != 3 || levels[2].Level != 3 || levels[2].Status != ledger.VipStatusDisabled { + t.Fatalf("grown program missing disabled placeholder: levels=%+v err=%v", levels, err) + } + commands := make([]ledger.AdminVipLevelCommand, 0, 3) + for _, level := range levels { + commands = append(commands, ledger.AdminVipLevelCommand{ + Level: level.Level, Name: level.Name, Status: ledger.VipStatusActive, + PriceCoin: 100, DurationMS: level.DurationMS, SortOrder: level.SortOrder, + }) + } + if _, _, err := service.UpdateAdminVipLevels(ctx, commands, 9001); err != nil { + t.Fatalf("activate grown VIP levels failed: %v", err) + } + base.LevelCount = 2 + if _, err := service.UpdateAdminVipProgramConfig(ctx, ledger.AdminVipProgramConfigCommand{Config: base, OperatorUserID: 9001}); err != nil { + t.Fatalf("shrink VIP program level_count failed: %v", err) + } + 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) { + t.Fatalf("level above current level_count must be unreachable, got %v", err) + } +} diff --git a/services/wallet-service/internal/service/wallet/vip_daily_coin_rebate.go b/services/wallet-service/internal/service/wallet/vip_daily_coin_rebate.go new file mode 100644 index 00000000..d243233b --- /dev/null +++ b/services/wallet-service/internal/service/wallet/vip_daily_coin_rebate.go @@ -0,0 +1,116 @@ +package wallet + +import ( + "context" + "strings" + "time" + + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + "hyapp/services/wallet-service/internal/domain/ledger" +) + +const vipDailyCoinRebateTaskDayLayout = "2006-01-02" + +// ProcessVipDailyCoinRebateBatch 只接受 UTC 日期,不接受时区偏移。空 task_day 使用 wallet owner +// 当前 UTC 日期,使调度方无需也不能自行决定业务切日。 +func (s *Service) ProcessVipDailyCoinRebateBatch(ctx context.Context, command ledger.ProcessVipDailyCoinRebateBatchCommand) (ledger.ProcessVipDailyCoinRebateBatchResult, error) { + if s.repository == nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + command.AppCode = appcode.Normalize(command.AppCode) + now := s.now().UTC() + command.NowMS = now.UnixMilli() + command.TaskDay = strings.TrimSpace(command.TaskDay) + if command.TaskDay == "" { + command.TaskDay = now.Format(vipDailyCoinRebateTaskDayLayout) + } + dayStart, err := time.ParseInLocation(vipDailyCoinRebateTaskDayLayout, command.TaskDay, time.UTC) + if err != nil || dayStart.Format(vipDailyCoinRebateTaskDayLayout) != command.TaskDay { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, xerr.New(xerr.InvalidArgument, "task_day must be an UTC date in YYYY-MM-DD") + } + if dayStart.After(now) { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, xerr.New(xerr.InvalidArgument, "future vip rebate task_day is not allowed") + } + if command.BatchSize <= 0 { + command.BatchSize = 100 + } + if command.BatchSize > 500 { + command.BatchSize = 500 + } + ctx = appcode.WithContext(ctx, command.AppCode) + return s.repository.ProcessVipDailyCoinRebateBatch(ctx, command) +} + +// GetMyCurrentVipDailyCoinRebate 查询当前 UTC 日返现;没有记录是正常状态,以 found=false 表达。 +func (s *Service) GetMyCurrentVipDailyCoinRebate(ctx context.Context, userID int64) (ledger.VipDailyCoinRebate, bool, error) { + if userID <= 0 { + return ledger.VipDailyCoinRebate{}, false, xerr.New(xerr.InvalidArgument, "user_id is required") + } + if s.repository == nil { + return ledger.VipDailyCoinRebate{}, false, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + nowMS := s.now().UTC().UnixMilli() + ctx = appcode.WithContext(ctx, appcode.FromContext(ctx)) + return s.repository.GetMyCurrentVipDailyCoinRebate(ctx, userID, nowMS) +} + +// ListMyVipDailyCoinRebateStatuses 返回用户历史记录;expired 由 wallet owner 使用当前 UTC 时钟投影。 +func (s *Service) ListMyVipDailyCoinRebateStatuses(ctx context.Context, query ledger.ListVipDailyCoinRebateStatusesQuery) ([]ledger.VipDailyCoinRebate, int64, error) { + if query.UserID <= 0 { + return nil, 0, xerr.New(xerr.InvalidArgument, "user_id is required") + } + if s.repository == nil { + return nil, 0, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + query.AppCode = appcode.Normalize(query.AppCode) + if query.Page <= 0 { + query.Page = 1 + } + if query.PageSize <= 0 { + query.PageSize = 20 + } + if query.PageSize > 100 { + query.PageSize = 100 + } + if len(query.RebateIDs) > 100 { + return nil, 0, xerr.New(xerr.InvalidArgument, "rebate_ids cannot contain more than 100 items") + } + seenRebateIDs := make(map[string]struct{}, len(query.RebateIDs)) + normalizedRebateIDs := make([]string, 0, len(query.RebateIDs)) + for _, rebateID := range query.RebateIDs { + rebateID = strings.TrimSpace(rebateID) + if rebateID == "" || len(rebateID) > 96 { + return nil, 0, xerr.New(xerr.InvalidArgument, "rebate_ids contains an invalid id") + } + if _, exists := seenRebateIDs[rebateID]; exists { + continue + } + seenRebateIDs[rebateID] = struct{}{} + normalizedRebateIDs = append(normalizedRebateIDs, rebateID) + } + query.RebateIDs = normalizedRebateIDs + query.NowMS = s.now().UTC().UnixMilli() + ctx = appcode.WithContext(ctx, query.AppCode) + return s.repository.ListMyVipDailyCoinRebateStatuses(ctx, query) +} + +// ClaimVipDailyCoinRebate 只校验命令形状;可领取窗口、金额、付费 VIP 快照和余额变更均在 +// repository 的同一行锁事务内裁决,客户端无法提交金额或延长过期时间。 +func (s *Service) ClaimVipDailyCoinRebate(ctx context.Context, command ledger.ClaimVipDailyCoinRebateCommand) (ledger.ClaimVipDailyCoinRebateReceipt, error) { + command.AppCode = appcode.Normalize(command.AppCode) + command.CommandID = strings.TrimSpace(command.CommandID) + command.RebateID = strings.TrimSpace(command.RebateID) + if command.CommandID == "" || command.UserID <= 0 || command.RebateID == "" { + return ledger.ClaimVipDailyCoinRebateReceipt{}, xerr.New(xerr.InvalidArgument, "vip daily coin rebate claim command is incomplete") + } + if len(command.CommandID) > 128 || len(command.RebateID) > 96 { + return ledger.ClaimVipDailyCoinRebateReceipt{}, xerr.New(xerr.InvalidArgument, "vip daily coin rebate claim command is invalid") + } + if s.repository == nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + command.NowMS = s.now().UTC().UnixMilli() + ctx = appcode.WithContext(ctx, command.AppCode) + return s.repository.ClaimVipDailyCoinRebate(ctx, command) +} diff --git a/services/wallet-service/internal/service/wallet/vip_daily_coin_rebate_integration_test.go b/services/wallet-service/internal/service/wallet/vip_daily_coin_rebate_integration_test.go new file mode 100644 index 00000000..c01c2f3e --- /dev/null +++ b/services/wallet-service/internal/service/wallet/vip_daily_coin_rebate_integration_test.go @@ -0,0 +1,421 @@ +package wallet_test + +import ( + "context" + "encoding/json" + "strings" + "testing" + "time" + + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + "hyapp/services/wallet-service/internal/domain/ledger" + walletservice "hyapp/services/wallet-service/internal/service/wallet" + "hyapp/services/wallet-service/internal/testutil/mysqltest" +) + +// TestVipDailyCoinRebateUTCWindowSnapshotAndClaim 覆盖返现最关键的不可变边界: +// UTC 日切资格、run 配置快照、分页重放、App 隔离、available outbox 和并发领取仅入账一次。 +func TestVipDailyCoinRebateUTCWindowSnapshotAndClaim(t *testing.T) { + repository := mysqltest.NewRepository(t) + service := walletservice.New(repository) + now := time.Now().UTC() + dayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC) + dayStartMS := dayStart.UnixMilli() + dayEndMS := dayStart.Add(24 * time.Hour).UnixMilli() + taskDay := dayStart.Format("2006-01-02") + famiCtx := appcode.WithContext(context.Background(), "fami") + + repository.SetVIPDailyCoinRebateAmount("fami", 6, 60, ledger.VipStatusActive) + repository.SetVIPDailyCoinRebateAmount("fami", 7, 70, ledger.VipStatusActive) + // started==day_start 与 expires>day_start 均为有效;开始晚 1ms、到期恰好落在 day_start 均无资格。 + repository.SeedPaidVIPAtWindow("fami", 910001, 6, dayStartMS, dayEndMS) + repository.SeedPaidVIPAtWindow("fami", 910002, 6, dayStartMS+1, dayEndMS) + repository.SeedPaidVIPAtWindow("fami", 910003, 6, dayStartMS-1000, dayStartMS) + repository.SeedPaidVIPAtWindow("fami", 910004, 7, dayStartMS-1000, dayStartMS+1) + + firstPage, err := service.ProcessVipDailyCoinRebateBatch(famiCtx, ledger.ProcessVipDailyCoinRebateBatchCommand{ + AppCode: "fami", TaskDay: taskDay, BatchSize: 1, + }) + if err != nil { + t.Fatalf("process first VIP rebate page failed: %v", err) + } + if firstPage.CreatedCount != 1 || !firstPage.HasMore || firstPage.Run.LevelAmounts[6] != 60 || firstPage.Run.LevelAmounts[7] != 70 { + t.Fatalf("first VIP rebate page snapshot mismatch: %+v", firstPage) + } + initialConfigVersion := firstPage.Run.ConfigVersion + // run 创建后改价不能污染剩余页;VIP7 仍必须按 70 生成,而不是新值 700。 + repository.SetVIPDailyCoinRebateAmount("fami", 7, 700, ledger.VipStatusActive) + var completed ledger.ProcessVipDailyCoinRebateBatchResult + createdAfterConfigChange := 0 + for page := 0; page < 10; page++ { + current, pageErr := service.ProcessVipDailyCoinRebateBatch(famiCtx, ledger.ProcessVipDailyCoinRebateBatchCommand{ + AppCode: "fami", TaskDay: taskDay, BatchSize: 1, + }) + if pageErr != nil { + t.Fatalf("process remaining VIP rebate page failed: %v", pageErr) + } + if current.Run.ConfigVersion != initialConfigVersion || current.Run.LevelAmounts[7] != 70 { + t.Fatalf("existing run must keep original config snapshot: first=%+v current=%+v", firstPage.Run, current.Run) + } + createdAfterConfigChange += current.CreatedCount + completed = current + if !current.HasMore { + break + } + } + if createdAfterConfigChange != 1 || completed.HasMore || completed.Run.Status != ledger.VipDailyCoinRebateRunStatusCompleted { + t.Fatalf("complete VIP rebate run failed: created=%d result=%+v", createdAfterConfigChange, completed) + } + // 完成后任意重放都只返回已有 run,不重复返现或 outbox。 + replayed, err := service.ProcessVipDailyCoinRebateBatch(famiCtx, ledger.ProcessVipDailyCoinRebateBatchCommand{ + AppCode: "fami", TaskDay: taskDay, BatchSize: 500, + }) + if err != nil || replayed.CreatedCount != 0 || replayed.HasMore { + t.Fatalf("completed VIP rebate replay must be a no-op: result=%+v err=%v", replayed, err) + } + if got := repository.CountRows("vip_daily_coin_rebates", "app_code = ? AND task_day = ?", "fami", taskDay); got != 2 { + t.Fatalf("UTC boundary must create exactly two Fami rebates, got %d", got) + } + if got := repository.CountRows("wallet_outbox", "app_code = ? AND event_type = ?", "fami", "VipDailyCoinRebateAvailable"); got != 2 { + t.Fatalf("available outbox must be one-to-one with rebates, got %d", got) + } + + rebate6, found, err := service.GetMyCurrentVipDailyCoinRebate(famiCtx, 910001) + if err != nil || !found || rebate6.CoinAmount != 60 || rebate6.AvailableAtMS != dayStartMS || rebate6.ExpiresAtMS != dayEndMS { + t.Fatalf("current VIP6 rebate mismatch: found=%v rebate=%+v err=%v", found, rebate6, err) + } + rebate7, found, err := service.GetMyCurrentVipDailyCoinRebate(famiCtx, 910004) + if err != nil || !found || rebate7.CoinAmount != 70 { + t.Fatalf("current VIP7 rebate must use run snapshot: found=%v rebate=%+v err=%v", found, rebate7, err) + } + if _, found, err := service.GetMyCurrentVipDailyCoinRebate(famiCtx, 910002); err != nil || found { + t.Fatalf("membership starting after day_start must not receive rebate: found=%v err=%v", found, err) + } + + var availablePayload map[string]any + if err := json.Unmarshal([]byte(repository.WalletOutboxPayload("fami", "VipDailyCoinRebateAvailable", 910001)), &availablePayload); err != nil { + t.Fatalf("decode available outbox payload failed: %v", err) + } + for _, key := range []string{"rebate_id", "user_id", "task_day", "vip_level", "vip_name", "coin_amount", "available_at_ms", "expires_at_ms", "config_version", "created_at_ms"} { + if _, exists := availablePayload[key]; !exists { + t.Fatalf("available outbox payload missing %s: %+v", key, availablePayload) + } + } + + statuses, total, err := service.ListMyVipDailyCoinRebateStatuses(famiCtx, ledger.ListVipDailyCoinRebateStatusesQuery{ + AppCode: "fami", UserID: 910001, RebateIDs: []string{rebate6.RebateID, rebate7.RebateID}, Page: 1, PageSize: 20, + }) + if err != nil || total != 1 || len(statuses) != 1 || statuses[0].RebateID != rebate6.RebateID { + t.Fatalf("rebate_ids status lookup must remain user scoped: items=%+v total=%d err=%v", statuses, total, err) + } + + type claimResult struct { + receipt ledger.ClaimVipDailyCoinRebateReceipt + err error + } + start := make(chan struct{}) + results := make(chan claimResult, 2) + for range 2 { + go func() { + <-start + receipt, claimErr := service.ClaimVipDailyCoinRebate(famiCtx, ledger.ClaimVipDailyCoinRebateCommand{ + AppCode: "fami", CommandID: "claim-vip-rebate-concurrent", UserID: 910001, RebateID: rebate6.RebateID, + }) + results <- claimResult{receipt: receipt, err: claimErr} + }() + } + close(start) + left, right := <-results, <-results + if left.err != nil || right.err != nil || left.receipt.TransactionID == "" || left.receipt.TransactionID != right.receipt.TransactionID { + t.Fatalf("concurrent claim replay must return same success: left=%+v right=%+v", left, right) + } + if left.receipt.CoinBalance.AvailableAmount != 60 || right.receipt.CoinBalance.AvailableAmount != 60 { + t.Fatalf("concurrent claim must credit once: left=%+v right=%+v", left.receipt.CoinBalance, right.receipt.CoinBalance) + } + if got := repository.CountRows("wallet_transactions", "app_code = ? AND biz_type = ? AND external_ref = ?", "fami", "vip_daily_coin_rebate", rebate6.RebateID); got != 1 { + t.Fatalf("concurrent claim created %d wallet transactions, want 1", got) + } + if got := repository.CountRows("wallet_entries", "app_code = ? AND transaction_id = ?", "fami", left.receipt.TransactionID); got != 1 { + t.Fatalf("concurrent claim created %d wallet entries, want 1", got) + } + // 不同 command 的重复点击仍返回原交易;但已使用 command 改投另一 rebate 必须是稳定幂等冲突。 + retry, err := service.ClaimVipDailyCoinRebate(famiCtx, ledger.ClaimVipDailyCoinRebateCommand{ + AppCode: "fami", CommandID: "claim-vip-rebate-second-click", UserID: 910001, RebateID: rebate6.RebateID, + }) + if err != nil || retry.TransactionID != left.receipt.TransactionID || retry.CoinBalance.AvailableAmount != 60 { + t.Fatalf("different-command repeat click must return original receipt: receipt=%+v err=%v", retry, err) + } + _, err = service.ClaimVipDailyCoinRebate(famiCtx, ledger.ClaimVipDailyCoinRebateCommand{ + AppCode: "fami", CommandID: "claim-vip-rebate-second-click", UserID: 910004, RebateID: rebate7.RebateID, + }) + if !xerr.IsCode(err, xerr.IdempotencyConflict) { + t.Fatalf("successful repeat-click command must be consumed for its original rebate, got %v", err) + } + _, err = service.ClaimVipDailyCoinRebate(famiCtx, ledger.ClaimVipDailyCoinRebateCommand{ + AppCode: "fami", CommandID: "claim-vip-rebate-concurrent", UserID: 910004, RebateID: rebate7.RebateID, + }) + if !xerr.IsCode(err, xerr.IdempotencyConflict) { + t.Fatalf("same command with another rebate must return IDEMPOTENCY_CONFLICT, got %v", err) + } + + // 相同 user/task_day 在另一个 App 形成独立 run、rebate 和账户,不共享任何幂等事实。 + laluCtx := appcode.WithContext(context.Background(), "lalu") + repository.SetVIPDailyCoinRebateAmount("lalu", 1, 11, ledger.VipStatusActive) + repository.SeedPaidVIPAtWindow("lalu", 910001, 1, dayStartMS, dayEndMS) + laluRun, err := service.ProcessVipDailyCoinRebateBatch(laluCtx, ledger.ProcessVipDailyCoinRebateBatchCommand{ + AppCode: "lalu", TaskDay: taskDay, BatchSize: 100, + }) + if err != nil || laluRun.CreatedCount != 1 { + t.Fatalf("process Lalu isolated rebate failed: result=%+v err=%v", laluRun, err) + } + laluRebate, found, err := service.GetMyCurrentVipDailyCoinRebate(laluCtx, 910001) + if err != nil || !found || laluRebate.CoinAmount != 11 || laluRebate.RebateID == rebate6.RebateID { + t.Fatalf("VIP rebate must stay App isolated: fami=%+v lalu=%+v found=%v err=%v", rebate6, laluRebate, found, err) + } +} + +// TestVipDailyCoinRebateLegacyZeroExpiryHistoryUsesMigrationBaseline 固定 060 老库兼容边界: +// ALTER 产生的 0 有效期 history 不能覆盖会员主表事实;基线只补无完整快照用户且可重入。 +func TestVipDailyCoinRebateLegacyZeroExpiryHistoryUsesMigrationBaseline(t *testing.T) { + repository := mysqltest.NewRepository(t) + service := walletservice.New(repository) + ctx := appcode.WithContext(context.Background(), "fami") + now := time.Now().UTC() + dayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC) + dayStartMS := dayStart.UnixMilli() + dayEndMS := dayStart.Add(24 * time.Hour).UnixMilli() + + repository.SetVIPDailyCoinRebateAmount("fami", 6, 606, ledger.VipStatusActive) + // 940101 只有旧 0 有效期 history,应被基线补齐;940102 已有新格式快照,迁移不得再插行。 + repository.SeedLegacyPaidVIPAtWindow("fami", 940101, 6, dayStartMS-1_000, dayEndMS) + repository.SeedPaidVIPAtWindow("fami", 940102, 6, dayStartMS-1_000, dayEndMS) + repository.ApplyVIPHistoryMigrationBaseline(dayStartMS - 500) + repository.ApplyVIPHistoryMigrationBaseline(dayStartMS - 500) + if got := repository.CountRows("user_vip_history", "app_code = ? AND order_id = ?", "fami", "vip_configurable_060_baseline"); got != 1 { + t.Fatalf("migration baseline must be idempotent and skip complete histories, got %d rows", got) + } + if got := repository.CountRows("user_vip_history", "app_code = ? AND user_id = ?", "fami", 940102); got != 1 { + t.Fatalf("complete new-format history must remain untouched, got %d rows", got) + } + if got := repository.CountRows("user_vip_history", "app_code = ? AND user_id = ? AND new_expires_at_ms = 0", "fami", 940101); got != 1 { + t.Fatalf("migration must not rewrite legacy zero-expiry history, got %d rows", got) + } + + // 基线执行后再造一条旧数据,单独验证 repository 忽略 0 快照并回退 current membership。 + repository.SeedLegacyPaidVIPAtWindow("fami", 940103, 6, dayStartMS-1_000, dayEndMS) + result, err := service.ProcessVipDailyCoinRebateBatch(ctx, ledger.ProcessVipDailyCoinRebateBatchCommand{ + AppCode: "fami", TaskDay: dayStart.Format("2006-01-02"), BatchSize: 100, + }) + if err != nil || result.CreatedCount != 3 || result.HasMore { + t.Fatalf("legacy VIP rebate recovery mismatch: result=%+v err=%v", result, err) + } + for _, userID := range []int64{940101, 940102, 940103} { + rebate, found, queryErr := service.GetMyCurrentVipDailyCoinRebate(ctx, userID) + if queryErr != nil || !found || rebate.VipLevel != 6 || rebate.CoinAmount != 606 { + t.Fatalf("recovered VIP rebate mismatch for user %d: found=%v rebate=%+v err=%v", userID, found, rebate, queryErr) + } + } +} + +// TestVipDailyCoinRebateLatestLegacyHistoryDoesNotReviveOlderSnapshot 验证排序与有效性判定的先后顺序: +// 边界前最新行是迁移零值时,不得越过它选中更旧但完整的 VIP 快照。 +func TestVipDailyCoinRebateLatestLegacyHistoryDoesNotReviveOlderSnapshot(t *testing.T) { + repository := mysqltest.NewRepository(t) + service := walletservice.New(repository) + ctx := appcode.WithContext(context.Background(), "fami") + now := time.Now().UTC() + dayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC) + dayStartMS := dayStart.UnixMilli() + dayEndMS := dayStart.Add(24 * time.Hour).UnixMilli() + + repository.SetVIPDailyCoinRebateAmount("fami", 6, 606, ledger.VipStatusActive) + // 较旧完整行看似有效到日终;较新旧格式行的有效期未知,当前会员于日切恰好到期。 + repository.SeedPaidVIPAtWindow("fami", 940201, 6, dayStartMS-2_000, dayEndMS) + repository.SeedLegacyPaidVIPAtWindow("fami", 940201, 6, dayStartMS-1_000, dayStartMS) + result, err := service.ProcessVipDailyCoinRebateBatch(ctx, ledger.ProcessVipDailyCoinRebateBatchCommand{ + AppCode: "fami", TaskDay: dayStart.Format("2006-01-02"), BatchSize: 100, + }) + if err != nil || result.CreatedCount != 0 || result.HasMore { + t.Fatalf("newer incomplete history must block older VIP snapshot revival: result=%+v err=%v", result, err) + } + if _, found, queryErr := service.GetMyCurrentVipDailyCoinRebate(ctx, 940201); queryErr != nil || found { + t.Fatalf("stale older VIP snapshot unexpectedly created rebate: found=%v err=%v", found, queryErr) + } +} + +// TestVipDailyCoinRebateExpiredAndNotFoundCodes 固定客户端依赖的 404/409 原因码。 +func TestVipDailyCoinRebateExpiredAndNotFoundCodes(t *testing.T) { + repository := mysqltest.NewRepository(t) + service := walletservice.New(repository) + ctx := appcode.WithContext(context.Background(), "fami") + now := time.Now().UTC() + todayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC) + yesterdayStart := todayStart.Add(-24 * time.Hour) + repository.SetVIPDailyCoinRebateAmount("fami", 6, 66, ledger.VipStatusActive) + repository.SeedPaidVIPAtWindow("fami", 920001, 6, yesterdayStart.UnixMilli(), todayStart.UnixMilli()) + result, err := service.ProcessVipDailyCoinRebateBatch(ctx, ledger.ProcessVipDailyCoinRebateBatchCommand{ + AppCode: "fami", TaskDay: yesterdayStart.Format("2006-01-02"), BatchSize: 100, + }) + if err != nil || result.CreatedCount != 1 { + t.Fatalf("create expired rebate fixture failed: result=%+v err=%v", result, err) + } + items, _, err := service.ListMyVipDailyCoinRebateStatuses(ctx, ledger.ListVipDailyCoinRebateStatusesQuery{ + AppCode: "fami", UserID: 920001, Page: 1, PageSize: 20, + }) + if err != nil || len(items) != 1 || items[0].Status != ledger.VipDailyCoinRebateStatusExpired { + t.Fatalf("expired status projection mismatch: items=%+v err=%v", items, err) + } + _, err = service.ClaimVipDailyCoinRebate(ctx, ledger.ClaimVipDailyCoinRebateCommand{ + AppCode: "fami", CommandID: "claim-expired-vip-rebate", UserID: 920001, RebateID: items[0].RebateID, + }) + if !xerr.IsCode(err, xerr.VIPCoinRebateExpired) { + t.Fatalf("expired claim must return VIP_COIN_REBATE_EXPIRED, got %v", err) + } + _, err = service.ClaimVipDailyCoinRebate(ctx, ledger.ClaimVipDailyCoinRebateCommand{ + AppCode: "fami", CommandID: "claim-missing-vip-rebate", UserID: 920001, RebateID: "vip_rebate_missing", + }) + if !xerr.IsCode(err, xerr.VIPCoinRebateNotFound) { + t.Fatalf("missing claim must return VIP_COIN_REBATE_NOT_FOUND, got %v", err) + } +} + +// TestVipDailyCoinRebateConcurrentRunCreation 覆盖两个 cron worker 同时首次触发同一天: +// 等待 program 锁的后到事务必须 current-read 复用已提交 run,不能在旧 RR 快照上撞唯一键。 +func TestVipDailyCoinRebateConcurrentRunCreation(t *testing.T) { + repository := mysqltest.NewRepository(t) + service := walletservice.New(repository) + ctx := appcode.WithContext(context.Background(), "fami") + now := time.Now().UTC() + dayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC) + taskDay := dayStart.Format("2006-01-02") + repository.SetVIPDailyCoinRebateAmount("fami", 6, 88, ledger.VipStatusActive) + repository.SeedPaidVIPAtWindow("fami", 930001, 6, dayStart.UnixMilli(), dayStart.Add(24*time.Hour).UnixMilli()) + + type batchResult struct { + result ledger.ProcessVipDailyCoinRebateBatchResult + err error + } + start := make(chan struct{}) + results := make(chan batchResult, 2) + for range 2 { + go func() { + <-start + result, err := service.ProcessVipDailyCoinRebateBatch(ctx, ledger.ProcessVipDailyCoinRebateBatchCommand{ + AppCode: "fami", TaskDay: taskDay, BatchSize: 100, + }) + results <- batchResult{result: result, err: err} + }() + } + close(start) + left, right := <-results, <-results + if left.err != nil || right.err != nil || left.result.Run.RunID == "" || left.result.Run.RunID != right.result.Run.RunID { + t.Fatalf("concurrent run creation must return one stable run: left=%+v right=%+v", left, right) + } + if got := repository.CountRows("vip_daily_coin_rebate_runs", "app_code = ? AND task_day = ?", "fami", taskDay); got != 1 { + t.Fatalf("concurrent run creation persisted %d runs, want 1", got) + } + if got := repository.CountRows("vip_daily_coin_rebates", "app_code = ? AND task_day = ?", "fami", taskDay); got != 1 { + t.Fatalf("concurrent run creation persisted %d rebates, want 1", got) + } + if got := repository.CountRows("wallet_outbox", "app_code = ? AND event_type = ?", "fami", "VipDailyCoinRebateAvailable"); got != 1 { + t.Fatalf("concurrent run creation persisted %d available events, want 1", got) + } +} + +// TestVipDailyCoinRebateDisabledEmptyMetadataCanBeSaved 确保后台可先关闭权益并提交空对象, +// 但一旦启用就必须配置正 int64 coin_amount。 +func TestVipDailyCoinRebateDisabledEmptyMetadataCanBeSaved(t *testing.T) { + repository := mysqltest.NewRepository(t) + service := walletservice.New(repository) + ctx := appcode.WithContext(context.Background(), "fami") + _, levels, err := service.ListAdminVipLevels(ctx) + if err != nil { + t.Fatalf("list VIP levels failed: %v", err) + } + commands := make([]ledger.AdminVipLevelCommand, 0, len(levels)) + for _, level := range levels { + for index := range level.Benefits { + if level.Benefits[index].BenefitCode == ledger.VipBenefitCodeDailyCoinRebate { + level.Benefits[index].Status = ledger.VipStatusDisabled + level.Benefits[index].MetadataJSON = `{}` + } + } + commands = append(commands, ledger.AdminVipLevelCommand{ + Level: level.Level, Name: level.Name, Status: level.Status, PriceCoin: level.PriceCoin, + DurationMS: level.DurationMS, RewardResourceGroupID: level.RewardResourceGroupID, + SortOrder: level.SortOrder, Benefits: level.Benefits, + }) + } + if _, _, err := service.UpdateAdminVipLevels(ctx, commands, 9001); err != nil { + t.Fatalf("disabled daily rebate with empty metadata object must save: %v", err) + } + for commandIndex := range commands { + for benefitIndex := range commands[commandIndex].Benefits { + benefit := &commands[commandIndex].Benefits[benefitIndex] + if benefit.BenefitCode == ledger.VipBenefitCodeDailyCoinRebate { + benefit.Status = ledger.VipStatusActive + benefit.MetadataJSON = `{}` + _, _, err = service.UpdateAdminVipLevels(ctx, commands, 9001) + if !xerr.IsCode(err, xerr.InvalidArgument) { + t.Fatalf("active daily rebate without coin_amount must be invalid, got %v", err) + } + return + } + } + } + t.Fatal("Fami VIP config missing daily_coin_rebate fixture") +} + +// TestVipOnlineGlobalNoticeMetadataValidation 固定 notice owner 契约:message 可省略,存在时必须 +// 是 1..256 个非空字符,且 execution_scope 不能被后台改到 room/user。 +func TestVipOnlineGlobalNoticeMetadataValidation(t *testing.T) { + repository := mysqltest.NewRepository(t) + service := walletservice.New(repository) + ctx := appcode.WithContext(context.Background(), "fami") + _, levels, err := service.ListAdminVipLevels(ctx) + if err != nil { + t.Fatalf("list VIP levels failed: %v", err) + } + commands := make([]ledger.AdminVipLevelCommand, 0, len(levels)) + for _, level := range levels { + for index := range level.Benefits { + benefit := &level.Benefits[index] + if benefit.BenefitCode == ledger.VipBenefitCodeOnlineGlobalNotice { + benefit.MetadataJSON = `{}` + } + } + commands = append(commands, ledger.AdminVipLevelCommand{ + Level: level.Level, Name: level.Name, Status: level.Status, PriceCoin: level.PriceCoin, + DurationMS: level.DurationMS, RewardResourceGroupID: level.RewardResourceGroupID, + SortOrder: level.SortOrder, Benefits: level.Benefits, + }) + } + if _, _, err := service.UpdateAdminVipLevels(ctx, commands, 9001); err != nil { + t.Fatalf("online notice metadata without message must save: %v", err) + } + for commandIndex := range commands { + for benefitIndex := range commands[commandIndex].Benefits { + benefit := &commands[commandIndex].Benefits[benefitIndex] + if benefit.BenefitCode != ledger.VipBenefitCodeOnlineGlobalNotice { + continue + } + benefit.MetadataJSON = `{"message":" "}` + if _, _, err := service.UpdateAdminVipLevels(ctx, commands, 9001); !xerr.IsCode(err, xerr.InvalidArgument) { + t.Fatalf("blank online notice message must be invalid, got %v", err) + } + payload, _ := json.Marshal(map[string]string{"message": strings.Repeat("好", 257)}) + benefit.MetadataJSON = string(payload) + if _, _, err := service.UpdateAdminVipLevels(ctx, commands, 9001); !xerr.IsCode(err, xerr.InvalidArgument) { + t.Fatalf("257-character online notice message must be invalid, got %v", err) + } + benefit.MetadataJSON = `{"message":"hello"}` + benefit.ExecutionScope = ledger.VipExecutionScopeRoom + if _, _, err := service.UpdateAdminVipLevels(ctx, commands, 9001); !xerr.IsCode(err, xerr.InvalidArgument) { + t.Fatalf("online notice non-notice scope must be invalid, got %v", err) + } + return + } + } + t.Fatal("Fami VIP config missing online_global_notice fixture") +} 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 new file mode 100644 index 00000000..96168131 --- /dev/null +++ b/services/wallet-service/internal/service/wallet/vip_user_settings_integration_test.go @@ -0,0 +1,148 @@ +package wallet_test + +import ( + "context" + "testing" + "time" + + "hyapp/pkg/appcode" + "hyapp/services/wallet-service/internal/domain/ledger" + walletservice "hyapp/services/wallet-service/internal/service/wallet" + "hyapp/services/wallet-service/internal/testutil/mysqltest" +) + +// TestVipUserSettingsDefaultPartialUpdateAndAppScope 验证设置不授予/删除权益,且无行默认、 +// partial PATCH、付费/体验来源和 App 隔离都由 wallet owner 使用同一规则处理。 +func TestVipUserSettingsDefaultPartialUpdateAndAppScope(t *testing.T) { + repository := mysqltest.NewRepository(t) + service := walletservice.New(repository) + famiCtx := appcode.WithContext(context.Background(), "fami") + laluCtx := appcode.WithContext(context.Background(), "lalu") + const paidUserID int64 = 940001 + + defaultState, err := service.GetVipState(famiCtx, paidUserID) + if err != nil { + t.Fatalf("get default VIP settings failed: %v", err) + } + if !defaultState.UserSettings.RoomEntryNoticeEnabled || !defaultState.UserSettings.OnlineGlobalNoticeEnabled || 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 { + t.Fatalf("read must not materialize default settings row, got %d", got) + } + + roomOff := false + settings, err := service.UpdateVipUserSettings(famiCtx, ledger.UpdateVipUserSettingsCommand{ + AppCode: "fami", UserID: paidUserID, RoomEntryNoticeEnabled: &roomOff, + }) + if err != nil || settings.RoomEntryNoticeEnabled || !settings.OnlineGlobalNoticeEnabled || settings.UpdatedAtMS <= 0 { + t.Fatalf("first partial settings update mismatch: settings=%+v err=%v", settings, err) + } + onlineOff := false + settings, err = service.UpdateVipUserSettings(famiCtx, ledger.UpdateVipUserSettingsCommand{ + AppCode: "fami", UserID: paidUserID, OnlineGlobalNoticeEnabled: &onlineOff, + }) + if err != nil || settings.RoomEntryNoticeEnabled || settings.OnlineGlobalNoticeEnabled { + 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 { + t.Fatalf("same user settings must remain App scoped: state=%+v err=%v", laluState.UserSettings, err) + } + + // 两个客户端并发修改不同字段时,partial upsert 必须串行保留双方结果。 + const concurrentUserID int64 = 940003 + startUpdates := make(chan struct{}) + updateErrors := make(chan error, 2) + go func() { + <-startUpdates + _, updateErr := service.UpdateVipUserSettings(famiCtx, ledger.UpdateVipUserSettingsCommand{ + AppCode: "fami", UserID: concurrentUserID, RoomEntryNoticeEnabled: &roomOff, + }) + updateErrors <- updateErr + }() + go func() { + <-startUpdates + _, updateErr := service.UpdateVipUserSettings(famiCtx, ledger.UpdateVipUserSettingsCommand{ + AppCode: "fami", UserID: concurrentUserID, OnlineGlobalNoticeEnabled: &onlineOff, + }) + updateErrors <- updateErr + }() + close(startUpdates) + if leftErr, rightErr := <-updateErrors, <-updateErrors; leftErr != nil || rightErr != nil { + t.Fatalf("concurrent partial settings update failed: left=%v right=%v", leftErr, rightErr) + } + concurrentState, err := service.GetVipState(famiCtx, concurrentUserID) + if err != nil || concurrentState.UserSettings.RoomEntryNoticeEnabled || concurrentState.UserSettings.OnlineGlobalNoticeEnabled { + t.Fatalf("concurrent partial updates overwrote each other: settings=%+v err=%v", concurrentState.UserSettings, err) + } + + // 设置可在无 VIP 时保存,但 CheckVipBenefit 仍优先返回 vip_inactive,不能让偏好变成授权。 + inactiveCheck, err := service.CheckVipBenefit(famiCtx, paidUserID, ledger.VipBenefitCodeRoomEntryNotice) + if err != nil || inactiveCheck.Allowed || inactiveCheck.DenialReason != "vip_inactive" { + t.Fatalf("settings must not grant VIP benefit: result=%+v err=%v", inactiveCheck, err) + } + + now := time.Now().UTC() + repository.SeedPaidVIPAtWindow("fami", paidUserID, 9, now.Add(-time.Hour).UnixMilli(), now.Add(time.Hour).UnixMilli()) + paidState, err := service.GetVipState(famiCtx, paidUserID) + if err != nil || paidState.EffectiveSource != ledger.VipEffectiveSourcePaid { + t.Fatalf("get paid VIP state failed: state=%+v err=%v", paidState, err) + } + if !containsVipBenefit(paidState.EffectiveBenefits, ledger.VipBenefitCodeRoomEntryNotice) || !containsVipBenefit(paidState.EffectiveBenefits, ledger.VipBenefitCodeOnlineGlobalNotice) { + t.Fatalf("disabled user settings must not delete owned effective benefits: %+v", paidState.EffectiveBenefits) + } + for _, code := range []string{ledger.VipBenefitCodeRoomEntryNotice, ledger.VipBenefitCodeOnlineGlobalNotice} { + result, checkErr := service.CheckVipBenefit(famiCtx, paidUserID, code) + if checkErr != nil || result.Allowed || result.DenialReason != "user_setting_disabled" || result.Benefit.BenefitCode != code { + t.Fatalf("paid VIP user setting gate mismatch for %s: result=%+v err=%v", code, result, checkErr) + } + } + roomOn := true + settings, err = service.UpdateVipUserSettings(famiCtx, ledger.UpdateVipUserSettingsCommand{ + AppCode: "fami", UserID: paidUserID, RoomEntryNoticeEnabled: &roomOn, + }) + if err != nil || !settings.RoomEntryNoticeEnabled || settings.OnlineGlobalNoticeEnabled { + t.Fatalf("partial re-enable must preserve online=false: settings=%+v err=%v", settings, err) + } + roomCheck, err := service.CheckVipBenefit(famiCtx, paidUserID, ledger.VipBenefitCodeRoomEntryNotice) + if err != nil || !roomCheck.Allowed { + t.Fatalf("enabled paid room entry benefit must be allowed: result=%+v err=%v", roomCheck, err) + } + + // 体验卡与付费 VIP 共用同一设置门禁;佩戴后 effective_benefits 仍保留资格,执行结果为 disabled。 + const trialUserID int64 = 940002 + repository.SetVIPLevelStatusForApp("fami", 8, ledger.VipStatusActive, 100) + grant, err := service.GrantVipTrialCard(famiCtx, ledger.GrantVipTrialCardCommand{ + AppCode: "fami", CommandID: "settings-trial-grant", TargetUserID: trialUserID, + Level: 8, DurationMS: int64(24 * time.Hour / time.Millisecond), + GrantSource: ledger.VipGrantSourceAdmin, OperatorUserID: 9001, Reason: "settings test", + }) + if err != nil { + t.Fatalf("grant trial VIP for settings test failed: %v", err) + } + if _, _, err := service.EquipVipTrialCard(famiCtx, ledger.EquipVipTrialCardCommand{ + AppCode: "fami", RequestID: "settings-trial-equip", UserID: trialUserID, + EntitlementID: grant.TrialCard.EntitlementID, + }); err != nil { + t.Fatalf("equip trial VIP for settings test failed: %v", err) + } + if _, err := service.UpdateVipUserSettings(famiCtx, ledger.UpdateVipUserSettingsCommand{ + AppCode: "fami", UserID: trialUserID, RoomEntryNoticeEnabled: &roomOff, + }); err != nil { + t.Fatalf("disable trial user room entry setting failed: %v", err) + } + trialCheck, err := service.CheckVipBenefit(famiCtx, trialUserID, ledger.VipBenefitCodeRoomEntryNotice) + if err != nil || trialCheck.Allowed || trialCheck.DenialReason != "user_setting_disabled" || trialCheck.State.EffectiveSource != ledger.VipEffectiveSourceTrial || !containsVipBenefit(trialCheck.State.EffectiveBenefits, ledger.VipBenefitCodeRoomEntryNotice) { + t.Fatalf("trial VIP user setting gate mismatch: result=%+v err=%v", trialCheck, err) + } +} + +func containsVipBenefit(items []ledger.VipBenefit, code string) bool { + for _, item := range items { + if item.BenefitCode == code { + return true + } + } + return false +} diff --git a/services/wallet-service/internal/service/wallet/vip_validation_test.go b/services/wallet-service/internal/service/wallet/vip_validation_test.go new file mode 100644 index 00000000..ad7d1944 --- /dev/null +++ b/services/wallet-service/internal/service/wallet/vip_validation_test.go @@ -0,0 +1,93 @@ +package wallet + +import ( + "context" + "strings" + "testing" + + "hyapp/pkg/xerr" + "hyapp/services/wallet-service/internal/domain/ledger" +) + +// TestVipCommandStorageLengthsFailBeforeRepository keeps external strings within the VARCHAR +// boundaries used by transactions, outbox and entitlement identifiers; violations must be 4xx, +// never a MySQL data-too-long error surfaced as 5xx. +func TestVipCommandStorageLengthsFailBeforeRepository(t *testing.T) { + service := New(nil) + testCases := []struct { + name string + run func() error + }{ + { + name: "purchase command id", + run: func() error { + _, err := service.PurchaseVip(context.Background(), ledger.PurchaseVipCommand{ + CommandID: strings.Repeat("x", 129), UserID: 1, Level: 1, + }) + return err + }, + }, + { + name: "direct grant command id", + run: func() error { + _, err := service.GrantVip(context.Background(), ledger.GrantVipCommand{ + CommandID: strings.Repeat("x", 129), TargetUserID: 1, Level: 1, + GrantSource: ledger.VipGrantSourceAdmin, OperatorUserID: 1, + }) + return err + }, + }, + { + name: "equip request id", + run: func() error { + _, _, err := service.EquipVipTrialCard(context.Background(), ledger.EquipVipTrialCardCommand{ + RequestID: strings.Repeat("x", 129), UserID: 1, EntitlementID: "ent-1", + }) + return err + }, + }, + { + name: "equip entitlement id", + run: func() error { + _, _, err := service.EquipVipTrialCard(context.Background(), ledger.EquipVipTrialCardCommand{ + RequestID: "req-1", UserID: 1, EntitlementID: strings.Repeat("x", 97), + }) + return err + }, + }, + { + name: "unequip request id", + run: func() error { + _, _, err := service.UnequipVipTrialCard(context.Background(), ledger.UnequipVipTrialCardCommand{ + RequestID: strings.Repeat("x", 129), UserID: 1, + }) + return err + }, + }, + { + name: "rebate claim command id", + run: func() error { + _, err := service.ClaimVipDailyCoinRebate(context.Background(), ledger.ClaimVipDailyCoinRebateCommand{ + CommandID: strings.Repeat("x", 129), UserID: 1, RebateID: "vip_rebate_1", + }) + return err + }, + }, + { + name: "rebate id", + run: func() error { + _, err := service.ClaimVipDailyCoinRebate(context.Background(), ledger.ClaimVipDailyCoinRebateCommand{ + CommandID: "claim-rebate", UserID: 1, RebateID: strings.Repeat("x", 97), + }) + return err + }, + }, + } + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + if err := testCase.run(); !xerr.IsCode(err, xerr.InvalidArgument) { + t.Fatalf("oversized VIP identifier must be invalid argument, got %v", err) + } + }) + } +} diff --git a/services/wallet-service/internal/storage/mysql/app_wallet_constants.go b/services/wallet-service/internal/storage/mysql/app_wallet_constants.go index 9a635e58..fae5ba2c 100644 --- a/services/wallet-service/internal/storage/mysql/app_wallet_constants.go +++ b/services/wallet-service/internal/storage/mysql/app_wallet_constants.go @@ -3,6 +3,7 @@ package mysql const ( bizTypeVIPPurchase = "vip_purchase" bizTypeVIPGrant = "vip_grant" + bizTypeVIPTrialCardGrant = "vip_trial_card_grant" vipOutboxAsset = "VIP" managerCenterVIPGrantDurationMS = 30 * 24 * 60 * 60 * 1000 ) diff --git a/services/wallet-service/internal/storage/mysql/constants.go b/services/wallet-service/internal/storage/mysql/constants.go index ddd230eb..d2be5e2f 100644 --- a/services/wallet-service/internal/storage/mysql/constants.go +++ b/services/wallet-service/internal/storage/mysql/constants.go @@ -33,6 +33,7 @@ const ( bizTypeHostSalarySettlement = "host_salary_settlement" bizTypeCPBreakupFee = "cp_breakup_fee" bizTypeWheelDrawDebit = "wheel_draw_debit" + bizTypeVipDailyCoinRebate = "vip_daily_coin_rebate" outboxStatusPending = "pending" outboxStatusDelivering = "delivering" outboxStatusDelivered = "delivered" diff --git a/services/wallet-service/internal/storage/mysql/recharge_stats_repository.go b/services/wallet-service/internal/storage/mysql/recharge_stats_repository.go new file mode 100644 index 00000000..93576c9a --- /dev/null +++ b/services/wallet-service/internal/storage/mysql/recharge_stats_repository.go @@ -0,0 +1,73 @@ +package mysql + +import ( + "context" + "fmt" + + "hyapp/pkg/appcode" + "hyapp/services/wallet-service/internal/domain/ledger" +) + +const maxBatchRechargeStatsUsers = 500 + +// BatchGetUserRechargeStats 批量读取 owner 维护的累计表;输入先去重,避免 IN 参数和返回行无意义膨胀。 +func (r *Repository) BatchGetUserRechargeStats(ctx context.Context, userIDs []int64) ([]ledger.UserRechargeStats, error) { + userIDs = uniquePositiveUserIDs(userIDs) + if len(userIDs) == 0 { + return []ledger.UserRechargeStats{}, nil + } + if len(userIDs) > maxBatchRechargeStatsUsers { + return nil, fmt.Errorf("too many user ids: %d", len(userIDs)) + } + args := make([]any, 0, len(userIDs)+1) + args = append(args, appcode.FromContext(ctx)) + for _, userID := range userIDs { + args = append(args, userID) + } + rows, err := r.db.QueryContext(ctx, ` + SELECT user_id, recharge_count, total_coin_amount, total_usd_minor_amount, + first_recharged_at_ms, updated_at_ms + FROM wallet_user_recharge_stats + WHERE app_code = ? AND user_id IN (`+placeholders(len(userIDs))+`) + ORDER BY user_id ASC`, args...) + if err != nil { + return nil, err + } + defer rows.Close() + + items := make([]ledger.UserRechargeStats, 0, len(userIDs)) + for rows.Next() { + var item ledger.UserRechargeStats + if err := rows.Scan( + &item.UserID, + &item.RechargeCount, + &item.TotalCoinAmount, + &item.TotalUSDMinorAmount, + &item.FirstRechargedAtMS, + &item.UpdatedAtMS, + ); err != nil { + return nil, err + } + items = append(items, item) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +func uniquePositiveUserIDs(values []int64) []int64 { + seen := make(map[int64]struct{}, len(values)) + result := make([]int64, 0, len(values)) + for _, value := range values { + if value <= 0 { + continue + } + if _, ok := seen[value]; ok { + continue + } + seen[value] = struct{}{} + result = append(result, value) + } + return result +} diff --git a/services/wallet-service/internal/storage/mysql/recharge_stats_repository_test.go b/services/wallet-service/internal/storage/mysql/recharge_stats_repository_test.go new file mode 100644 index 00000000..4c973a46 --- /dev/null +++ b/services/wallet-service/internal/storage/mysql/recharge_stats_repository_test.go @@ -0,0 +1,41 @@ +package mysql + +import ( + "context" + "regexp" + "testing" + + "github.com/DATA-DOG/go-sqlmock" + "hyapp/pkg/appcode" +) + +func TestBatchGetUserRechargeStatsUsesAggregateTableAndDeduplicatesIDs(t *testing.T) { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("create sqlmock: %v", err) + } + defer db.Close() + + mock.ExpectQuery(regexp.QuoteMeta(` + SELECT user_id, recharge_count, total_coin_amount, total_usd_minor_amount, + first_recharged_at_ms, updated_at_ms + FROM wallet_user_recharge_stats + WHERE app_code = ? AND user_id IN (?,?) + ORDER BY user_id ASC`)). + WithArgs("lalu", int64(1001), int64(1002)). + WillReturnRows(sqlmock.NewRows([]string{ + "user_id", "recharge_count", "total_coin_amount", "total_usd_minor_amount", "first_recharged_at_ms", "updated_at_ms", + }).AddRow(int64(1001), int64(3), int64(9000), int64(1250), int64(1700000000000), int64(1700000005000))) + + repo := &Repository{db: db} + items, err := repo.BatchGetUserRechargeStats(appcode.WithContext(context.Background(), "lalu"), []int64{1001, 0, 1002, 1001}) + if err != nil { + t.Fatalf("BatchGetUserRechargeStats failed: %v", err) + } + if len(items) != 1 || items[0].UserID != 1001 || items[0].TotalUSDMinorAmount != 1250 || items[0].RechargeCount != 3 { + t.Fatalf("unexpected recharge stats: %+v", items) + } + if err := mock.ExpectationsWereMet(); err != nil { + t.Fatalf("unmet sql expectations: %v", err) + } +} 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 36020310..6342f8b0 100644 --- a/services/wallet-service/internal/storage/mysql/resource_entitlement_repository.go +++ b/services/wallet-service/internal/storage/mysql/resource_entitlement_repository.go @@ -84,6 +84,10 @@ func (r *Repository) EquipUserResource(ctx context.Context, command resourcedoma if err != nil { return resourcedomain.UserResourceEntitlement{}, err } + if resourcedomain.NormalizeResourceType(entitlement.Resource.ResourceType) == resourcedomain.TypeVIPTrialCard { + // 只有 service 的通用背包适配层可以把体验卡委托给专用状态机;仓储直写会绕过 program 开关和 VIP outbox。 + return resourcedomain.UserResourceEntitlement{}, xerr.New(xerr.InvalidArgument, "vip_trial_card must use the VIP trial-card state machine") + } if !isEquipableResourceType(entitlement.Resource.ResourceType) { return resourcedomain.UserResourceEntitlement{}, xerr.New(xerr.InvalidArgument, "resource_type cannot be equipped") } @@ -122,6 +126,10 @@ func (r *Repository) UnequipUserResource(ctx context.Context, command resourcedo if command.UserID <= 0 || command.ResourceType == "" { return resourcedomain.UnequipUserResourceResult{}, xerr.New(xerr.InvalidArgument, "user_id and resource_type are required") } + if command.ResourceType == resourcedomain.TypeVIPTrialCard { + // 防御性拒绝仓储直写;公开通用入口会在 service 层委托 UnequipVipTrialCard 并发布完整状态事件。 + return resourcedomain.UnequipUserResourceResult{}, xerr.New(xerr.InvalidArgument, "vip_trial_card must use the VIP trial-card state machine") + } if !resourcedomain.ValidResourceType(command.ResourceType) || !isEquipableResourceType(command.ResourceType) { return resourcedomain.UnequipUserResourceResult{}, xerr.New(xerr.InvalidArgument, "resource_type cannot be equipped") } @@ -599,7 +607,7 @@ func (r *Repository) pruneExpiredUserResourceEquipment(ctx context.Context, user func isEquipableResourceType(resourceType string) bool { switch resourcedomain.NormalizeResourceType(resourceType) { - case resourcedomain.TypeAvatarFrame, resourcedomain.TypeProfileCard, resourcedomain.TypeVehicle, resourcedomain.TypeChatBubble, resourcedomain.TypeBadge, resourcedomain.TypeMicSeatAnimation: + case resourcedomain.TypeAvatarFrame, resourcedomain.TypeProfileCard, resourcedomain.TypeVehicle, resourcedomain.TypeChatBubble, resourcedomain.TypeBadge, resourcedomain.TypeMicSeatAnimation, resourcedomain.TypeVIPTrialCard: return true default: return false 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 1b883c60..9d42a33e 100644 --- a/services/wallet-service/internal/storage/mysql/resource_grant_repository.go +++ b/services/wallet-service/internal/storage/mysql/resource_grant_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" "strconv" "strings" @@ -44,6 +45,9 @@ func (r *Repository) GrantResource(ctx context.Context, command resourcedomain.G if err != nil { return resourcedomain.ResourceGrant{}, err } + if resourcedomain.NormalizeResourceType(resource.ResourceType) == resourcedomain.TypeVIPTrialCard { + return resourcedomain.ResourceGrant{}, xerr.New(xerr.InvalidArgument, "vip_trial_card must use GrantVipTrialCard") + } if err := validateGrantableResourceForSource(resource, command.GrantSource); err != nil { return resourcedomain.ResourceGrant{}, err } @@ -119,6 +123,9 @@ func (r *Repository) GrantResourceGroup(ctx context.Context, command resourcedom } continue } + if resourcedomain.NormalizeResourceType(item.Resource.ResourceType) == resourcedomain.TypeVIPTrialCard { + return resourcedomain.ResourceGrant{}, xerr.New(xerr.InvalidArgument, "resource group cannot grant vip_trial_card") + } if err := validateActiveResourceGroupResource(item.Resource); err != nil { return resourcedomain.ResourceGrant{}, err } @@ -580,6 +587,17 @@ func (r *Repository) revokeGrantedEntitlement(ctx context.Context, tx *sql.Tx, g ); err != nil { return walletOutboxEvent{}, err } + // VIP 体验卡的业务元数据与通用 entitlement 同事务撤销;否则后台审计会残留 active 卡片, + // 虽然状态查询因 entitlement 失效不会继续授权,仍会形成两套互相矛盾的事实。 + 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, grant.TargetUserID, + item.EntitlementID, ledger.VipTrialCardStatusActive, + ); err != nil { + return walletOutboxEvent{}, err + } } eventCommandID := resourceGrantRevokeCommandID(command, grant.GrantID, item.GrantItemID) diff --git a/services/wallet-service/internal/storage/mysql/resource_repository_test.go b/services/wallet-service/internal/storage/mysql/resource_repository_test.go index 2382cf98..8a981b45 100644 --- a/services/wallet-service/internal/storage/mysql/resource_repository_test.go +++ b/services/wallet-service/internal/storage/mysql/resource_repository_test.go @@ -14,6 +14,15 @@ func TestDecorativeResourceTypesAreEquipable(t *testing.T) { } } +func TestVIPTrialCardUsesInternalSingleSelectEquipmentSlot(t *testing.T) { + if !isEquipableResourceType(resourcedomain.TypeVIPTrialCard) { + t.Fatalf("vip_trial_card dedicated state machine must reuse the internal equipment slot") + } + if allowsMultipleEquippedResources(resourcedomain.TypeVIPTrialCard) { + t.Fatalf("vip_trial_card equipment must keep exactly one current card") + } +} + func TestGrantDefaultEquippedResourceTypes(t *testing.T) { for _, resourceType := range []string{resourcedomain.TypeBadge, resourcedomain.TypeMicSeatAnimation} { if !isAutoEquippedOnGrantResourceType(resourceType) { diff --git a/services/wallet-service/internal/storage/mysql/transaction.go b/services/wallet-service/internal/storage/mysql/transaction.go index 8ff64214..21796efc 100644 --- a/services/wallet-service/internal/storage/mysql/transaction.go +++ b/services/wallet-service/internal/storage/mysql/transaction.go @@ -45,6 +45,31 @@ func (r *Repository) lookupTransactionWithConflictCode(ctx context.Context, tx * return txRow, true, nil } +// lookupTransactionConsistent 不对不存在的唯一键做 gap lock,供能在 INSERT duplicate 后安全回读的命令使用。 +// 这避免两个同 command 首发都持 gap lock、再以相反顺序等待业务行锁和唯一键插入造成死锁。 +func (r *Repository) lookupTransactionConsistent(ctx context.Context, tx *sql.Tx, commandID string, requestHash string, bizType string, conflictCode xerr.Code) (transactionRow, bool, error) { + row := tx.QueryRowContext(ctx, + `SELECT transaction_id, request_hash, biz_type, COALESCE(CAST(metadata_json AS CHAR), '{}') + FROM wallet_transactions + WHERE app_code = ? AND command_id = ?`, + appcode.FromContext(ctx), + commandID, + ) + var txRow transactionRow + var storedHash string + var storedBizType string + if err := row.Scan(&txRow.TransactionID, &storedHash, &storedBizType, &txRow.MetadataJSON); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return transactionRow{}, false, nil + } + return transactionRow{}, false, err + } + if storedHash != requestHash || storedBizType != bizType { + return transactionRow{}, true, xerr.New(conflictCode, "wallet command idempotency conflict") + } + return txRow, true, nil +} + func (r *Repository) insertTransaction(ctx context.Context, tx *sql.Tx, transactionID string, commandID string, bizType string, requestHash string, externalRef string, metadata any, nowMs int64) error { metadataJSON, err := json.Marshal(metadata) if err != nil { 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 623d5b06..205456b7 100644 --- a/services/wallet-service/internal/storage/mysql/vip_admin_repository.go +++ b/services/wallet-service/internal/storage/mysql/vip_admin_repository.go @@ -3,111 +3,227 @@ package mysql import ( "context" "database/sql" + "encoding/json" + "errors" "hyapp/pkg/appcode" "hyapp/pkg/xerr" "hyapp/services/wallet-service/internal/domain/ledger" resourcedomain "hyapp/services/wallet-service/internal/domain/resource" + "strconv" "strings" "time" + "unicode/utf8" ) -// UpdateAdminVipLevels 保存完整 10 级 VIP 配置。 -func (r *Repository) UpdateAdminVipLevels(ctx context.Context, levels []ledger.AdminVipLevelCommand, operatorUserID int64) ([]ledger.VipLevel, error) { +const vipPlaceholderDurationMS int64 = 30 * 24 * 60 * 60 * 1000 + +// UpdateAdminVipLevels 按 program.level_count 保存完整等级与每级显式权益集合。 +// 每次变更同时递增 config_version,使 room/user 等执行方能够识别最新权限快照。 +func (r *Repository) UpdateAdminVipLevels(ctx context.Context, levels []ledger.AdminVipLevelCommand, operatorUserID int64) (ledger.VipProgramConfig, []ledger.VipLevel, error) { if r == nil || r.db == nil { - return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + return ledger.VipProgramConfig{}, nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") } if operatorUserID <= 0 { - return nil, xerr.New(xerr.InvalidArgument, "operator_user_id is required") + return ledger.VipProgramConfig{}, nil, xerr.New(xerr.InvalidArgument, "operator_user_id is required") } - normalized, err := normalizeAdminVipLevelCommands(levels) - if err != nil { - return nil, err - } - tx, err := r.db.BeginTx(ctx, nil) if err != nil { - return nil, err + return ledger.VipProgramConfig{}, nil, err } defer func() { _ = tx.Rollback() }() - nowMs := time.Now().UnixMilli() + program, err := r.queryVipProgramConfig(ctx, tx.QueryRowContext(ctx, vipProgramSelectSQL()+` FOR UPDATE`, appcode.FromContext(ctx))) + if errors.Is(err, sql.ErrNoRows) { + return ledger.VipProgramConfig{}, nil, xerr.New(xerr.NotFound, "vip program config not found") + } + if err != nil { + return ledger.VipProgramConfig{}, nil, err + } + normalized, err := normalizeAdminVipLevelCommands(levels, program) + if err != nil { + return ledger.VipProgramConfig{}, nil, err + } + + nowMS := time.Now().UnixMilli() for _, level := range normalized { - if level.Status == ledger.VipStatusActive { + if level.Status == ledger.VipStatusActive && level.RewardResourceGroupID > 0 { if err := r.requireActiveResourceGroup(ctx, tx, level.RewardResourceGroupID); err != nil { - return nil, err + return ledger.VipProgramConfig{}, nil, err } } if _, err := tx.ExecContext(ctx, ` INSERT INTO vip_levels ( app_code, level, name, status, price_coin, duration_ms, reward_resource_group_id, required_recharge_coin_amount, sort_order, created_at_ms, updated_at_ms - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ) VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?) ON DUPLICATE KEY UPDATE - name = VALUES(name), - status = VALUES(status), - price_coin = VALUES(price_coin), - duration_ms = VALUES(duration_ms), - reward_resource_group_id = VALUES(reward_resource_group_id), - required_recharge_coin_amount = VALUES(required_recharge_coin_amount), - sort_order = VALUES(sort_order), + name = VALUES(name), status = VALUES(status), price_coin = VALUES(price_coin), + duration_ms = VALUES(duration_ms), reward_resource_group_id = VALUES(reward_resource_group_id), + required_recharge_coin_amount = 0, sort_order = VALUES(sort_order), updated_at_ms = VALUES(updated_at_ms)`, - appcode.FromContext(ctx), - level.Level, - level.Name, - level.Status, - level.PriceCoin, - level.DurationMS, - level.RewardResourceGroupID, - level.RequiredRechargeCoinAmount, - level.SortOrder, - nowMs, - nowMs, + appcode.FromContext(ctx), level.Level, level.Name, level.Status, level.PriceCoin, + level.DurationMS, level.RewardResourceGroupID, level.SortOrder, nowMS, nowMS, ); err != nil { - return nil, err + return ledger.VipProgramConfig{}, nil, err + } + // 请求携带的是该等级最终完整集合,因此先删后插,明确支持运营移除权益且不做 unlock_level 自动继承。 + if _, err := tx.ExecContext(ctx, `DELETE FROM vip_level_benefits WHERE app_code = ? AND level = ?`, appcode.FromContext(ctx), level.Level); err != nil { + return ledger.VipProgramConfig{}, nil, err + } + for _, benefit := range level.Benefits { + if err := r.validateAdminVipBenefit(ctx, tx, level.Level, benefit); err != nil { + return ledger.VipProgramConfig{}, nil, err + } + var metadata any + if strings.TrimSpace(benefit.MetadataJSON) != "" { + metadata = benefit.MetadataJSON + } + if _, err := tx.ExecContext(ctx, ` + INSERT INTO vip_level_benefits ( + app_code, level, benefit_code, name, benefit_type, unlock_level, status, + trial_enabled, resource_id, resource_type, execution_scope, auto_equip, + sort_order, metadata_json, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + appcode.FromContext(ctx), level.Level, benefit.BenefitCode, benefit.Name, + benefit.BenefitType, benefit.UnlockLevel, benefit.Status, benefit.TrialEnabled, + benefit.ResourceID, benefit.ResourceType, benefit.ExecutionScope, benefit.AutoEquip, + benefit.SortOrder, metadata, nowMS, nowMS, + ); err != nil { + return ledger.VipProgramConfig{}, nil, err + } } } - if err := tx.Commit(); err != nil { - return nil, err + if _, err := tx.ExecContext(ctx, ` + UPDATE vip_program_configs + SET config_version = config_version + 1, updated_by_admin_id = ?, updated_at_ms = ? + WHERE app_code = ?`, operatorUserID, nowMS, appcode.FromContext(ctx)); err != nil { + return ledger.VipProgramConfig{}, nil, err } + if err := tx.Commit(); err != nil { + return ledger.VipProgramConfig{}, nil, err + } + // 提交后用单独 repeatable-read 快照返回 program+levels;即使另一管理员紧接着更新,回包也不会跨版本拼接。 return r.ListAdminVipLevels(ctx) } -func normalizeAdminVipLevelCommands(levels []ledger.AdminVipLevelCommand) ([]ledger.AdminVipLevelCommand, error) { - if len(levels) != 10 { - return nil, xerr.New(xerr.InvalidArgument, "vip config requires exactly 10 levels") +// UpdateAdminVipProgramConfig 只接受服务端已实现的策略组合,并在锁内递增配置版本。 +func (r *Repository) UpdateAdminVipProgramConfig(ctx context.Context, command ledger.AdminVipProgramConfigCommand) (ledger.VipProgramConfig, error) { + if r == nil || r.db == nil { + return ledger.VipProgramConfig{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") } - byLevel := make(map[int32]ledger.AdminVipLevelCommand, 10) + config := normalizeAdminVipProgramConfig(command.Config) + if err := validateAdminVipProgramConfig(config); err != nil { + return ledger.VipProgramConfig{}, err + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return ledger.VipProgramConfig{}, err + } + defer func() { _ = tx.Rollback() }() + + nowMS := time.Now().UnixMilli() + if _, err := tx.ExecContext(ctx, ` + INSERT INTO vip_program_configs ( + app_code, program_type, level_count, same_level_expiry_policy, + upgrade_expiry_policy, downgrade_purchase_policy, benefit_inheritance_policy, + grant_mode, trial_card_enabled, status, config_version, updated_by_admin_id, + created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?) + ON DUPLICATE KEY UPDATE + program_type = VALUES(program_type), level_count = VALUES(level_count), + same_level_expiry_policy = VALUES(same_level_expiry_policy), + upgrade_expiry_policy = VALUES(upgrade_expiry_policy), + downgrade_purchase_policy = VALUES(downgrade_purchase_policy), + benefit_inheritance_policy = VALUES(benefit_inheritance_policy), + grant_mode = VALUES(grant_mode), trial_card_enabled = VALUES(trial_card_enabled), + status = VALUES(status), config_version = config_version + 1, + updated_by_admin_id = VALUES(updated_by_admin_id), updated_at_ms = VALUES(updated_at_ms)`, + appcode.FromContext(ctx), config.ProgramType, config.LevelCount, config.SameLevelExpiryPolicy, + config.UpgradeExpiryPolicy, config.DowngradePurchasePolicy, + config.BenefitInheritancePolicy, config.GrantMode, config.TrialCardEnabled, + config.Status, command.OperatorUserID, nowMS, nowMS, + ); err != nil { + return ledger.VipProgramConfig{}, err + } + // level_count 增大或新 App 首次建体系时,事务内补齐不可购买的结构占位等级。 + // 价格和资源组保持 0,只有运营随后提交完整等级配置并显式启用后才能进入购买链路。 + for level := int32(1); level <= config.LevelCount; level++ { + if _, err := tx.ExecContext(ctx, ` + INSERT IGNORE INTO vip_levels ( + app_code, level, name, status, price_coin, duration_ms, + reward_resource_group_id, required_recharge_coin_amount, sort_order, + created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, 0, ?, 0, 0, ?, ?, ?)`, + appcode.FromContext(ctx), level, "VIP"+strconv.Itoa(int(level)), ledger.VipStatusDisabled, + vipPlaceholderDurationMS, level*10, nowMS, nowMS, + ); err != nil { + return ledger.VipProgramConfig{}, err + } + } + config, err = r.queryVipProgramConfig(ctx, tx.QueryRowContext(ctx, vipProgramSelectSQL(), appcode.FromContext(ctx))) + if err != nil { + return ledger.VipProgramConfig{}, err + } + if err := tx.Commit(); err != nil { + return ledger.VipProgramConfig{}, err + } + return config, nil +} + +func normalizeAdminVipLevelCommands(levels []ledger.AdminVipLevelCommand, program ledger.VipProgramConfig) ([]ledger.AdminVipLevelCommand, error) { + if int32(len(levels)) != program.LevelCount { + return nil, xerr.New(xerr.InvalidArgument, "vip config level count does not match program") + } + byLevel := make(map[int32]ledger.AdminVipLevelCommand, len(levels)) for _, level := range levels { level.Name = strings.TrimSpace(level.Name) level.Status = strings.ToLower(strings.TrimSpace(level.Status)) if level.Status == "" { level.Status = ledger.VipStatusDisabled } - if level.Level < 1 || level.Level > 10 { - return nil, xerr.New(xerr.InvalidArgument, "vip level must be between 1 and 10") + if level.Level < 1 || level.Level > program.LevelCount { + return nil, xerr.New(xerr.InvalidArgument, "vip level is outside program level_count") } if _, exists := byLevel[level.Level]; exists { return nil, xerr.New(xerr.InvalidArgument, "vip level is duplicated") } - // 累充门槛字段仅保留数据库和 proto 兼容性;后台保存任意等级时都归零,防止旧客户端把历史门槛重新写入生效数据。 level.RequiredRechargeCoinAmount = 0 - if err := validateAdminVipLevelCommand(level); err != nil { + benefitCodes := make(map[string]struct{}, len(level.Benefits)) + for index := range level.Benefits { + benefit := &level.Benefits[index] + benefit.BenefitCode = strings.ToLower(strings.TrimSpace(benefit.BenefitCode)) + benefit.Name = strings.TrimSpace(benefit.Name) + benefit.BenefitType = strings.ToLower(strings.TrimSpace(benefit.BenefitType)) + benefit.Status = strings.ToLower(strings.TrimSpace(benefit.Status)) + benefit.ResourceType = resourcedomain.NormalizeResourceType(benefit.ResourceType) + benefit.ExecutionScope = strings.ToLower(strings.TrimSpace(benefit.ExecutionScope)) + benefit.MetadataJSON = strings.TrimSpace(benefit.MetadataJSON) + // 体验卡永远不参与金币返现;保存时强制收敛,运行时仍会按编码再次兜底。 + if benefit.BenefitCode == ledger.VipBenefitCodeDailyCoinRebate { + benefit.TrialEnabled = false + } + if _, exists := benefitCodes[benefit.BenefitCode]; benefit.BenefitCode == "" || exists { + return nil, xerr.New(xerr.InvalidArgument, "vip benefit code is empty or duplicated") + } + benefitCodes[benefit.BenefitCode] = struct{}{} + } + if err := validateAdminVipLevelCommand(level, program); err != nil { return nil, err } byLevel[level.Level] = level } - normalized := make([]ledger.AdminVipLevelCommand, 0, 10) - for level := int32(1); level <= 10; level++ { + normalized := make([]ledger.AdminVipLevelCommand, 0, program.LevelCount) + for level := int32(1); level <= program.LevelCount; level++ { item, ok := byLevel[level] if !ok { - return nil, xerr.New(xerr.InvalidArgument, "vip config requires levels 1 to 10") + return nil, xerr.New(xerr.InvalidArgument, "vip config requires a complete level sequence") } normalized = append(normalized, item) } return normalized, nil } -func validateAdminVipLevelCommand(level ledger.AdminVipLevelCommand) error { +func validateAdminVipLevelCommand(level ledger.AdminVipLevelCommand, program ledger.VipProgramConfig) error { if level.Name == "" { return xerr.New(xerr.InvalidArgument, "vip level name is required") } @@ -116,17 +232,148 @@ func validateAdminVipLevelCommand(level ledger.AdminVipLevelCommand) error { default: return xerr.New(xerr.InvalidArgument, "vip level status is invalid") } - if level.PriceCoin < 0 || level.DurationMS <= 0 || level.RewardResourceGroupID < 0 || level.RequiredRechargeCoinAmount < 0 { + if level.PriceCoin < 0 || level.DurationMS <= 0 || level.RewardResourceGroupID < 0 { return xerr.New(xerr.InvalidArgument, "vip level config is invalid") } - if level.Status != ledger.VipStatusActive { - return nil - } - if level.PriceCoin <= 0 { + if level.Status == ledger.VipStatusActive && level.PriceCoin <= 0 { return xerr.New(xerr.InvalidArgument, "active vip level price_coin must be greater than zero") } - if level.RewardResourceGroupID <= 0 { - return xerr.New(xerr.InvalidArgument, "active vip level reward_resource_group_id is required") + // legacy_timed 继续允许无资源组的既有等级;tiered 体系的能力也来自显式 benefits,不能强制复制旧资源组模型。 + _ = program + return nil +} + +func (r *Repository) validateAdminVipBenefit(ctx context.Context, tx *sql.Tx, level int32, benefit ledger.VipBenefit) error { + if benefit.BenefitCode == "" || benefit.Name == "" || benefit.UnlockLevel < 0 || benefit.ResourceID < 0 { + return xerr.New(xerr.InvalidArgument, "vip benefit is incomplete") + } + switch benefit.BenefitType { + case ledger.VipBenefitTypeDecoration, ledger.VipBenefitTypeFunction: + default: + return xerr.New(xerr.InvalidArgument, "vip benefit type is invalid") + } + switch benefit.Status { + case ledger.VipStatusActive, ledger.VipStatusDisabled: + default: + return xerr.New(xerr.InvalidArgument, "vip benefit status is invalid") + } + switch benefit.ExecutionScope { + case ledger.VipExecutionScopeWallet, ledger.VipExecutionScopeRoom, ledger.VipExecutionScopeUser, ledger.VipExecutionScopeNotice: + default: + return xerr.New(xerr.InvalidArgument, "vip benefit execution_scope is invalid") + } + if benefit.MetadataJSON != "" && !json.Valid([]byte(benefit.MetadataJSON)) { + return xerr.New(xerr.InvalidArgument, "vip benefit metadata_json 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") + } + if benefit.TrialEnabled { + return xerr.New(xerr.InvalidArgument, "daily_coin_rebate cannot be enabled for trial cards") + } + // disabled 允许空对象,便于后台表单原样提交未定金额;若已显式带 coin_amount, + // 即使 disabled 也拒绝非法类型,避免稍后仅切状态时激活脏数据。 + validateAmount := benefit.Status == ledger.VipStatusActive + if !validateAmount && benefit.MetadataJSON != "" { + var metadata map[string]any + if err := json.Unmarshal([]byte(benefit.MetadataJSON), &metadata); err != nil || metadata == nil { + return xerr.New(xerr.InvalidArgument, "daily_coin_rebate metadata_json must be an object") + } + _, validateAmount = metadata["coin_amount"] + } + // active 必须是 JSON 正 int64,不猜测任何产品上限。 + if validateAmount { + if _, err := parseVipDailyCoinRebateAmount(benefit.MetadataJSON); err != nil { + return xerr.New(xerr.InvalidArgument, "daily_coin_rebate metadata_json.coin_amount must be a positive int64") + } + } + } + if benefit.BenefitCode == ledger.VipBenefitCodeOnlineGlobalNotice { + if benefit.ExecutionScope != ledger.VipExecutionScopeNotice { + return xerr.New(xerr.InvalidArgument, "online_global_notice execution_scope must be notice") + } + if benefit.MetadataJSON != "" { + var metadata map[string]any + if err := json.Unmarshal([]byte(benefit.MetadataJSON), &metadata); err != nil || metadata == nil { + return xerr.New(xerr.InvalidArgument, "online_global_notice metadata_json must be an object") + } + if rawMessage, exists := metadata["message"]; exists { + message, ok := rawMessage.(string) + if !ok || strings.TrimSpace(message) == "" || utf8.RuneCountInString(message) > 256 { + return xerr.New(xerr.InvalidArgument, "online_global_notice metadata_json.message must be a non-empty string within 256 characters") + } + } + } + } + if benefit.ResourceID == 0 { + return nil + } + resource, err := r.getResourceForUpdate(ctx, tx, benefit.ResourceID) + if err != nil { + return err + } + if resource.Status != resourcedomain.StatusActive { + return xerr.New(xerr.Conflict, "vip benefit resource is disabled") + } + if benefit.ResourceType != "" && resourcedomain.NormalizeResourceType(resource.ResourceType) != benefit.ResourceType { + return xerr.New(xerr.Conflict, "vip benefit resource_type mismatch") + } + _ = level + return nil +} + +func normalizeAdminVipProgramConfig(config ledger.VipProgramConfig) ledger.VipProgramConfig { + config.AppCode = appcode.Normalize(config.AppCode) + config.ProgramType = strings.ToLower(strings.TrimSpace(config.ProgramType)) + config.SameLevelExpiryPolicy = strings.ToLower(strings.TrimSpace(config.SameLevelExpiryPolicy)) + config.UpgradeExpiryPolicy = strings.ToLower(strings.TrimSpace(config.UpgradeExpiryPolicy)) + config.DowngradePurchasePolicy = strings.ToLower(strings.TrimSpace(config.DowngradePurchasePolicy)) + // “最低等级自动继承”已被产品明确移除。旧后台若仍提交 cumulative,也只能作为兼容输入, + // 服务端持久化和回包一律收敛为 target_only,防止隐藏字段恢复旧语义。 + config.BenefitInheritancePolicy = ledger.VipBenefitInheritanceTargetOnly + config.GrantMode = strings.ToLower(strings.TrimSpace(config.GrantMode)) + config.Status = strings.ToLower(strings.TrimSpace(config.Status)) + return config +} + +func validateAdminVipProgramConfig(config ledger.VipProgramConfig) error { + switch config.ProgramType { + case ledger.VipProgramTypeLegacyTimed, ledger.VipProgramTypeTieredPrivilegeV1: + default: + return xerr.New(xerr.InvalidArgument, "vip program_type is invalid") + } + if config.LevelCount < 1 || config.LevelCount > 20 { + return xerr.New(xerr.InvalidArgument, "vip level_count must be between 1 and 20") + } + if config.SameLevelExpiryPolicy != ledger.VipExpiryPolicyExtendRemaining { + return xerr.New(xerr.InvalidArgument, "vip same_level_expiry_policy is invalid") + } + switch config.UpgradeExpiryPolicy { + case ledger.VipExpiryPolicyExtendRemaining, ledger.VipExpiryPolicyReplaceFromNow: + default: + return xerr.New(xerr.InvalidArgument, "vip upgrade_expiry_policy is invalid") + } + if config.DowngradePurchasePolicy != ledger.VipDowngradePurchasePolicyReject { + return xerr.New(xerr.InvalidArgument, "vip downgrade_purchase_policy is invalid") + } + // 产品已明确忽略“最低等级自动继承”;当前运行时只支持后台为每级保存完整集合。 + if config.BenefitInheritancePolicy != ledger.VipBenefitInheritanceTargetOnly { + return xerr.New(xerr.InvalidArgument, "vip benefit_inheritance_policy must be target_only") + } + switch config.GrantMode { + case ledger.VipGrantModeDirectMembership: + case ledger.VipGrantModeTrialCard: + if !config.TrialCardEnabled { + return xerr.New(xerr.InvalidArgument, "trial_card grant mode requires trial_card_enabled") + } + default: + return xerr.New(xerr.InvalidArgument, "vip grant_mode is invalid") + } + switch config.Status { + case ledger.VipStatusActive, ledger.VipStatusDisabled: + default: + return xerr.New(xerr.InvalidArgument, "vip program status is invalid") } return nil } diff --git a/services/wallet-service/internal/storage/mysql/vip_command_repository.go b/services/wallet-service/internal/storage/mysql/vip_command_repository.go new file mode 100644 index 00000000..a8e5f120 --- /dev/null +++ b/services/wallet-service/internal/storage/mysql/vip_command_repository.go @@ -0,0 +1,44 @@ +package mysql + +import ( + "context" + "database/sql" + + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" +) + +// lockVipCommand 在任何会员、账户、返现或资源业务锁之前串行化同 App、同 command_id 的 VIP 写命令。 +// +// 仅依赖 wallet_transactions 或 resource_grants 的唯一键时,两个首发事务可能先锁住不同业务行, +// 再同时争抢幂等唯一键,导致后到请求泄漏余额不足、降级或 MySQL duplicate 等可变结果。守卫行与 +// 业务事实处于同一事务:失败会一起回滚,成功后则让重放请求先等待原事务提交,再读取稳定回执。 +func (r *Repository) lockVipCommand(ctx context.Context, tx *sql.Tx, commandID string, bizType string, requestHash string, nowMS int64, conflictCode xerr.Code) error { + if _, err := tx.ExecContext(ctx, ` + INSERT INTO vip_command_locks ( + app_code, command_id, biz_type, request_hash, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE command_id = VALUES(command_id)`, + appcode.FromContext(ctx), commandID, bizType, requestHash, nowMS, nowMS, + ); err != nil { + return err + } + + // UPSERT 已经承担等待未提交同键事务的职责;FOR UPDATE 再读取已提交语义,既校验跨 VIP + // 命令类型复用,也不依赖 MySQL RowsAffected/CLIENT_FOUND_ROWS 的驱动差异。 + var storedBizType string + var storedRequestHash string + if err := tx.QueryRowContext(ctx, ` + SELECT biz_type, request_hash + FROM vip_command_locks + WHERE app_code = ? AND command_id = ? + FOR UPDATE`, + appcode.FromContext(ctx), commandID, + ).Scan(&storedBizType, &storedRequestHash); err != nil { + return err + } + if storedBizType != bizType || storedRequestHash != requestHash { + return xerr.New(conflictCode, "vip command idempotency conflict") + } + return nil +} diff --git a/services/wallet-service/internal/storage/mysql/vip_daily_coin_rebate_repository.go b/services/wallet-service/internal/storage/mysql/vip_daily_coin_rebate_repository.go new file mode 100644 index 00000000..b015d5be --- /dev/null +++ b/services/wallet-service/internal/storage/mysql/vip_daily_coin_rebate_repository.go @@ -0,0 +1,632 @@ +package mysql + +import ( + "context" + "database/sql" + "encoding/json" + "errors" + "fmt" + "strconv" + "strings" + "time" + + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + "hyapp/services/wallet-service/internal/domain/ledger" +) + +const ( + vipDailyCoinRebateTaskDayLayout = "2006-01-02" + vipDailyCoinRebateAvailableEvent = "VipDailyCoinRebateAvailable" +) + +type vipDailyCoinRebateCandidate struct { + UserID int64 + Level int32 + VipName string + ExpiresAtMS int64 +} + +type vipDailyCoinRebateMetadata struct { + RebateID string `json:"rebate_id"` + UserID int64 `json:"user_id"` + TaskDay string `json:"task_day"` + VipLevel int32 `json:"vip_level"` + VipName string `json:"vip_name"` + CoinAmount int64 `json:"coin_amount"` + AvailableAtMS int64 `json:"available_at_ms"` + ExpiresAtMS int64 `json:"expires_at_ms"` + ConfigVersion int64 `json:"config_version"` + CreatedAtMS int64 `json:"created_at_ms"` +} + +// ProcessVipDailyCoinRebateBatch 在一个事务内串行推进单 App+UTC 日游标。 +// run 首次创建时锁住 program 并固化金额矩阵;后续页只读 run 快照,绝不混入后台的新配置版本。 +func (r *Repository) ProcessVipDailyCoinRebateBatch(ctx context.Context, command ledger.ProcessVipDailyCoinRebateBatchCommand) (ledger.ProcessVipDailyCoinRebateBatchResult, error) { + if r == nil || r.db == nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + ctx = contextWithCommandApp(ctx, command.AppCode) + command.AppCode = appcode.FromContext(ctx) + dayStart, err := time.ParseInLocation(vipDailyCoinRebateTaskDayLayout, command.TaskDay, time.UTC) + if err != nil || dayStart.Format(vipDailyCoinRebateTaskDayLayout) != command.TaskDay { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, xerr.New(xerr.InvalidArgument, "vip rebate task_day is invalid") + } + dayStartMS := dayStart.UnixMilli() + dayEndMS := dayStart.Add(24 * time.Hour).UnixMilli() + if command.BatchSize <= 0 { + command.BatchSize = 100 + } + if command.BatchSize > 500 { + command.BatchSize = 500 + } + + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, err + } + defer func() { _ = tx.Rollback() }() + + run, exists, err := r.findVipDailyCoinRebateRun(ctx, tx, command.TaskDay, false) + if err != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, err + } + if !exists { + // 缺 run 时先锁 program,再二次检查唯一日 run。并发 worker 会在该锁上排队, + // 避免两个不存在键的 gap lock 互相等待,并保证金额与 config_version 来自同一快照。 + program, lockErr := r.queryVipProgramConfig(ctx, tx.QueryRowContext(ctx, vipProgramSelectSQL()+` FOR UPDATE`, command.AppCode)) + if errors.Is(lockErr, sql.ErrNoRows) { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, xerr.New(xerr.NotFound, "vip program config not found") + } + if lockErr != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, lockErr + } + // 等待 program 锁后必须使用 locking current read。普通 RR 快照仍停留在等待前, + // 看不到另一个 worker 刚提交的 run,随后 INSERT 会错误撞唯一键。 + run, exists, err = r.findVipDailyCoinRebateRun(ctx, tx, command.TaskDay, true) + if err != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, err + } + if !exists { + levelAmounts := map[int32]int64{} + if program.Status == ledger.VipStatusActive { + levelAmounts, err = r.loadVipDailyCoinRebateLevelAmounts(ctx, tx, program.LevelCount) + if err != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, err + } + } + levelAmountsJSON, marshalErr := json.Marshal(levelAmounts) + if marshalErr != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, marshalErr + } + run = ledger.VipDailyCoinRebateRun{ + RunID: vipDailyCoinRebateRunID(command.AppCode, command.TaskDay), + TaskDay: command.TaskDay, + DayStartMS: dayStartMS, + DayEndMS: dayEndMS, + ConfigVersion: program.ConfigVersion, + LevelAmounts: levelAmounts, + LevelAmountsJSON: string(levelAmountsJSON), + Status: ledger.VipDailyCoinRebateRunStatusRunning, + CreatedAtMS: command.NowMS, + UpdatedAtMS: command.NowMS, + } + if _, err := tx.ExecContext(ctx, ` + INSERT INTO vip_daily_coin_rebate_runs ( + app_code, task_day, run_id, day_start_ms, day_end_ms, config_version, + level_amounts_json, status, last_user_id, scanned_count, created_count, + created_at_ms, updated_at_ms, completed_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, 0, 0, ?, ?, 0)`, + command.AppCode, run.TaskDay, run.RunID, run.DayStartMS, run.DayEndMS, + run.ConfigVersion, run.LevelAmountsJSON, run.Status, command.NowMS, command.NowMS, + ); err != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, err + } + } + } + run, exists, err = r.findVipDailyCoinRebateRun(ctx, tx, command.TaskDay, true) + if err != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, err + } + if !exists { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, xerr.New(xerr.Internal, "vip daily coin rebate run creation failed") + } + if run.Status == ledger.VipDailyCoinRebateRunStatusCompleted { + if err := tx.Commit(); err != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, err + } + return ledger.ProcessVipDailyCoinRebateBatchResult{Run: run}, nil + } + + // 没有任何已配置正数金额时,直接完成 run。扫描会员既不会生成返现,也只会放大日切压力。 + if len(run.LevelAmounts) == 0 { + run.Status = ledger.VipDailyCoinRebateRunStatusCompleted + run.CompletedAtMS = command.NowMS + run.UpdatedAtMS = command.NowMS + if err := r.updateVipDailyCoinRebateRun(ctx, tx, run); err != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, err + } + if err := tx.Commit(); err != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, err + } + return ledger.ProcessVipDailyCoinRebateBatchResult{Run: run}, nil + } + + candidates, err := r.listVipDailyCoinRebateCandidates(ctx, tx, run.DayStartMS, run.LastUserID, command.BatchSize) + if err != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, err + } + createdCount := 0 + for _, candidate := range candidates { + if candidate.Level <= 0 || candidate.ExpiresAtMS <= run.DayStartMS { + continue + } + amount, enabled := run.LevelAmounts[candidate.Level] + if !enabled || amount <= 0 { + continue + } + rebateID := vipDailyCoinRebateID(command.AppCode, run.TaskDay, candidate.UserID) + result, insertErr := tx.ExecContext(ctx, ` + INSERT IGNORE INTO vip_daily_coin_rebates ( + app_code, rebate_id, run_id, task_day, user_id, vip_level, vip_name, + coin_amount, status, available_at_ms, expires_at_ms, config_version, + claimed_at_ms, wallet_transaction_id, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, '', ?, ?)`, + command.AppCode, rebateID, run.RunID, run.TaskDay, candidate.UserID, candidate.Level, + candidate.VipName, amount, ledger.VipDailyCoinRebateStatusClaimable, + run.DayStartMS, run.DayEndMS, run.ConfigVersion, command.NowMS, command.NowMS, + ) + if insertErr != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, insertErr + } + inserted, rowsErr := result.RowsAffected() + if rowsErr != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, rowsErr + } + if inserted == 0 { + continue + } + createdCount++ + metadata := vipDailyCoinRebateMetadata{ + RebateID: rebateID, UserID: candidate.UserID, TaskDay: run.TaskDay, + VipLevel: candidate.Level, VipName: candidate.VipName, CoinAmount: amount, + AvailableAtMS: run.DayStartMS, ExpiresAtMS: run.DayEndMS, + ConfigVersion: run.ConfigVersion, CreatedAtMS: command.NowMS, + } + // available 不是余额变化,因此 transaction_id 使用稳定 rebate_id 占位;事件与返现行 + // 同事务提交,下游可直接用 rebate_id 做通知幂等源 ID。 + if err := r.insertWalletOutbox(ctx, tx, []walletOutboxEvent{{ + EventID: eventID(rebateID, vipDailyCoinRebateAvailableEvent, candidate.UserID, ledger.AssetCoin), + EventType: vipDailyCoinRebateAvailableEvent, + TransactionID: rebateID, + CommandID: vipDailyCoinRebateAvailableCommandID(run.TaskDay, candidate.UserID), + UserID: candidate.UserID, + AssetType: ledger.AssetCoin, + Payload: metadata, + CreatedAtMS: command.NowMS, + }}); err != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, err + } + } + + if len(candidates) > 0 { + run.LastUserID = candidates[len(candidates)-1].UserID + } + run.ScannedCount += int64(len(candidates)) + run.CreatedCount += int64(createdCount) + run.UpdatedAtMS = command.NowMS + if len(candidates) < command.BatchSize { + run.Status = ledger.VipDailyCoinRebateRunStatusCompleted + run.CompletedAtMS = command.NowMS + } + if err := r.updateVipDailyCoinRebateRun(ctx, tx, run); err != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, err + } + if err := tx.Commit(); err != nil { + return ledger.ProcessVipDailyCoinRebateBatchResult{}, err + } + return ledger.ProcessVipDailyCoinRebateBatchResult{ + Run: run, ScannedCount: len(candidates), CreatedCount: createdCount, + HasMore: run.Status == ledger.VipDailyCoinRebateRunStatusRunning, + }, nil +} + +// GetMyCurrentVipDailyCoinRebate 只读取当前 UTC task_day;未生成记录不视为错误。 +func (r *Repository) GetMyCurrentVipDailyCoinRebate(ctx context.Context, userID int64, nowMS int64) (ledger.VipDailyCoinRebate, bool, error) { + if r == nil || r.db == nil { + return ledger.VipDailyCoinRebate{}, false, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + taskDay := time.UnixMilli(nowMS).UTC().Format(vipDailyCoinRebateTaskDayLayout) + rebate, err := scanVipDailyCoinRebate(r.db.QueryRowContext(ctx, vipDailyCoinRebateSelectSQL()+` + WHERE app_code = ? AND user_id = ? AND task_day = ?`, appcode.FromContext(ctx), userID, taskDay)) + if errors.Is(err, sql.ErrNoRows) { + return ledger.VipDailyCoinRebate{}, false, nil + } + if err != nil { + return ledger.VipDailyCoinRebate{}, false, err + } + return projectVipDailyCoinRebateStatus(rebate, nowMS), true, nil +} + +// ListMyVipDailyCoinRebateStatuses 按 UTC 日倒序分页,禁止为状态展示扫描整张返现表。 +func (r *Repository) ListMyVipDailyCoinRebateStatuses(ctx context.Context, query ledger.ListVipDailyCoinRebateStatusesQuery) ([]ledger.VipDailyCoinRebate, int64, error) { + if r == nil || r.db == nil { + return nil, 0, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + appCode := appcode.FromContext(ctx) + if len(query.RebateIDs) > 0 { + args := []any{appCode, query.UserID} + args = append(args, walletOutboxEventArgs(query.RebateIDs)...) + rows, err := r.db.QueryContext(ctx, vipDailyCoinRebateSelectSQL()+` + WHERE app_code = ? AND user_id = ? AND rebate_id IN (`+walletOutboxPlaceholders(len(query.RebateIDs))+`) + ORDER BY task_day DESC, rebate_id DESC`, args...) + if err != nil { + return nil, 0, err + } + defer rows.Close() + items := make([]ledger.VipDailyCoinRebate, 0, len(query.RebateIDs)) + for rows.Next() { + item, scanErr := scanVipDailyCoinRebate(rows) + if scanErr != nil { + return nil, 0, scanErr + } + items = append(items, projectVipDailyCoinRebateStatus(item, query.NowMS)) + } + return items, int64(len(items)), rows.Err() + } + var total int64 + if err := r.db.QueryRowContext(ctx, ` + SELECT COUNT(*) FROM vip_daily_coin_rebates WHERE app_code = ? AND user_id = ?`, + appCode, query.UserID, + ).Scan(&total); err != nil { + return nil, 0, err + } + offset := (query.Page - 1) * query.PageSize + rows, err := r.db.QueryContext(ctx, vipDailyCoinRebateSelectSQL()+` + WHERE app_code = ? AND user_id = ? + ORDER BY task_day DESC, rebate_id DESC LIMIT ? OFFSET ?`, + appCode, query.UserID, query.PageSize, offset, + ) + if err != nil { + return nil, 0, err + } + defer rows.Close() + items := make([]ledger.VipDailyCoinRebate, 0, query.PageSize) + for rows.Next() { + item, scanErr := scanVipDailyCoinRebate(rows) + if scanErr != nil { + return nil, 0, scanErr + } + items = append(items, projectVipDailyCoinRebateStatus(item, query.NowMS)) + } + return items, total, rows.Err() +} + +// ClaimVipDailyCoinRebate 在返现行锁、COIN 账户锁、交易、分录和 outbox 的单一事务中完成领取。 +func (r *Repository) ClaimVipDailyCoinRebate(ctx context.Context, command ledger.ClaimVipDailyCoinRebateCommand) (ledger.ClaimVipDailyCoinRebateReceipt, error) { + if r == nil || r.db == nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + ctx = contextWithCommandApp(ctx, command.AppCode) + command.AppCode = appcode.FromContext(ctx) + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, err + } + defer func() { _ = tx.Rollback() }() + + requestHash := stableHash(fmt.Sprintf("vip_daily_coin_rebate_claim|%s|%d|%s", command.AppCode, command.UserID, command.RebateID)) + // 所有 VIP 写命令共用 command guard。不同 command 重复点击已领取返现虽然不再造交易, + // 也会持久化 guard,保证该 command 后续改投另一 rebate 时稳定返回 IDEMPOTENCY_CONFLICT。 + if err := r.lockVipCommand(ctx, tx, command.CommandID, bizTypeVipDailyCoinRebate, requestHash, command.NowMS, xerr.IdempotencyConflict); err != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, err + } + rebate, err := scanVipDailyCoinRebate(tx.QueryRowContext(ctx, vipDailyCoinRebateSelectSQL()+` + WHERE app_code = ? AND rebate_id = ? AND user_id = ? FOR UPDATE`, + command.AppCode, command.RebateID, command.UserID, + )) + if errors.Is(err, sql.ErrNoRows) { + return ledger.ClaimVipDailyCoinRebateReceipt{}, xerr.New(xerr.VIPCoinRebateNotFound, "vip daily coin rebate not found") + } + if err != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, err + } + if txRow, exists, lookupErr := r.lookupTransactionConsistent(ctx, tx, command.CommandID, requestHash, bizTypeVipDailyCoinRebate, xerr.IdempotencyConflict); lookupErr != nil || exists { + if lookupErr != nil || !exists { + return ledger.ClaimVipDailyCoinRebateReceipt{}, lookupErr + } + if rebate.WalletTransactionID != "" && rebate.WalletTransactionID != txRow.TransactionID { + return ledger.ClaimVipDailyCoinRebateReceipt{}, xerr.New(xerr.LedgerConflict, "vip daily coin rebate transaction mismatch") + } + balance, balanceErr := r.balanceAfterTransaction(ctx, tx, txRow.TransactionID, command.UserID, ledger.AssetCoin) + if balanceErr != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, balanceErr + } + rebate.Status = ledger.VipDailyCoinRebateStatusClaimed + rebate.WalletTransactionID = txRow.TransactionID + if err := tx.Commit(); err != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, err + } + return ledger.ClaimVipDailyCoinRebateReceipt{Rebate: rebate, TransactionID: txRow.TransactionID, CoinBalance: balance}, nil + } + if rebate.Status == ledger.VipDailyCoinRebateStatusClaimed || rebate.WalletTransactionID != "" { + // 不同 command 的重复点击也返回原成功回执;返现本身才是唯一业务操作, + // 不为第二个 command 伪造一笔钱包交易。若 command 已用于其他 payload,上面的幂等查询仍会拒绝。 + balance, balanceErr := r.balanceAfterTransaction(ctx, tx, rebate.WalletTransactionID, command.UserID, ledger.AssetCoin) + if balanceErr != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, balanceErr + } + if err := tx.Commit(); err != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, err + } + return ledger.ClaimVipDailyCoinRebateReceipt{ + Rebate: rebate, TransactionID: rebate.WalletTransactionID, CoinBalance: balance, + }, nil + } + // 领取窗严格为 [available_at_ms, expires_at_ms):日切毫秒可领取,次日日切毫秒不可领取。 + if command.NowMS < rebate.AvailableAtMS { + return ledger.ClaimVipDailyCoinRebateReceipt{}, xerr.New(xerr.Conflict, "vip daily coin rebate is not available yet") + } + if command.NowMS >= rebate.ExpiresAtMS { + return ledger.ClaimVipDailyCoinRebateReceipt{}, xerr.New(xerr.VIPCoinRebateExpired, "vip daily coin rebate expired") + } + if rebate.CoinAmount <= 0 { + return ledger.ClaimVipDailyCoinRebateReceipt{}, xerr.New(xerr.LedgerConflict, "vip daily coin rebate amount is invalid") + } + + account, err := r.lockAccount(ctx, tx, command.UserID, ledger.AssetCoin, true, command.NowMS) + if err != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, err + } + transactionID := transactionID(command.AppCode, command.CommandID) + metadata := vipDailyCoinRebateMetadata{ + RebateID: rebate.RebateID, UserID: rebate.UserID, TaskDay: rebate.TaskDay, + VipLevel: rebate.VipLevel, VipName: rebate.VipName, CoinAmount: rebate.CoinAmount, + AvailableAtMS: rebate.AvailableAtMS, ExpiresAtMS: rebate.ExpiresAtMS, + ConfigVersion: rebate.ConfigVersion, CreatedAtMS: command.NowMS, + } + if err := r.insertTransaction(ctx, tx, transactionID, command.CommandID, bizTypeVipDailyCoinRebate, requestHash, rebate.RebateID, metadata, command.NowMS); err != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, err + } + if err := r.applyAccountDelta(ctx, tx, account, rebate.CoinAmount, 0, command.NowMS); err != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, err + } + balance := ledger.AssetBalance{ + AppCode: command.AppCode, UserID: command.UserID, AssetType: ledger.AssetCoin, + AvailableAmount: account.AvailableAmount + rebate.CoinAmount, + FrozenAmount: account.FrozenAmount, Version: account.Version + 1, UpdatedAtMs: command.NowMS, + } + if err := r.insertEntry(ctx, tx, walletEntry{ + TransactionID: transactionID, UserID: command.UserID, AssetType: ledger.AssetCoin, + AvailableDelta: rebate.CoinAmount, AvailableAfter: balance.AvailableAmount, + FrozenAfter: balance.FrozenAmount, CreatedAtMS: command.NowMS, + }); err != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, err + } + result, err := tx.ExecContext(ctx, ` + UPDATE vip_daily_coin_rebates + SET status = ?, claimed_at_ms = ?, wallet_transaction_id = ?, updated_at_ms = ? + WHERE app_code = ? AND rebate_id = ? AND user_id = ? AND status = ?`, + ledger.VipDailyCoinRebateStatusClaimed, command.NowMS, transactionID, command.NowMS, + command.AppCode, rebate.RebateID, command.UserID, ledger.VipDailyCoinRebateStatusClaimable, + ) + if err != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, err + } + updated, err := result.RowsAffected() + if err != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, err + } + if updated != 1 { + return ledger.ClaimVipDailyCoinRebateReceipt{}, xerr.New(xerr.LedgerConflict, "vip daily coin rebate claim conflict") + } + if err := r.insertWalletOutbox(ctx, tx, []walletOutboxEvent{ + balanceChangedEvent(transactionID, command.CommandID, command.UserID, ledger.AssetCoin, + rebate.CoinAmount, 0, balance.AvailableAmount, balance.FrozenAmount, balance.Version, + metadata, command.NowMS, bizTypeVipDailyCoinRebate), + }); err != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, err + } + if err := tx.Commit(); err != nil { + return ledger.ClaimVipDailyCoinRebateReceipt{}, err + } + rebate.Status = ledger.VipDailyCoinRebateStatusClaimed + rebate.ClaimedAtMS = command.NowMS + rebate.WalletTransactionID = transactionID + rebate.UpdatedAtMS = command.NowMS + return ledger.ClaimVipDailyCoinRebateReceipt{Rebate: rebate, TransactionID: transactionID, CoinBalance: balance}, nil +} + +func (r *Repository) loadVipDailyCoinRebateLevelAmounts(ctx context.Context, tx *sql.Tx, levelCount int32) (map[int32]int64, error) { + rows, err := tx.QueryContext(ctx, ` + SELECT level, COALESCE(CAST(metadata_json AS CHAR), '') + FROM vip_level_benefits + WHERE app_code = ? AND level BETWEEN 1 AND ? AND benefit_code = ? AND status = ? + ORDER BY level ASC`, + appcode.FromContext(ctx), levelCount, ledger.VipBenefitCodeDailyCoinRebate, ledger.VipStatusActive, + ) + if err != nil { + return nil, err + } + defer rows.Close() + amounts := make(map[int32]int64) + for rows.Next() { + var level int32 + var metadataJSON string + if err := rows.Scan(&level, &metadataJSON); err != nil { + return nil, err + } + amount, err := parseVipDailyCoinRebateAmount(metadataJSON) + if err != nil { + return nil, xerr.New(xerr.Conflict, fmt.Sprintf("vip level %d daily_coin_rebate metadata is invalid", level)) + } + amounts[level] = amount + } + return amounts, rows.Err() +} + +// listVipDailyCoinRebateCandidates 先按 membership 主键取固定大小的一页,再只为本页用户还原 +// UTC 日切状态。不能在每一页对全 App history 做窗口排序;那会让日切批任务退化成重复全表扫描。 +// 迁移前 history 新增的有效期字段为 0,这些行不是可信的日切快照。必须先对全部历史排序, +// 再判断边界最近一条是否完整;否则过滤后再排序会越过较新未知变更,错误复活较旧 VIP。 +// 边界行不完整时改用首条后续 history.previous_* 或 current membership 安全兜底。 +func (r *Repository) listVipDailyCoinRebateCandidates(ctx context.Context, tx *sql.Tx, dayStartMS int64, lastUserID int64, limit int) ([]vipDailyCoinRebateCandidate, error) { + rows, err := tx.QueryContext(ctx, ` + WITH member_page AS ( + SELECT user_id, level, name, started_at_ms, expires_at_ms + FROM user_vip_memberships + WHERE app_code = ? AND user_id > ? + ORDER BY user_id ASC + LIMIT ? + ), ranked_history AS ( + SELECT h.user_id, h.new_level AS vip_level, h.new_expires_at_ms AS expires_at_ms, + ROW_NUMBER() OVER (PARTITION BY h.user_id ORDER BY h.created_at_ms DESC, h.history_id DESC) AS row_no + FROM user_vip_history h + INNER JOIN member_page p ON p.user_id = h.user_id + WHERE h.app_code = ? AND h.created_at_ms <= ? + ), ranked_after_history AS ( + SELECT h.user_id, h.previous_level AS vip_level, h.previous_expires_at_ms AS expires_at_ms, + ROW_NUMBER() OVER (PARTITION BY h.user_id ORDER BY h.created_at_ms ASC, h.history_id ASC) AS row_no + FROM user_vip_history h + INNER JOIN member_page p ON p.user_id = h.user_id + WHERE h.app_code = ? AND h.created_at_ms > ? + ), boundary_memberships AS ( + SELECT p.user_id, + COALESCE(h.vip_level, + CASE WHEN future.vip_level > 0 AND future.expires_at_ms > ? THEN future.vip_level + WHEN p.started_at_ms <= ? THEN p.level ELSE 0 END) AS vip_level, + COALESCE(h.expires_at_ms, + CASE WHEN future.vip_level > 0 AND future.expires_at_ms > ? THEN future.expires_at_ms + WHEN p.started_at_ms <= ? THEN p.expires_at_ms ELSE 0 END) AS expires_at_ms, + p.name AS membership_name + FROM member_page p + LEFT JOIN ranked_history h + ON h.user_id = p.user_id AND h.row_no = 1 + AND h.vip_level > 0 AND h.expires_at_ms > 0 + LEFT JOIN ranked_after_history future + ON future.user_id = p.user_id AND future.row_no = 1 + AND future.vip_level > 0 AND future.expires_at_ms > 0 + ) + SELECT b.user_id, b.vip_level, COALESCE(v.name, b.membership_name, CONCAT('VIP', b.vip_level)), b.expires_at_ms + FROM boundary_memberships b + LEFT JOIN vip_levels v ON v.app_code = ? AND v.level = b.vip_level + ORDER BY b.user_id ASC`, + appcode.FromContext(ctx), lastUserID, limit, + appcode.FromContext(ctx), dayStartMS, + appcode.FromContext(ctx), dayStartMS, + dayStartMS, dayStartMS, dayStartMS, dayStartMS, + appcode.FromContext(ctx), + ) + if err != nil { + return nil, err + } + defer rows.Close() + items := make([]vipDailyCoinRebateCandidate, 0, limit) + for rows.Next() { + var item vipDailyCoinRebateCandidate + if err := rows.Scan(&item.UserID, &item.Level, &item.VipName, &item.ExpiresAtMS); err != nil { + return nil, err + } + items = append(items, item) + } + return items, rows.Err() +} + +func (r *Repository) findVipDailyCoinRebateRun(ctx context.Context, tx *sql.Tx, taskDay string, lock bool) (ledger.VipDailyCoinRebateRun, bool, error) { + query := ` + SELECT run_id, task_day, day_start_ms, day_end_ms, config_version, + CAST(level_amounts_json AS CHAR), status, last_user_id, scanned_count, + created_count, created_at_ms, updated_at_ms, completed_at_ms + FROM vip_daily_coin_rebate_runs + WHERE app_code = ? AND task_day = ?` + if lock { + query += ` FOR UPDATE` + } + var run ledger.VipDailyCoinRebateRun + if err := tx.QueryRowContext(ctx, query, appcode.FromContext(ctx), taskDay).Scan( + &run.RunID, &run.TaskDay, &run.DayStartMS, &run.DayEndMS, &run.ConfigVersion, + &run.LevelAmountsJSON, &run.Status, &run.LastUserID, &run.ScannedCount, + &run.CreatedCount, &run.CreatedAtMS, &run.UpdatedAtMS, &run.CompletedAtMS, + ); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return ledger.VipDailyCoinRebateRun{}, false, nil + } + return ledger.VipDailyCoinRebateRun{}, false, err + } + if err := json.Unmarshal([]byte(run.LevelAmountsJSON), &run.LevelAmounts); err != nil { + return ledger.VipDailyCoinRebateRun{}, false, xerr.New(xerr.LedgerConflict, "vip daily coin rebate run snapshot is invalid") + } + return run, true, nil +} + +func (r *Repository) updateVipDailyCoinRebateRun(ctx context.Context, tx *sql.Tx, run ledger.VipDailyCoinRebateRun) error { + _, err := tx.ExecContext(ctx, ` + UPDATE vip_daily_coin_rebate_runs + SET status = ?, last_user_id = ?, scanned_count = ?, created_count = ?, + updated_at_ms = ?, completed_at_ms = ? + WHERE app_code = ? AND task_day = ? AND run_id = ?`, + run.Status, run.LastUserID, run.ScannedCount, run.CreatedCount, + run.UpdatedAtMS, run.CompletedAtMS, appcode.FromContext(ctx), run.TaskDay, run.RunID, + ) + return err +} + +func vipDailyCoinRebateSelectSQL() string { + return ` + SELECT rebate_id, user_id, task_day, vip_level, vip_name, coin_amount, status, + available_at_ms, expires_at_ms, config_version, claimed_at_ms, + wallet_transaction_id, created_at_ms, updated_at_ms + FROM vip_daily_coin_rebates ` +} + +func scanVipDailyCoinRebate(scanner interface{ Scan(...any) error }) (ledger.VipDailyCoinRebate, error) { + var rebate ledger.VipDailyCoinRebate + err := scanner.Scan( + &rebate.RebateID, &rebate.UserID, &rebate.TaskDay, &rebate.VipLevel, + &rebate.VipName, &rebate.CoinAmount, &rebate.Status, &rebate.AvailableAtMS, + &rebate.ExpiresAtMS, &rebate.ConfigVersion, &rebate.ClaimedAtMS, + &rebate.WalletTransactionID, &rebate.CreatedAtMS, &rebate.UpdatedAtMS, + ) + return rebate, err +} + +func projectVipDailyCoinRebateStatus(rebate ledger.VipDailyCoinRebate, nowMS int64) ledger.VipDailyCoinRebate { + if rebate.Status == ledger.VipDailyCoinRebateStatusClaimable && nowMS >= rebate.ExpiresAtMS { + rebate.Status = ledger.VipDailyCoinRebateStatusExpired + } + return rebate +} + +func parseVipDailyCoinRebateAmount(metadataJSON string) (int64, error) { + decoder := json.NewDecoder(strings.NewReader(strings.TrimSpace(metadataJSON))) + decoder.UseNumber() + var metadata map[string]any + if err := decoder.Decode(&metadata); err != nil || metadata == nil { + return 0, errors.New("metadata_json must be an object") + } + raw, ok := metadata["coin_amount"] + if !ok { + return 0, errors.New("coin_amount is required") + } + number, ok := raw.(json.Number) + if !ok { + return 0, errors.New("coin_amount must be an integer") + } + amount, err := number.Int64() + if err != nil || amount <= 0 { + return 0, errors.New("coin_amount must be a positive int64") + } + return amount, nil +} + +func vipDailyCoinRebateRunID(appCode string, taskDay string) string { + return "vip_rebate_run_" + stableHash(appcode.Normalize(appCode)+"|"+taskDay) +} + +func vipDailyCoinRebateID(appCode string, taskDay string, userID int64) string { + return "vip_rebate_" + stableHash(fmt.Sprintf("%s|%s|%d", appcode.Normalize(appCode), taskDay, userID)) +} + +func vipDailyCoinRebateAvailableCommandID(taskDay string, userID int64) string { + return "vip_rebate_available:" + taskDay + ":" + strconv.FormatInt(userID, 10) +} diff --git a/services/wallet-service/internal/storage/mysql/vip_daily_coin_rebate_repository_test.go b/services/wallet-service/internal/storage/mysql/vip_daily_coin_rebate_repository_test.go new file mode 100644 index 00000000..f31e4882 --- /dev/null +++ b/services/wallet-service/internal/storage/mysql/vip_daily_coin_rebate_repository_test.go @@ -0,0 +1,40 @@ +package mysql + +import ( + "math" + "testing" +) + +// TestParseVipDailyCoinRebateAmount 只接受 JSON 正 int64;不允许字符串、浮点数、零、负数或溢出值。 +func TestParseVipDailyCoinRebateAmount(t *testing.T) { + testCases := []struct { + name string + payload string + want int64 + valid bool + }{ + {name: "positive", payload: `{"coin_amount":123}`, want: 123, valid: true}, + {name: "max int64", payload: `{"coin_amount":9223372036854775807}`, want: math.MaxInt64, valid: true}, + {name: "missing", payload: `{}`, valid: false}, + {name: "string", payload: `{"coin_amount":"123"}`, valid: false}, + {name: "float", payload: `{"coin_amount":1.5}`, valid: false}, + {name: "zero", payload: `{"coin_amount":0}`, valid: false}, + {name: "negative", payload: `{"coin_amount":-1}`, valid: false}, + {name: "overflow", payload: `{"coin_amount":9223372036854775808}`, valid: false}, + {name: "array", payload: `[]`, valid: false}, + } + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + amount, err := parseVipDailyCoinRebateAmount(testCase.payload) + if testCase.valid { + if err != nil || amount != testCase.want { + t.Fatalf("parse positive int64 mismatch: amount=%d err=%v", amount, err) + } + return + } + if err == nil { + t.Fatalf("invalid payload unexpectedly parsed as %d", amount) + } + }) + } +} diff --git a/services/wallet-service/internal/storage/mysql/vip_grant_repository.go b/services/wallet-service/internal/storage/mysql/vip_grant_repository.go index ace978e9..6fa3377d 100644 --- a/services/wallet-service/internal/storage/mysql/vip_grant_repository.go +++ b/services/wallet-service/internal/storage/mysql/vip_grant_repository.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "encoding/json" + "errors" "fmt" "hyapp/pkg/appcode" "hyapp/pkg/xerr" @@ -28,21 +29,42 @@ func (r *Repository) GrantVip(ctx context.Context, command ledger.GrantVipComman command.Reason = command.GrantSource } + requestHash := vipGrantRequestHash(command) + nowMs := time.Now().UnixMilli() tx, err := r.db.BeginTx(ctx, nil) if err != nil { return ledger.GrantVipReceipt{}, err } defer func() { _ = tx.Rollback() }() - requestHash := vipGrantRequestHash(command) - if txRow, exists, err := r.lookupTransaction(ctx, tx, command.CommandID, requestHash, bizTypeVIPGrant); err != nil || exists { + if err := r.lockVipCommand(ctx, tx, command.CommandID, bizTypeVIPGrant, requestHash, nowMs, xerr.LedgerConflict); err != nil { + return ledger.GrantVipReceipt{}, err + } + if _, exists, err := r.lookupTransactionConsistent(ctx, tx, command.CommandID, requestHash, bizTypeVIPGrant, xerr.LedgerConflict); err != nil || exists { if err != nil || !exists { return ledger.GrantVipReceipt{}, err } - return r.vipGrantReceiptForTransaction(ctx, tx, txRow, command.TargetUserID) + _ = tx.Rollback() + return r.replayVipGrant(ctx, command, requestHash) } - nowMs := time.Now().UnixMilli() + program, err := r.queryVipProgramConfig(ctx, tx.QueryRowContext(ctx, vipProgramSelectSQL()+` LOCK IN SHARE MODE`, command.AppCode)) + if errors.Is(err, sql.ErrNoRows) { + return ledger.GrantVipReceipt{}, xerr.New(xerr.NotFound, "vip program config not found") + } + if err != nil { + return ledger.GrantVipReceipt{}, err + } + if program.Status != ledger.VipStatusActive { + return ledger.GrantVipReceipt{}, xerr.New(xerr.Conflict, "vip program is disabled") + } + if command.Level > program.LevelCount { + return ledger.GrantVipReceipt{}, xerr.New(xerr.VIPLevelNotFound, "vip level exceeds program level_count") + } + // 体验卡体系的后台发放必须走 GrantVipTrialCard,禁止旧 GrantVip 绕过背包佩戴语义直接改会员表。 + if program.GrantMode != ledger.VipGrantModeDirectMembership { + return ledger.GrantVipReceipt{}, xerr.New(xerr.Conflict, "vip program requires trial card grant") + } level, err := r.getVipLevelForUpdate(ctx, tx, command.Level) if err != nil { return ledger.GrantVipReceipt{}, err @@ -58,6 +80,14 @@ func (r *Repository) GrantVip(ctx context.Context, command ledger.GrantVipComman if err != nil { return ledger.GrantVipReceipt{}, err } + expiryPolicy := program.SameLevelExpiryPolicy + if current.Active && command.Level > current.Level { + expiryPolicy = program.UpgradeExpiryPolicy + } + expectedStartedAtMS, expectedExpiresAtMS, err := vipActivationWindow(current, level, expiryPolicy, nowMs) + if err != nil { + return ledger.GrantVipReceipt{}, err + } transactionID := transactionID(command.AppCode, command.CommandID) recordID := "vip_grant_" + stableHash(command.AppCode+"|"+command.CommandID) expectedResourceGrantID := resourceGrantID(command.AppCode, "vip_reward:"+command.CommandID) @@ -67,6 +97,7 @@ func (r *Repository) GrantVip(ctx context.Context, command ledger.GrantVipComman "resource_grant_id": expectedResourceGrantID, "user_id": command.TargetUserID, "target_level": command.Level, + "vip_name": level.Name, "grant_source": command.GrantSource, "operator_user_id": command.OperatorUserID, "reason": command.Reason, @@ -74,8 +105,19 @@ func (r *Repository) GrantVip(ctx context.Context, command ledger.GrantVipComman "duration_ms": level.DurationMS, "transaction_id": transactionID, "required_recharge_bypassed": true, + "program_type": program.ProgramType, + "config_version": program.ConfigVersion, + "expiry_policy": expiryPolicy, + "previous_expires_at_ms": current.ExpiresAtMS, + "started_at_ms": expectedStartedAtMS, + "new_expires_at_ms": expectedExpiresAtMS, + "created_at_ms": nowMs, } if err := r.insertTransaction(ctx, tx, transactionID, command.CommandID, bizTypeVIPGrant, requestHash, recordID, metadata, nowMs); err != nil { + if isMySQLDuplicateError(err) { + _ = tx.Rollback() + return r.replayVipGrant(ctx, command, requestHash) + } return ledger.GrantVipReceipt{}, err } activation, err := r.activateUserVip(ctx, tx, vipActivationCommand{ @@ -89,34 +131,85 @@ func (r *Repository) GrantVip(ctx context.Context, command ledger.GrantVipComman RecordID: recordID, Level: level, Current: current, + Program: program, + ExpiryPolicy: expiryPolicy, NowMS: nowMs, }) if err != nil { return ledger.GrantVipReceipt{}, err } if err := r.insertWalletOutbox(ctx, tx, []walletOutboxEvent{ - vipActivatedEvent(transactionID, command.CommandID, command.TargetUserID, command.GrantSource, activation.Action, activation.PreviousLevel, activation.VIP, level.RewardResourceGroupID, activation.ResourceGrantID, activation.RewardItems, nowMs), + vipActivatedEvent(transactionID, command.CommandID, command.TargetUserID, command.GrantSource, activation.Action, activation.PreviousLevel, activation.PreviousExpiresAtMS, activation.ExpiryPolicy, activation.VIP, level.RewardResourceGroupID, activation.ResourceGrantID, activation.RewardItems, nowMs), }); err != nil { return ledger.GrantVipReceipt{}, err } if err := tx.Commit(); err != nil { return ledger.GrantVipReceipt{}, err } + state, err := r.GetVipState(ctx, command.TargetUserID) + if err != nil { + return ledger.GrantVipReceipt{}, err + } return ledger.GrantVipReceipt{ TransactionID: transactionID, Vip: activation.VIP, RewardItems: activation.RewardItems, + State: state, }, nil } +func (r *Repository) replayVipGrant(ctx context.Context, command ledger.GrantVipCommand, requestHash string) (ledger.GrantVipReceipt, error) { + tx, err := r.db.BeginTx(ctx, &sql.TxOptions{ReadOnly: true, Isolation: sql.LevelRepeatableRead}) + if err != nil { + return ledger.GrantVipReceipt{}, err + } + defer func() { _ = tx.Rollback() }() + txRow, exists, err := r.lookupTransactionConsistent(ctx, tx, command.CommandID, requestHash, bizTypeVIPGrant, xerr.LedgerConflict) + if err != nil { + return ledger.GrantVipReceipt{}, err + } + if !exists { + return ledger.GrantVipReceipt{}, xerr.New(xerr.Unavailable, "vip grant idempotent receipt is not visible") + } + receipt, err := r.vipGrantReceiptForTransaction(ctx, tx, txRow, command.TargetUserID) + if err != nil { + return ledger.GrantVipReceipt{}, err + } + _ = tx.Rollback() + receipt.State, err = r.GetVipState(ctx, command.TargetUserID) + return receipt, err +} + func (r *Repository) vipGrantReceiptForTransaction(ctx context.Context, tx *sql.Tx, txRow transactionRow, userID int64) (ledger.GrantVipReceipt, error) { var metadata struct { ResourceGrantID string `json:"resource_grant_id"` + TargetLevel int32 `json:"target_level"` + VIPName string `json:"vip_name"` + StartedAtMS int64 `json:"started_at_ms"` + NewExpiresAtMS int64 `json:"new_expires_at_ms"` + ProgramType string `json:"program_type"` + ConfigVersion int64 `json:"config_version"` + CreatedAtMS int64 `json:"created_at_ms"` } _ = json.Unmarshal([]byte(txRow.MetadataJSON), &metadata) - vip, err := r.queryUserVip(ctx, tx, userID, time.Now().UnixMilli(), false) - if err != nil { - return ledger.GrantVipReceipt{}, err + vip := ledger.UserVip{ + UserID: userID, + Level: metadata.TargetLevel, + Name: metadata.VIPName, + Active: metadata.TargetLevel > 0 && metadata.NewExpiresAtMS > time.Now().UnixMilli(), + StartedAtMS: metadata.StartedAtMS, + ExpiresAtMS: metadata.NewExpiresAtMS, + UpdatedAtMS: metadata.CreatedAtMS, + ProgramType: metadata.ProgramType, + ConfigVersion: metadata.ConfigVersion, + } + if vip.Level <= 0 || vip.ExpiresAtMS <= 0 { + // 迁移前的历史赠送元数据没有完整快照,只能兼容读取当前会员;新命令始终走上面的稳定回执。 + var err error + vip, err = r.queryUserVip(ctx, tx, userID, time.Now().UnixMilli(), false) + if err != nil { + return ledger.GrantVipReceipt{}, err + } } rewards, err := r.rewardItemsByGrant(ctx, tx, metadata.ResourceGrantID, vip.ExpiresAtMS) if err != nil { diff --git a/services/wallet-service/internal/storage/mysql/vip_policy_test.go b/services/wallet-service/internal/storage/mysql/vip_policy_test.go new file mode 100644 index 00000000..9bbc4d5b --- /dev/null +++ b/services/wallet-service/internal/storage/mysql/vip_policy_test.go @@ -0,0 +1,50 @@ +package mysql + +import ( + "testing" + "time" + + "hyapp/services/wallet-service/internal/domain/ledger" +) + +func TestVipActivationWindowReplaceFromNowDropsUpgradeRemainder(t *testing.T) { + nowMS := time.Now().UnixMilli() + durationMS := int64(30 * 24 * time.Hour / time.Millisecond) + current := ledger.UserVip{ + Level: 3, + Active: true, + StartedAtMS: nowMS - durationMS, + ExpiresAtMS: nowMS + int64(15*24*time.Hour/time.Millisecond), + } + startedAtMS, expiresAtMS, err := vipActivationWindow(current, ledger.VipLevel{Level: 4, DurationMS: durationMS}, ledger.VipExpiryPolicyReplaceFromNow, nowMS) + if err != nil { + t.Fatalf("vipActivationWindow failed: %v", err) + } + if startedAtMS != nowMS || expiresAtMS != nowMS+durationMS { + t.Fatalf("higher Fami VIP must replace from now: started=%d expires=%d now=%d duration=%d", startedAtMS, expiresAtMS, nowMS, durationMS) + } +} + +func TestVipActivationWindowKeepsSameLevelRenewalAndLegacyUpgrade(t *testing.T) { + nowMS := time.Now().UnixMilli() + durationMS := int64(7 * 24 * time.Hour / time.Millisecond) + current := ledger.UserVip{Level: 3, Active: true, StartedAtMS: nowMS - durationMS, ExpiresAtMS: nowMS + durationMS} + for _, testCase := range []struct { + name string + level int32 + policy string + }{ + {name: "same level in P1", level: 3, policy: ledger.VipExpiryPolicyReplaceFromNow}, + {name: "legacy upgrade", level: 4, policy: ledger.VipExpiryPolicyExtendRemaining}, + } { + t.Run(testCase.name, func(t *testing.T) { + startedAtMS, expiresAtMS, err := vipActivationWindow(current, ledger.VipLevel{Level: testCase.level, DurationMS: durationMS}, testCase.policy, nowMS) + if err != nil { + t.Fatalf("vipActivationWindow failed: %v", err) + } + if startedAtMS != current.StartedAtMS || expiresAtMS != current.ExpiresAtMS+durationMS { + t.Fatalf("renew/legacy must extend remaining time: started=%d expires=%d", startedAtMS, expiresAtMS) + } + }) + } +} diff --git a/services/wallet-service/internal/storage/mysql/vip_program_repository.go b/services/wallet-service/internal/storage/mysql/vip_program_repository.go new file mode 100644 index 00000000..3a01a948 --- /dev/null +++ b/services/wallet-service/internal/storage/mysql/vip_program_repository.go @@ -0,0 +1,342 @@ +package mysql + +import ( + "context" + "database/sql" + "errors" + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + "hyapp/services/wallet-service/internal/domain/ledger" + resourcedomain "hyapp/services/wallet-service/internal/domain/resource" + "strings" + "time" +) + +type vipProgramScanner interface { + Scan(dest ...any) error +} + +type vipBenefitRows interface { + Next() bool + Scan(dest ...any) error + Err() error + Close() error +} + +// vipSnapshotQuerier 是 VIP 组合读模型的最小查询能力;*sql.Tx 和 *sql.DB 都满足。 +// 组合读取统一接收该接口,防止 helper 意外逃逸到 r.db、破坏调用者的 repeatable-read 快照。 +type vipSnapshotQuerier interface { + QueryContext(context.Context, string, ...any) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...any) *sql.Row +} + +// GetVipProgramConfig 返回当前 App 唯一的 VIP 状态机配置和用于后台展示的权益目录。 +// 权益目录取最高等级的显式集合;运行时仍只查询用户有效等级对应的那一组数据。 +func (r *Repository) GetVipProgramConfig(ctx context.Context) (ledger.VipProgramConfig, []ledger.VipBenefit, error) { + if r == nil || r.db == nil { + return ledger.VipProgramConfig{}, nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + tx, err := r.db.BeginTx(ctx, &sql.TxOptions{ReadOnly: true, Isolation: sql.LevelRepeatableRead}) + if err != nil { + return ledger.VipProgramConfig{}, nil, err + } + defer func() { _ = tx.Rollback() }() + config, err := r.requireVipProgramConfig(ctx, tx) + if err != nil { + return ledger.VipProgramConfig{}, nil, err + } + benefits, err := r.listVipLevelBenefits(ctx, tx, config.LevelCount, false) + return config, benefits, err +} + +// GetVipState 合并付费会员和当前佩戴体验卡。启用体验卡时不按等级限制切换; +// 卡片过期、卸下或 App 关闭体验卡能力后都会自然回落到仍有效的付费会员。 +func (r *Repository) GetVipState(ctx context.Context, userID int64) (ledger.VipState, error) { + if r == nil || r.db == nil { + return ledger.VipState{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + if userID <= 0 { + return ledger.VipState{}, xerr.New(xerr.InvalidArgument, "user_id is required") + } + nowMS := time.Now().UnixMilli() + // 先清理失效装备指针,再用一个 repeatable-read 快照读取 program、会员、卡片和权益, + // 防止后台改配置时返回“新 config_version + 旧 benefits”一类混合状态。 + if err := r.pruneExpiredUserResourceEquipment(ctx, []int64{userID}, []string{resourcedomain.TypeVIPTrialCard}, nowMS); err != nil { + return ledger.VipState{}, err + } + tx, err := r.db.BeginTx(ctx, &sql.TxOptions{ReadOnly: true, Isolation: sql.LevelRepeatableRead}) + if err != nil { + return ledger.VipState{}, err + } + defer func() { _ = tx.Rollback() }() + config, err := r.requireVipProgramConfig(ctx, tx) + if err != nil { + return ledger.VipState{}, err + } + return r.getVipStateFromSnapshot(ctx, tx, userID, nowMS, config) +} + +// requireVipProgramConfig 从调用者指定的快照读取 App 配置,并把缺迁移/错 app_code 明确映射为业务错误。 +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 config, err +} + +// getVipStateFromSnapshot 只使用调用者事务装配 paid、已佩戴卡片、最终身份与权益。 +// raw 事实始终返回;program 总开关关闭时不产生 effective VIP,体验卡开关关闭时则仅回落 paid。 +func (r *Repository) getVipStateFromSnapshot(ctx context.Context, querier vipSnapshotQuerier, userID int64, nowMS int64, config ledger.VipProgramConfig) (ledger.VipState, error) { + paid, err := r.queryUserVip(ctx, querier, userID, nowMS, false) + if errors.Is(err, sql.ErrNoRows) { + paid = ledger.UserVip{UserID: userID, ProgramType: config.ProgramType, ConfigVersion: config.ConfigVersion} + } else if err != nil { + return ledger.VipState{}, err + } + + trial, err := r.queryEquippedVipTrialCardWithQuery(ctx, querier, userID, nowMS) + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return ledger.VipState{}, err + } + if errors.Is(err, sql.ErrNoRows) { + trial = nil + } + settings, err := r.queryVipUserSettings(ctx, querier, userID, false) + if err != nil { + return ledger.VipState{}, err + } + + state := ledger.VipState{ + PaidVip: paid, + EquippedTrialCard: trial, + EffectiveSource: ledger.VipEffectiveSourceNone, + EvaluatedAtMS: nowMS, + ProgramConfig: config, + UserSettings: settings, + EffectiveVip: ledger.UserVip{ + UserID: userID, + ProgramType: config.ProgramType, + ConfigVersion: config.ConfigVersion, + }, + } + if config.Status != ledger.VipStatusActive { + return state, nil + } + if paid.Active { + state.EffectiveVip = paid + state.EffectiveSource = ledger.VipEffectiveSourcePaid + } + if config.TrialCardEnabled && trial != nil { + state.EffectiveVip = ledger.UserVip{ + UserID: userID, + Level: trial.Level, + Name: trial.Name, + Active: true, + StartedAtMS: trial.EffectiveAtMS, + ExpiresAtMS: trial.ExpiresAtMS, + UpdatedAtMS: trial.UpdatedAtMS, + ProgramType: config.ProgramType, + ConfigVersion: config.ConfigVersion, + } + state.EffectiveSource = ledger.VipEffectiveSourceTrial + } + if !state.EffectiveVip.Active || state.EffectiveVip.Level <= 0 { + return state, nil + } + benefits, err := r.listVipLevelBenefits(ctx, querier, state.EffectiveVip.Level, true) + if err != nil { + return ledger.VipState{}, err + } + if state.EffectiveSource == ledger.VipEffectiveSourceTrial { + filtered := benefits[:0] + for _, benefit := range benefits { + // 金币返现是付费会员硬边界,不能依赖后台复选框;即使历史配置误写为 true 也必须二次排除。 + if benefit.TrialEnabled && benefit.BenefitCode != ledger.VipBenefitCodeDailyCoinRebate { + filtered = append(filtered, benefit) + } + } + benefits = filtered + } + state.EffectiveBenefits = benefits + return state, nil +} + +// CheckVipBenefit 只匹配 wallet 已合并并过滤后的 effective_benefits,不能退化成 level >= N。 +func (r *Repository) CheckVipBenefit(ctx context.Context, userID int64, benefitCode string) (ledger.CheckVipBenefitResult, error) { + state, err := r.GetVipState(ctx, userID) + if err != nil { + return ledger.CheckVipBenefitResult{}, err + } + code := strings.ToLower(strings.TrimSpace(benefitCode)) + result := ledger.CheckVipBenefitResult{ + State: state, + DenialReason: "benefit_not_enabled", + EvaluatedAtMS: state.EvaluatedAtMS, + } + if !state.EffectiveVip.Active { + result.DenialReason = "vip_inactive" + return result, nil + } + for _, benefit := range state.EffectiveBenefits { + if strings.ToLower(strings.TrimSpace(benefit.BenefitCode)) != code { + continue + } + result.Benefit = benefit + // effective_benefits 保留用户实际拥有的权益资格;可关闭通知只在执行时做设置门禁, + // 从而客户端关闭后仍能看见权益并重新开启。 + if !state.UserSettings.AllowsBenefitSetting(code) { + result.DenialReason = "user_setting_disabled" + return result, nil + } + result.Allowed = true + result.DenialReason = "" + return result, nil + } + return result, nil +} + +func vipProgramSelectSQL() string { + return ` + SELECT app_code, program_type, level_count, same_level_expiry_policy, + upgrade_expiry_policy, downgrade_purchase_policy, benefit_inheritance_policy, + grant_mode, trial_card_enabled, status, config_version, updated_by_admin_id, + created_at_ms, updated_at_ms + FROM vip_program_configs + WHERE app_code = ?` +} + +func (r *Repository) queryVipProgramConfig(ctx context.Context, scanner vipProgramScanner) (ledger.VipProgramConfig, error) { + var config ledger.VipProgramConfig + err := scanner.Scan( + &config.AppCode, + &config.ProgramType, + &config.LevelCount, + &config.SameLevelExpiryPolicy, + &config.UpgradeExpiryPolicy, + &config.DowngradePurchasePolicy, + &config.BenefitInheritancePolicy, + &config.GrantMode, + &config.TrialCardEnabled, + &config.Status, + &config.ConfigVersion, + &config.UpdatedByAdminID, + &config.CreatedAtMS, + &config.UpdatedAtMS, + ) + return config, err +} + +type vipBenefitQuerier interface { + QueryContext(context.Context, string, ...any) (*sql.Rows, error) +} + +func (r *Repository) listVipLevelBenefits(ctx context.Context, querier vipBenefitQuerier, level int32, activeOnly bool) ([]ledger.VipBenefit, error) { + query := ` + SELECT benefit_code, name, benefit_type, unlock_level, status, trial_enabled, + resource_id, resource_type, execution_scope, auto_equip, sort_order, + metadata_json, created_at_ms, updated_at_ms + FROM vip_level_benefits + WHERE app_code = ? AND level = ?` + args := []any{appcode.FromContext(ctx), level} + if activeOnly { + query += ` AND status = ?` + args = append(args, ledger.VipStatusActive) + } + query += ` ORDER BY sort_order ASC, benefit_code ASC` + rows, err := querier.QueryContext(ctx, query, args...) + if err != nil { + return nil, err + } + defer rows.Close() + benefits := make([]ledger.VipBenefit, 0) + for rows.Next() { + benefit, err := scanVipBenefit(rows) + if err != nil { + return nil, err + } + benefits = append(benefits, benefit) + } + return benefits, rows.Err() +} + +func scanVipBenefit(scanner vipProgramScanner) (ledger.VipBenefit, error) { + var benefit ledger.VipBenefit + var metadata sql.NullString + err := scanner.Scan( + &benefit.BenefitCode, + &benefit.Name, + &benefit.BenefitType, + &benefit.UnlockLevel, + &benefit.Status, + &benefit.TrialEnabled, + &benefit.ResourceID, + &benefit.ResourceType, + &benefit.ExecutionScope, + &benefit.AutoEquip, + &benefit.SortOrder, + &metadata, + &benefit.CreatedAtMS, + &benefit.UpdatedAtMS, + ) + if metadata.Valid { + benefit.MetadataJSON = metadata.String + } + return benefit, err +} + +type vipRowQuerier interface { + QueryRowContext(context.Context, string, ...any) *sql.Row +} + +func (r *Repository) queryEquippedVipTrialCardWithQuery(ctx context.Context, querier vipRowQuerier, userID int64, nowMS int64) (*ledger.VipTrialCard, error) { + row := querier.QueryRowContext(ctx, ` + SELECT c.trial_card_id, c.entitlement_id, c.resource_id, c.user_id, c.level, + c.name, c.status, c.duration_ms, c.effective_at_ms, c.expires_at_ms, + c.grant_source, c.source_grant_id, c.created_at_ms, c.updated_at_ms + FROM user_resource_equipment eq + JOIN user_vip_trial_cards c ON c.app_code = eq.app_code + AND c.user_id = eq.user_id AND c.entitlement_id = eq.entitlement_id + JOIN user_resource_entitlements e ON e.app_code = eq.app_code + AND e.user_id = eq.user_id AND e.entitlement_id = eq.entitlement_id + JOIN resources r ON r.app_code = eq.app_code AND r.resource_id = eq.resource_id + WHERE eq.app_code = ? AND eq.user_id = ? AND eq.resource_type = ? + AND c.status = ? AND c.effective_at_ms <= ? AND c.expires_at_ms > ? + AND e.status = 'active' AND e.effective_at_ms <= ? + AND (e.expires_at_ms = 0 OR e.expires_at_ms > ?) AND e.remaining_quantity > 0 + AND r.status = 'active' + LIMIT 1`, + appcode.FromContext(ctx), userID, resourcedomain.TypeVIPTrialCard, + ledger.VipTrialCardStatusActive, nowMS, nowMS, nowMS, nowMS, + ) + card, err := scanVipTrialCard(row, nowMS) + if err != nil { + return nil, err + } + card.Equipped = true + return &card, nil +} + +func scanVipTrialCard(scanner vipProgramScanner, nowMS int64) (ledger.VipTrialCard, error) { + var card ledger.VipTrialCard + err := scanner.Scan( + &card.TrialCardID, + &card.EntitlementID, + &card.ResourceID, + &card.UserID, + &card.Level, + &card.Name, + &card.Status, + &card.DurationMS, + &card.EffectiveAtMS, + &card.ExpiresAtMS, + &card.GrantSource, + &card.SourceGrantID, + &card.CreatedAtMS, + &card.UpdatedAtMS, + ) + if err == nil && card.ExpiresAtMS > nowMS { + card.RemainingDurationMS = card.ExpiresAtMS - nowMS + } + return card, 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 09bc246e..b5877ebc 100644 --- a/services/wallet-service/internal/storage/mysql/vip_purchase_repository.go +++ b/services/wallet-service/internal/storage/mysql/vip_purchase_repository.go @@ -22,21 +22,38 @@ func (r *Repository) PurchaseVip(ctx context.Context, command ledger.PurchaseVip ctx = contextWithCommandApp(ctx, command.AppCode) command.AppCode = appcode.FromContext(ctx) + requestHash := stableHash(fmt.Sprintf("vip_purchase|%s|%d|%d", command.AppCode, command.UserID, command.Level)) + nowMs := time.Now().UnixMilli() tx, err := r.db.BeginTx(ctx, nil) if err != nil { return ledger.PurchaseVipReceipt{}, err } defer func() { _ = tx.Rollback() }() - requestHash := stableHash(fmt.Sprintf("vip_purchase|%s|%d|%d", command.AppCode, command.UserID, command.Level)) - if txRow, exists, err := r.lookupTransaction(ctx, tx, command.CommandID, requestHash, bizTypeVIPPurchase); err != nil || exists { + if err := r.lockVipCommand(ctx, tx, command.CommandID, bizTypeVIPPurchase, requestHash, nowMs, xerr.LedgerConflict); err != nil { + return ledger.PurchaseVipReceipt{}, err + } + if _, exists, err := r.lookupTransactionConsistent(ctx, tx, command.CommandID, requestHash, bizTypeVIPPurchase, xerr.LedgerConflict); err != nil || exists { if err != nil || !exists { return ledger.PurchaseVipReceipt{}, err } - return r.vipPurchaseReceiptForTransaction(ctx, tx, txRow.TransactionID, command.UserID) + _ = tx.Rollback() + return r.replayVipPurchase(ctx, command, requestHash) } - nowMs := time.Now().UnixMilli() + 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") + } + if err != nil { + return ledger.PurchaseVipReceipt{}, err + } + if program.Status != ledger.VipStatusActive { + return ledger.PurchaseVipReceipt{}, xerr.New(xerr.Conflict, "vip program is disabled") + } + if command.Level > program.LevelCount { + return ledger.PurchaseVipReceipt{}, xerr.New(xerr.VIPLevelNotFound, "vip level exceeds program level_count") + } level, err := r.getVipLevelForUpdate(ctx, tx, command.Level) if err != nil { return ledger.PurchaseVipReceipt{}, err @@ -49,15 +66,20 @@ func (r *Repository) PurchaseVip(ctx context.Context, command ledger.PurchaseVip return ledger.PurchaseVipReceipt{}, err } previousLevel := int32(0) - baseExpiresAt := nowMs if current.Active { previousLevel = current.Level - baseExpiresAt = current.ExpiresAtMS if current.Level > command.Level { return ledger.PurchaseVipReceipt{}, xerr.New(xerr.VIPDowngradeNotAllowed, "vip downgrade is not allowed") } } - newExpiresAt := baseExpiresAt + level.DurationMS + expiryPolicy := program.SameLevelExpiryPolicy + if current.Active && command.Level > current.Level { + expiryPolicy = program.UpgradeExpiryPolicy + } + startedAtMS, newExpiresAt, err := vipActivationWindow(current, level, expiryPolicy, nowMs) + if err != nil { + return ledger.PurchaseVipReceipt{}, err + } account, err := r.lockAccount(ctx, tx, command.UserID, ledger.AssetCoin, false, nowMs) if err != nil { return ledger.PurchaseVipReceipt{}, err @@ -70,20 +92,30 @@ func (r *Repository) PurchaseVip(ctx context.Context, command ledger.PurchaseVip 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, - "previous_level": previousLevel, - "price_coin": level.PriceCoin, - "expires_at_ms": newExpiresAt, - "balance_after": coinBalanceAfter, - "reward_group_id": level.RewardResourceGroupID, - "duration_ms": level.DurationMS, + "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, + "reward_group_id": level.RewardResourceGroupID, + "duration_ms": level.DurationMS, + "previous_expires_at_ms": current.ExpiresAtMS, + "started_at_ms": startedAtMS, + "program_type": program.ProgramType, + "config_version": program.ConfigVersion, + "expiry_policy": expiryPolicy, // 兼容旧账务元数据字段;业务已不再按累计充值限制 VIP 购买,因此固定记录 0。 "required_recharge_coin_amount": int64(0), } if err := r.insertTransaction(ctx, tx, transactionID, command.CommandID, bizTypeVIPPurchase, requestHash, orderID, metadata, nowMs); err != nil { + if isMySQLDuplicateError(err) { + _ = tx.Rollback() + return r.replayVipPurchase(ctx, command, requestHash) + } return ledger.PurchaseVipReceipt{}, err } if err := r.applyAccountDelta(ctx, tx, account, -level.PriceCoin, 0, nowMs); err != nil { @@ -112,6 +144,8 @@ func (r *Repository) PurchaseVip(ctx context.Context, command ledger.PurchaseVip RecordID: orderID, Level: level, Current: current, + Program: program, + ExpiryPolicy: expiryPolicy, NowMS: nowMs, }) if err != nil { @@ -119,11 +153,15 @@ func (r *Repository) PurchaseVip(ctx context.Context, command ledger.PurchaseVip } if _, err := tx.ExecContext(ctx, ` INSERT INTO vip_purchase_orders ( - app_code, order_id, command_id, user_id, target_level, previous_level, price_coin, - status, wallet_transaction_id, resource_grant_id, request_hash, created_at_ms, updated_at_ms - ) VALUES (?, ?, ?, ?, ?, ?, ?, 'succeeded', ?, ?, ?, ?, ?)`, + app_code, order_id, command_id, user_id, target_level, previous_level, + previous_expires_at_ms, new_expires_at_ms, price_coin, duration_ms, + program_type, config_version, expiry_policy, status, wallet_transaction_id, + resource_grant_id, request_hash, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'succeeded', ?, ?, ?, ?, ?)`, command.AppCode, orderID, command.CommandID, command.UserID, command.Level, previousLevel, - level.PriceCoin, transactionID, activation.ResourceGrantID, requestHash, nowMs, nowMs, + current.ExpiresAtMS, activation.VIP.ExpiresAtMS, level.PriceCoin, level.DurationMS, + program.ProgramType, program.ConfigVersion, expiryPolicy, transactionID, + activation.ResourceGrantID, requestHash, nowMs, nowMs, ); err != nil { return ledger.PurchaseVipReceipt{}, err } @@ -147,7 +185,7 @@ func (r *Repository) PurchaseVip(ctx context.Context, command ledger.PurchaseVip Payload: metadata, CreatedAtMS: nowMs, }, - vipActivatedEvent(transactionID, command.CommandID, command.UserID, ledger.VipGrantSourcePurchase, activation.Action, activation.PreviousLevel, activation.VIP, level.RewardResourceGroupID, activation.ResourceGrantID, activation.RewardItems, nowMs), + vipActivatedEvent(transactionID, command.CommandID, command.UserID, ledger.VipGrantSourcePurchase, activation.Action, activation.PreviousLevel, activation.PreviousExpiresAtMS, activation.ExpiryPolicy, activation.VIP, level.RewardResourceGroupID, activation.ResourceGrantID, activation.RewardItems, nowMs), }); err != nil { return ledger.PurchaseVipReceipt{}, err } @@ -155,6 +193,10 @@ func (r *Repository) PurchaseVip(ctx context.Context, command ledger.PurchaseVip return ledger.PurchaseVipReceipt{}, err } + state, err := r.GetVipState(ctx, command.UserID) + if err != nil { + return ledger.PurchaseVipReceipt{}, err + } return ledger.PurchaseVipReceipt{ OrderID: orderID, TransactionID: transactionID, @@ -162,22 +204,44 @@ func (r *Repository) PurchaseVip(ctx context.Context, command ledger.PurchaseVip CoinSpent: level.PriceCoin, CoinBalanceAfter: coinBalanceAfter, RewardItems: activation.RewardItems, + State: state, }, nil } +func (r *Repository) replayVipPurchase(ctx context.Context, command ledger.PurchaseVipCommand, requestHash string) (ledger.PurchaseVipReceipt, error) { + tx, err := r.db.BeginTx(ctx, &sql.TxOptions{ReadOnly: true, Isolation: sql.LevelRepeatableRead}) + if err != nil { + return ledger.PurchaseVipReceipt{}, err + } + defer func() { _ = tx.Rollback() }() + txRow, exists, err := r.lookupTransactionConsistent(ctx, tx, command.CommandID, requestHash, bizTypeVIPPurchase, xerr.LedgerConflict) + if err != nil { + return ledger.PurchaseVipReceipt{}, err + } + if !exists { + return ledger.PurchaseVipReceipt{}, xerr.New(xerr.Unavailable, "vip purchase idempotent receipt is not visible") + } + receipt, err := r.vipPurchaseReceiptForTransaction(ctx, tx, txRow, command.UserID) + if err != nil { + return ledger.PurchaseVipReceipt{}, err + } + _ = tx.Rollback() + receipt.State, err = r.GetVipState(ctx, command.UserID) + return receipt, err +} + func (r *Repository) activateUserVip(ctx context.Context, tx *sql.Tx, command vipActivationCommand) (vipActivationResult, error) { previousLevel := int32(0) - baseExpiresAt := command.NowMS - startedAt := command.NowMS if command.Current.Active { previousLevel = command.Current.Level - baseExpiresAt = command.Current.ExpiresAtMS - startedAt = command.Current.StartedAtMS if command.Current.Level > command.Level.Level { return vipActivationResult{}, xerr.New(xerr.VIPDowngradeNotAllowed, "vip downgrade is not allowed") } } - expiresAt := baseExpiresAt + command.Level.DurationMS + startedAt, expiresAt, err := vipActivationWindow(command.Current, command.Level, command.ExpiryPolicy, command.NowMS) + if err != nil { + return vipActivationResult{}, err + } rewardItems, resourceGrantID, err := r.applyVipRewardGroup(ctx, tx, vipRewardGrantCommand{ AppCode: command.AppCode, CommandID: command.CommandID, @@ -191,38 +255,73 @@ func (r *Repository) activateUserVip(ctx context.Context, tx *sql.Tx, command vi } if _, err := tx.ExecContext(ctx, ` UPDATE user_vip_memberships - SET level = ?, name = ?, status = ?, started_at_ms = ?, expires_at_ms = ?, updated_at_ms = ? + SET level = ?, name = ?, status = ?, program_type = ?, config_version = ?, + started_at_ms = ?, expires_at_ms = ?, updated_at_ms = ? WHERE app_code = ? AND user_id = ?`, - command.Level.Level, command.Level.Name, ledger.VipStatusActive, startedAt, expiresAt, command.NowMS, command.AppCode, command.UserID, + command.Level.Level, command.Level.Name, ledger.VipStatusActive, + command.Program.ProgramType, command.Program.ConfigVersion, + startedAt, expiresAt, command.NowMS, command.AppCode, command.UserID, ); err != nil { return vipActivationResult{}, err } action := vipActivationAction(command.Source, previousLevel, command.Level.Level) if _, err := tx.ExecContext(ctx, ` INSERT INTO user_vip_history ( - app_code, user_id, action, previous_level, new_level, order_id, created_at_ms - ) VALUES (?, ?, ?, ?, ?, ?, ?)`, - command.AppCode, command.UserID, action, previousLevel, command.Level.Level, command.RecordID, command.NowMS, + app_code, user_id, action, previous_level, new_level, previous_expires_at_ms, + new_expires_at_ms, program_type, config_version, order_id, created_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + command.AppCode, command.UserID, action, previousLevel, command.Level.Level, + command.Current.ExpiresAtMS, expiresAt, command.Program.ProgramType, + command.Program.ConfigVersion, command.RecordID, command.NowMS, ); err != nil { return vipActivationResult{}, err } return vipActivationResult{ VIP: ledger.UserVip{ - UserID: command.UserID, - Level: command.Level.Level, - Name: command.Level.Name, - Active: true, - StartedAtMS: startedAt, - ExpiresAtMS: expiresAt, - UpdatedAtMS: command.NowMS, + UserID: command.UserID, + Level: command.Level.Level, + Name: command.Level.Name, + Active: true, + StartedAtMS: startedAt, + ExpiresAtMS: expiresAt, + UpdatedAtMS: command.NowMS, + ProgramType: command.Program.ProgramType, + ConfigVersion: command.Program.ConfigVersion, }, - PreviousLevel: previousLevel, - Action: action, - ResourceGrantID: resourceGrantID, - RewardItems: rewardItems, + PreviousLevel: previousLevel, + PreviousExpiresAtMS: command.Current.ExpiresAtMS, + ExpiryPolicy: command.ExpiryPolicy, + Action: action, + ResourceGrantID: resourceGrantID, + RewardItems: rewardItems, }, nil } +// vipActivationWindow 把有效期策略收敛成一个纯函数,购买、后台直发和测试共享同一边界。 +// replace_from_now 只作用于有效会员的高级升级;同级续费仍始终从当前截止时间累加。 +func vipActivationWindow(current ledger.UserVip, level ledger.VipLevel, expiryPolicy string, nowMS int64) (int64, int64, error) { + if level.DurationMS <= 0 { + return 0, 0, xerr.New(xerr.InvalidArgument, "vip duration_ms must be positive") + } + startedAtMS := nowMS + baseExpiresAtMS := nowMS + if current.Active { + startedAtMS = current.StartedAtMS + baseExpiresAtMS = current.ExpiresAtMS + if level.Level > current.Level && expiryPolicy == ledger.VipExpiryPolicyReplaceFromNow { + startedAtMS = nowMS + baseExpiresAtMS = nowMS + } + } + if expiryPolicy != ledger.VipExpiryPolicyExtendRemaining && expiryPolicy != ledger.VipExpiryPolicyReplaceFromNow { + return 0, 0, xerr.New(xerr.Conflict, "vip expiry policy is invalid") + } + if level.DurationMS > int64(^uint64(0)>>1)-baseExpiresAtMS { + return 0, 0, xerr.New(xerr.InvalidArgument, "vip expiry overflow") + } + return startedAtMS, baseExpiresAtMS + level.DurationMS, nil +} + func vipActivationAction(source string, previousLevel int32, newLevel int32) string { if source != ledger.VipGrantSourcePurchase { return source @@ -295,12 +394,23 @@ func (r *Repository) applyVipRewardGroup(ctx context.Context, tx *sql.Tx, comman if err != nil { return nil, "", err } - rewards = append(rewards, ledger.VipRewardItem{Quantity: inserted.Quantity, ExpiresAtMS: 0}) + assetType := resourcedomain.NormalizeWalletAssetType(item.WalletAssetType) + // 首次回执与幂等回放都使用同一资源快照形状,wallet_asset 不能在重试时凭空多出字段。 + rewards = append(rewards, ledger.VipRewardItem{ + ResourceCode: assetType, + ResourceType: "wallet_asset", + Name: assetType, + Quantity: inserted.Quantity, + ExpiresAtMS: 0, + }) continue } if err := validateActiveResourceGroupResource(item.Resource); err != nil { return nil, "", err } + if resourcedomain.NormalizeResourceType(item.Resource.ResourceType) == resourcedomain.TypeVIPTrialCard { + return nil, "", xerr.New(xerr.InvalidArgument, "vip reward group cannot contain vip_trial_card") + } inserted, err := r.applyGrantItem(ctx, tx, grantID, rewardCommandID, command.UserID, item.Resource, item.Quantity, durationMS, nowMs) if err != nil { return nil, "", err @@ -330,7 +440,7 @@ func (r *Repository) applyVipRewardGroup(ctx context.Context, tx *sql.Tx, comman return rewards, grantID, nil } -func vipActivatedEvent(transactionID string, commandID string, userID int64, source string, action string, previousLevel int32, vip ledger.UserVip, rewardGroupID int64, resourceGrantID string, rewardItems []ledger.VipRewardItem, nowMs int64) walletOutboxEvent { +func vipActivatedEvent(transactionID string, commandID string, userID int64, source string, action string, previousLevel int32, previousExpiresAtMS int64, expiryPolicy string, vip ledger.UserVip, rewardGroupID int64, resourceGrantID string, rewardItems []ledger.VipRewardItem, nowMs int64) walletOutboxEvent { payload := map[string]any{ "event_type": "VipActivated", "transaction_id": transactionID, @@ -339,10 +449,14 @@ func vipActivatedEvent(transactionID string, commandID string, userID int64, sou "source": source, "action": action, "previous_level": previousLevel, + "previous_expires_at_ms": previousExpiresAtMS, "level": vip.Level, "vip_name": vip.Name, "started_at_ms": vip.StartedAtMS, "expires_at_ms": vip.ExpiresAtMS, + "program_type": vip.ProgramType, + "config_version": vip.ConfigVersion, + "expiry_policy": expiryPolicy, "reward_resource_group_id": rewardGroupID, "resource_grant_id": resourceGrantID, "reward_items": vipRewardItemsNoticePayload(rewardItems), @@ -380,35 +494,71 @@ func vipRewardItemsNoticePayload(items []ledger.VipRewardItem) []map[string]any return payload } -func (r *Repository) vipPurchaseReceiptForTransaction(ctx context.Context, tx *sql.Tx, transactionID string, userID int64) (ledger.PurchaseVipReceipt, error) { +func (r *Repository) vipPurchaseReceiptForTransaction(ctx context.Context, tx *sql.Tx, txRow transactionRow, userID int64) (ledger.PurchaseVipReceipt, error) { var orderID string var level int32 var priceCoin int64 var grantID string + var expiresAtMS int64 + var durationMS int64 + var programType string + var configVersion int64 + var createdAtMS int64 + var currentLevelName string err := tx.QueryRowContext(ctx, ` - SELECT order_id, target_level, price_coin, resource_grant_id - FROM vip_purchase_orders - WHERE app_code = ? AND wallet_transaction_id = ?`, - appcode.FromContext(ctx), transactionID, - ).Scan(&orderID, &level, &priceCoin, &grantID) + SELECT o.order_id, o.target_level, o.price_coin, o.resource_grant_id, + o.new_expires_at_ms, o.duration_ms, o.program_type, o.config_version, + o.created_at_ms, COALESCE(v.name, '') + FROM vip_purchase_orders o + LEFT JOIN vip_levels v ON v.app_code = o.app_code AND v.level = o.target_level + WHERE o.app_code = ? AND o.wallet_transaction_id = ?`, + appcode.FromContext(ctx), txRow.TransactionID, + ).Scan(&orderID, &level, &priceCoin, &grantID, &expiresAtMS, &durationMS, &programType, &configVersion, &createdAtMS, ¤tLevelName) if err != nil { return ledger.PurchaseVipReceipt{}, err } - vip, err := r.queryUserVip(ctx, tx, userID, time.Now().UnixMilli(), false) + var metadata struct { + VIPName string `json:"vip_name"` + StartedAtMS int64 `json:"started_at_ms"` + ExpiresAtMS int64 `json:"expires_at_ms"` + } + _ = json.Unmarshal([]byte(txRow.MetadataJSON), &metadata) + if expiresAtMS <= 0 { + expiresAtMS = metadata.ExpiresAtMS + } + startedAtMS := metadata.StartedAtMS + if startedAtMS <= 0 { + startedAtMS = createdAtMS + if durationMS > 0 && expiresAtMS > durationMS && expiresAtMS-durationMS < startedAtMS { + startedAtMS = expiresAtMS - durationMS + } + } + vipName := strings.TrimSpace(metadata.VIPName) + if vipName == "" { + vipName = currentLevelName + } + vip := ledger.UserVip{ + UserID: userID, + Level: level, + Name: vipName, + Active: level > 0 && expiresAtMS > time.Now().UnixMilli(), + StartedAtMS: startedAtMS, + ExpiresAtMS: expiresAtMS, + UpdatedAtMS: createdAtMS, + ProgramType: programType, + ConfigVersion: configVersion, + } + balance, err := r.balanceAfterTransaction(ctx, tx, txRow.TransactionID, userID, ledger.AssetCoin) if err != nil { return ledger.PurchaseVipReceipt{}, err } - balance, err := r.balanceAfterTransaction(ctx, tx, transactionID, userID, ledger.AssetCoin) - if err != nil { - return ledger.PurchaseVipReceipt{}, err - } - rewards, err := r.rewardItemsByGrant(ctx, tx, grantID, vip.ExpiresAtMS) + rewards, err := r.rewardItemsByGrant(ctx, tx, grantID, expiresAtMS) if err != nil { return ledger.PurchaseVipReceipt{}, err } return ledger.PurchaseVipReceipt{ OrderID: orderID, - TransactionID: transactionID, + TransactionID: txRow.TransactionID, Vip: vip, CoinSpent: priceCoin, CoinBalanceAfter: balance.AvailableAmount, diff --git a/services/wallet-service/internal/storage/mysql/vip_query_repository.go b/services/wallet-service/internal/storage/mysql/vip_query_repository.go index 7f2d9ca7..3d9d763d 100644 --- a/services/wallet-service/internal/storage/mysql/vip_query_repository.go +++ b/services/wallet-service/internal/storage/mysql/vip_query_repository.go @@ -3,6 +3,7 @@ package mysql import ( "context" "database/sql" + "encoding/json" "errors" "hyapp/pkg/appcode" "hyapp/pkg/xerr" @@ -23,75 +24,104 @@ func (r *Repository) GetMyVip(ctx context.Context, userID int64) (ledger.UserVip return vip, err } -// ListVipPackages 返回当前会员和全部 active VIP 包。 -func (r *Repository) ListVipPackages(ctx context.Context, userID int64) (ledger.UserVip, []ledger.VipLevel, error) { +// ListVipPackages 在一个 repeatable-read 快照中返回最终 VIP 状态和全部 active 套餐。 +// state、program、level、benefit 与奖励资源必须使用同一事务,否则后台改版瞬间可能返回跨版本组合。 +func (r *Repository) ListVipPackages(ctx context.Context, userID int64) (ledger.VipState, []ledger.VipLevel, error) { if r == nil || r.db == nil { - return ledger.UserVip{}, nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + return ledger.VipState{}, nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") } - nowMs := time.Now().UnixMilli() - current, err := r.GetMyVip(ctx, userID) + nowMS := time.Now().UnixMilli() + if err := r.pruneExpiredUserResourceEquipment(ctx, []int64{userID}, []string{resourcedomain.TypeVIPTrialCard}, nowMS); err != nil { + return ledger.VipState{}, nil, err + } + tx, err := r.db.BeginTx(ctx, &sql.TxOptions{ReadOnly: true, Isolation: sql.LevelRepeatableRead}) if err != nil { - return ledger.UserVip{}, nil, err + return ledger.VipState{}, nil, err } - levels, err := r.listVipLevels(ctx, nowMs, current.Level) - return current, levels, err + defer func() { _ = tx.Rollback() }() + config, err := r.requireVipProgramConfig(ctx, tx) + if err != nil { + return ledger.VipState{}, nil, err + } + state, err := r.getVipStateFromSnapshot(ctx, tx, userID, nowMS, config) + if err != nil { + return ledger.VipState{}, nil, err + } + levels, err := r.listVipLevelsFromSnapshot(ctx, tx, config, nowMS, state.PaidVip.Level) + return state, levels, err } -// ListAdminVipLevels 返回后台配置页所需的全部 VIP 等级。 -func (r *Repository) ListAdminVipLevels(ctx context.Context) ([]ledger.VipLevel, error) { +// ListAdminVipLevels 返回同一 repeatable-read 快照中的 program 与全部动态等级。 +func (r *Repository) ListAdminVipLevels(ctx context.Context) (ledger.VipProgramConfig, []ledger.VipLevel, error) { if r == nil || r.db == nil { - return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + return ledger.VipProgramConfig{}, nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") } - rows, err := r.db.QueryContext(ctx, ` + tx, err := r.db.BeginTx(ctx, &sql.TxOptions{ReadOnly: true, Isolation: sql.LevelRepeatableRead}) + if err != nil { + return ledger.VipProgramConfig{}, nil, err + } + defer func() { _ = tx.Rollback() }() + config, err := r.requireVipProgramConfig(ctx, tx) + if err != nil { + return ledger.VipProgramConfig{}, nil, err + } + levels, err := r.listAdminVipLevelsFromSnapshot(ctx, tx, config, time.Now().UnixMilli()) + return config, levels, err +} + +// listAdminVipLevelsFromSnapshot 在调用者事务内装配完整后台等级读模型。 +// 必须先耗尽并关闭 level rows,再查询每级 rewards/benefits;MySQL 单连接不允许在活动 rows 上嵌套查询。 +func (r *Repository) listAdminVipLevelsFromSnapshot(ctx context.Context, querier vipSnapshotQuerier, config ledger.VipProgramConfig, nowMS int64) ([]ledger.VipLevel, error) { + rows, err := querier.QueryContext(ctx, ` SELECT level, name, status, price_coin, duration_ms, reward_resource_group_id, required_recharge_coin_amount, sort_order, created_at_ms, updated_at_ms FROM vip_levels - WHERE app_code = ? + WHERE app_code = ? AND level BETWEEN 1 AND ? ORDER BY level ASC`, - appcode.FromContext(ctx), + appcode.FromContext(ctx), config.LevelCount, ) if err != nil { return nil, err } - defer rows.Close() - - levels := make([]ledger.VipLevel, 0, 10) - for rows.Next() { - level, err := r.scanVipLevel(rows) - if err != nil { - return nil, err - } + levels, err := r.scanAndCloseVipLevels(rows, int(config.LevelCount)) + if err != nil { + return nil, err + } + for index := range levels { + level := &levels[index] if level.RewardResourceGroupID > 0 { - level.RewardItems, err = r.vipRewardItems(ctx, level.RewardResourceGroupID, time.Now().UnixMilli()+level.DurationMS) + level.RewardItems, err = r.vipRewardItemsWithQuery(ctx, querier, level.RewardResourceGroupID, nowMS+level.DurationMS) if err != nil { return nil, err } } - levels = append(levels, level) + level.Benefits, err = r.listVipLevelBenefits(ctx, querier, level.Level, false) + if err != nil { + return nil, err + } + level.ConfigVersion = config.ConfigVersion } - return levels, rows.Err() + return levels, nil } -func (r *Repository) listVipLevels(ctx context.Context, nowMs int64, currentLevel int32) ([]ledger.VipLevel, error) { - rows, err := r.db.QueryContext(ctx, ` +func (r *Repository) listVipLevelsFromSnapshot(ctx context.Context, querier vipSnapshotQuerier, config ledger.VipProgramConfig, nowMS int64, currentLevel int32) ([]ledger.VipLevel, error) { + rows, err := querier.QueryContext(ctx, ` SELECT level, name, status, price_coin, duration_ms, reward_resource_group_id, required_recharge_coin_amount, sort_order, created_at_ms, updated_at_ms FROM vip_levels - WHERE app_code = ? AND status = ? + WHERE app_code = ? AND status = ? AND level BETWEEN 1 AND ? ORDER BY sort_order ASC, level ASC`, - appcode.FromContext(ctx), ledger.VipStatusActive, + appcode.FromContext(ctx), ledger.VipStatusActive, config.LevelCount, ) if err != nil { return nil, err } - defer rows.Close() - - levels := make([]ledger.VipLevel, 0) - for rows.Next() { - level, err := r.scanVipLevel(rows) - if err != nil { - return nil, err - } + levels, err := r.scanAndCloseVipLevels(rows, int(config.LevelCount)) + if err != nil { + return nil, err + } + for index := range levels { + level := &levels[index] // VIP 累充门槛已下线,旧字段只作为兼容输出保留;购买资格只看当前 VIP 等级和配置启停。 level.UserRechargeCoinAmount = 0 level.RechargeGateRequired = false @@ -100,7 +130,25 @@ func (r *Repository) listVipLevels(ctx context.Context, nowMs int64, currentLeve if !level.CanPurchase { level.PurchaseLockedReason = "current_vip_higher" } - level.RewardItems, err = r.vipRewardItems(ctx, level.RewardResourceGroupID, nowMs+level.DurationMS) + level.RewardItems, err = r.vipRewardItemsWithQuery(ctx, querier, level.RewardResourceGroupID, nowMS+level.DurationMS) + if err != nil { + return nil, err + } + level.Benefits, err = r.listVipLevelBenefits(ctx, querier, level.Level, true) + if err != nil { + return nil, err + } + level.ConfigVersion = config.ConfigVersion + } + return levels, nil +} + +// scanAndCloseVipLevels 把主游标生命周期收敛在一个函数内,返回后调用方才能安全执行同事务子查询。 +func (r *Repository) scanAndCloseVipLevels(rows *sql.Rows, capacity int) ([]ledger.VipLevel, error) { + defer rows.Close() + levels := make([]ledger.VipLevel, 0, capacity) + for rows.Next() { + level, err := r.scanVipLevel(rows) if err != nil { return nil, err } @@ -132,9 +180,12 @@ func (r *Repository) scanVipLevel(scanner scanTarget) (ledger.VipLevel, error) { func (r *Repository) ensureUserVipForUpdate(ctx context.Context, tx *sql.Tx, userID int64, nowMs int64) (ledger.UserVip, error) { if _, err := tx.ExecContext(ctx, ` INSERT IGNORE INTO user_vip_memberships ( - app_code, user_id, level, name, status, started_at_ms, expires_at_ms, created_at_ms, updated_at_ms - ) VALUES (?, ?, 0, '', 'inactive', 0, 0, ?, ?)`, - appcode.FromContext(ctx), userID, nowMs, nowMs, + app_code, user_id, level, name, status, program_type, config_version, + started_at_ms, expires_at_ms, created_at_ms, updated_at_ms + ) + SELECT ?, ?, 0, '', 'inactive', program_type, config_version, 0, 0, ?, ? + FROM vip_program_configs WHERE app_code = ?`, + appcode.FromContext(ctx), userID, nowMs, nowMs, appcode.FromContext(ctx), ); err != nil { return ledger.UserVip{}, err } @@ -145,7 +196,8 @@ func (r *Repository) queryUserVip(ctx context.Context, querier interface { QueryRowContext(context.Context, string, ...any) *sql.Row }, userID int64, nowMs int64, lock bool) (ledger.UserVip, error) { query := ` - SELECT m.user_id, m.level, COALESCE(v.name, m.name), m.started_at_ms, m.expires_at_ms, m.updated_at_ms + SELECT m.user_id, m.level, COALESCE(v.name, m.name), m.started_at_ms, m.expires_at_ms, + m.updated_at_ms, m.program_type, m.config_version FROM user_vip_memberships m LEFT JOIN vip_levels v ON v.app_code = m.app_code AND v.level = m.level WHERE m.app_code = ? AND m.user_id = ?` @@ -153,7 +205,16 @@ func (r *Repository) queryUserVip(ctx context.Context, querier interface { query += ` FOR UPDATE` } var vip ledger.UserVip - if err := querier.QueryRowContext(ctx, query, appcode.FromContext(ctx), userID).Scan(&vip.UserID, &vip.Level, &vip.Name, &vip.StartedAtMS, &vip.ExpiresAtMS, &vip.UpdatedAtMS); err != nil { + if err := querier.QueryRowContext(ctx, query, appcode.FromContext(ctx), userID).Scan( + &vip.UserID, + &vip.Level, + &vip.Name, + &vip.StartedAtMS, + &vip.ExpiresAtMS, + &vip.UpdatedAtMS, + &vip.ProgramType, + &vip.ConfigVersion, + ); err != nil { return ledger.UserVip{}, err } vip.Active = vip.Level > 0 && vip.ExpiresAtMS > nowMs @@ -165,10 +226,15 @@ func (r *Repository) queryUserVip(ctx context.Context, querier interface { } func (r *Repository) vipRewardItems(ctx context.Context, groupID int64, expiresAtMS int64) ([]ledger.VipRewardItem, error) { + return r.vipRewardItemsWithQuery(ctx, r.db, groupID, expiresAtMS) +} + +// vipRewardItemsWithQuery 必须沿用调用者给定的 DB/事务;套餐列表通过它确保资源组也来自同一配置快照。 +func (r *Repository) vipRewardItemsWithQuery(ctx context.Context, querier vipBenefitQuerier, groupID int64, expiresAtMS int64) ([]ledger.VipRewardItem, error) { if groupID <= 0 { return nil, nil } - items, err := r.listResourceGroupItemsWithQuery(ctx, r.db, groupID) + items, err := r.listResourceGroupItemsWithQuery(ctx, querier, groupID) if err != nil { return nil, err } @@ -197,13 +263,11 @@ func (r *Repository) rewardItemsByGrant(ctx context.Context, tx *sql.Tx, grantID return nil, nil } rows, err := tx.QueryContext(ctx, ` - SELECT i.resource_id, r.resource_code, r.resource_type, r.name, i.quantity, - COALESCE(r.asset_url, ''), COALESCE(r.preview_url, ''), COALESCE(r.animation_url, '') - FROM resource_grant_items i - JOIN resources r ON r.app_code = i.app_code AND r.resource_id = i.resource_id - WHERE i.app_code = ? AND i.grant_id = ? AND i.result_type = ? - ORDER BY i.grant_item_id ASC`, - appcode.FromContext(ctx), grantID, resourcedomain.ResultEntitlement, + SELECT resource_id, resource_snapshot_json, quantity, result_type + FROM resource_grant_items + WHERE app_code = ? AND grant_id = ? + ORDER BY grant_item_id ASC`, + appcode.FromContext(ctx), grantID, ) if err != nil { return nil, err @@ -211,20 +275,45 @@ func (r *Repository) rewardItemsByGrant(ctx context.Context, tx *sql.Tx, grantID defer rows.Close() items := make([]ledger.VipRewardItem, 0) for rows.Next() { - var item ledger.VipRewardItem - if err := rows.Scan( - &item.ResourceID, - &item.ResourceCode, - &item.ResourceType, - &item.Name, - &item.Quantity, - &item.AssetURL, - &item.PreviewURL, - &item.AnimationURL, - ); err != nil { + var resourceID int64 + var snapshotJSON string + var quantity int64 + var resultType string + if err := rows.Scan(&resourceID, &snapshotJSON, &quantity, &resultType); err != nil { return nil, err } - item.ExpiresAtMS = expiresAtMS + item := ledger.VipRewardItem{ResourceID: resourceID, Quantity: quantity} + switch resultType { + case resourcedomain.ResultEntitlement: + var resource resourcedomain.Resource + if err := json.Unmarshal([]byte(snapshotJSON), &resource); err != nil { + return nil, xerr.New(xerr.LedgerConflict, "vip reward resource snapshot is invalid") + } + item.ResourceID = resource.ResourceID + item.ResourceCode = resource.ResourceCode + item.ResourceType = resource.ResourceType + item.Name = resource.Name + item.ExpiresAtMS = expiresAtMS + item.AssetURL = resource.AssetURL + item.PreviewURL = resource.PreviewURL + item.AnimationURL = resource.AnimationURL + case resourcedomain.ResultWalletCredit: + var snapshot struct { + WalletAssetType string `json:"wallet_asset_type"` + WalletAssetAmount int64 `json:"wallet_asset_amount"` + } + if err := json.Unmarshal([]byte(snapshotJSON), &snapshot); err != nil || snapshot.WalletAssetType == "" { + return nil, xerr.New(xerr.LedgerConflict, "vip reward wallet snapshot is invalid") + } + item.ResourceCode = snapshot.WalletAssetType + item.ResourceType = "wallet_asset" + item.Name = snapshot.WalletAssetType + if snapshot.WalletAssetAmount > 0 { + item.Quantity = snapshot.WalletAssetAmount + } + default: + return nil, xerr.New(xerr.LedgerConflict, "vip reward result type is invalid") + } items = append(items, item) } return items, rows.Err() 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 new file mode 100644 index 00000000..a2de54cd --- /dev/null +++ b/services/wallet-service/internal/storage/mysql/vip_trial_card_repository.go @@ -0,0 +1,444 @@ +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" + "strings" + "time" +) + +// GrantVipTrialCard 原子写入资源发放、背包 entitlement、体验卡元数据和 outbox。 +// 发卡时即开始绝对计时,但不会自动佩戴;切卡因此不会暂停、延长或销毁任何卡片。 +func (r *Repository) GrantVipTrialCard(ctx context.Context, command ledger.GrantVipTrialCardCommand) (ledger.GrantVipTrialCardReceipt, error) { + if r == nil || r.db == nil { + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + ctx = contextWithCommandApp(ctx, command.AppCode) + command.AppCode = appcode.FromContext(ctx) + requestHash := stableHash(fmt.Sprintf("vip_trial_card|%s|%d|%d|%d|%d|%s|%d|%s", + command.AppCode, + command.TargetUserID, + command.Level, + command.DurationMS, + command.ResourceID, + command.GrantSource, + command.OperatorUserID, + strings.TrimSpace(command.Reason), + )) + + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + defer func() { _ = tx.Rollback() }() + + nowMS := time.Now().UnixMilli() + if err := r.lockVipCommand(ctx, tx, command.CommandID, bizTypeVIPTrialCardGrant, requestHash, nowMS, xerr.IdempotencyConflict); err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + existing, existingHash, err := r.queryVipTrialCardByCommand(ctx, tx, command.CommandID, nowMS, false) + if err == nil { + if existingHash != requestHash { + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.IdempotencyConflict, "vip trial card command payload changed") + } + _ = tx.Rollback() + return r.vipTrialCardReceiptForCommand(ctx, command, requestHash, existing) + } + if !errors.Is(err, sql.ErrNoRows) { + return ledger.GrantVipTrialCardReceipt{}, err + } + + program, err := r.queryVipProgramConfig(ctx, tx.QueryRowContext(ctx, vipProgramSelectSQL()+` LOCK IN SHARE MODE`, command.AppCode)) + if errors.Is(err, sql.ErrNoRows) { + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.NotFound, "vip program config not found") + } + if err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + if program.Status != ledger.VipStatusActive || !program.TrialCardEnabled || program.GrantMode != ledger.VipGrantModeTrialCard { + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.Conflict, "vip trial card is disabled for this app") + } + if command.Level > program.LevelCount { + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.InvalidArgument, "vip trial card level exceeds program level_count") + } + level, err := r.getVipLevelForUpdate(ctx, tx, command.Level) + if err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + if level.Status != ledger.VipStatusActive { + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.VIPLevelDisabled, "vip level is disabled") + } + resourceID, err := r.resolveVipTrialCardResourceID(ctx, tx, command.Level, command.ResourceID) + if err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + resource, err := r.getResourceForUpdate(ctx, tx, resourceID) + if err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + if err := validateVipTrialCardResource(resource, command.Level); err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + if err := validateGrantableResourceForSource(resource, vipResourceGrantSource(command.GrantSource)); err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + + grantID := resourceGrantID(command.AppCode, command.CommandID) + if err := r.insertResourceGrant( + ctx, + tx, + grantID, + command.CommandID, + command.TargetUserID, + vipResourceGrantSource(command.GrantSource), + resourcedomain.GrantSubjectResource, + fmt.Sprintf("%d", resource.ResourceID), + requestHash, + "", + command.Reason, + command.OperatorUserID, + nowMS, + ); err != nil { + // 普通一致性读不会锁住“不存在的 command_id”。两个并发首发都可能通过前置查询, + // 但 resource_grants 唯一键会让后提交者等待首笔事务;确认 duplicate 后回滚本事务并 + // 读取已提交卡片,才能稳定返回幂等回执而不是泄漏 MySQL 1062。 + if isMySQLDuplicateError(err) { + _ = tx.Rollback() + return r.vipTrialCardReceiptForCommand(ctx, command, requestHash, ledger.VipTrialCard{}) + } + return ledger.GrantVipTrialCardReceipt{}, err + } + item, err := r.applyGrantItem(ctx, tx, grantID, command.CommandID, command.TargetUserID, resource, 1, command.DurationMS, nowMS) + if err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + if item.EntitlementID == "" { + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.LedgerConflict, "vip trial card did not create entitlement") + } + expiresAtMS := nowMS + command.DurationMS + trialCardID := "vip_card_" + stableHash(command.AppCode+"|"+command.CommandID) + if _, err := tx.ExecContext(ctx, ` + INSERT INTO user_vip_trial_cards ( + app_code, trial_card_id, command_id, request_hash, user_id, entitlement_id, + resource_id, level, name, status, duration_ms, effective_at_ms, expires_at_ms, + grant_source, source_grant_id, operator_user_id, reason, program_type, + config_version, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + command.AppCode, + trialCardID, + command.CommandID, + requestHash, + command.TargetUserID, + item.EntitlementID, + resource.ResourceID, + level.Level, + level.Name, + ledger.VipTrialCardStatusActive, + command.DurationMS, + nowMS, + expiresAtMS, + command.GrantSource, + grantID, + command.OperatorUserID, + command.Reason, + program.ProgramType, + program.ConfigVersion, + nowMS, + nowMS, + ); err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + card := ledger.VipTrialCard{ + TrialCardID: trialCardID, + EntitlementID: item.EntitlementID, + ResourceID: resource.ResourceID, + UserID: command.TargetUserID, + Level: level.Level, + Name: level.Name, + Status: ledger.VipTrialCardStatusActive, + DurationMS: command.DurationMS, + EffectiveAtMS: nowMS, + ExpiresAtMS: expiresAtMS, + RemainingDurationMS: command.DurationMS, + GrantSource: command.GrantSource, + SourceGrantID: grantID, + CreatedAtMS: nowMS, + UpdatedAtMS: nowMS, + } + if err := r.insertWalletOutbox(ctx, tx, []walletOutboxEvent{ + resourceOutboxEvent("ResourceGranted", command.CommandID, command.TargetUserID, resource.ResourceID, map[string]any{ + "grant_id": grantID, + "resource": resource, + }, nowMS), + resourceOutboxEvent("VipTrialCardGranted", command.CommandID, command.TargetUserID, resource.ResourceID, map[string]any{ + "trial_card": card, + "program_type": program.ProgramType, + "config_version": program.ConfigVersion, + }, nowMS), + }); err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + if err := tx.Commit(); err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + state, err := r.GetVipState(ctx, command.TargetUserID) + if err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + return ledger.GrantVipTrialCardReceipt{TrialCard: card, State: state, ServerTimeMS: nowMS}, nil +} + +func (r *Repository) vipTrialCardReceiptForCommand(ctx context.Context, command ledger.GrantVipTrialCardCommand, requestHash string, known ledger.VipTrialCard) (ledger.GrantVipTrialCardReceipt, error) { + nowMS := time.Now().UnixMilli() + card := known + storedHash := requestHash + if card.TrialCardID == "" { + tx, err := r.db.BeginTx(ctx, &sql.TxOptions{ReadOnly: true}) + if err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + defer func() { _ = tx.Rollback() }() + card, storedHash, err = r.queryVipTrialCardByCommand(ctx, tx, command.CommandID, nowMS, false) + if errors.Is(err, sql.ErrNoRows) { + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.IdempotencyConflict, "command_id is already used by another resource grant") + } + if err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + _ = tx.Rollback() + } + if storedHash != requestHash || card.UserID != command.TargetUserID { + return ledger.GrantVipTrialCardReceipt{}, xerr.New(xerr.IdempotencyConflict, "vip trial card command payload changed") + } + state, err := r.GetVipState(ctx, command.TargetUserID) + if err != nil { + return ledger.GrantVipTrialCardReceipt{}, err + } + return ledger.GrantVipTrialCardReceipt{TrialCard: card, State: state, ServerTimeMS: nowMS}, nil +} + +// EquipVipTrialCard 只更新 vip_trial_card 单选装备槽。目标 entitlement 必须属于当前用户且仍在绝对有效期内。 +func (r *Repository) EquipVipTrialCard(ctx context.Context, command ledger.EquipVipTrialCardCommand) (ledger.VipTrialCard, ledger.VipState, error) { + if r == nil || r.db == nil { + return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + ctx = contextWithCommandApp(ctx, command.AppCode) + command.AppCode = appcode.FromContext(ctx) + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return ledger.VipTrialCard{}, ledger.VipState{}, err + } + defer func() { _ = tx.Rollback() }() + nowMS := time.Now().UnixMilli() + program, err := r.queryVipProgramConfig(ctx, tx.QueryRowContext(ctx, vipProgramSelectSQL(), command.AppCode)) + 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") + } + // 锁序必须与 RevokeResourceGrant 保持 entitlement -> trial_card;反向先锁 card 会和后台撤销形成死锁。 + // entitlement 同时承担并发有效性门禁,避免撤销在校验后抢先提交又被重新写回 equipment。 + entitlement, err := r.getUserResourceEntitlementForUpdateTx(ctx, tx, command.EntitlementID) + if err != nil { + 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") + } + if err != nil { + return ledger.VipTrialCard{}, ledger.VipState{}, err + } + 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") + } + if resourcedomain.NormalizeResourceType(entitlement.Resource.ResourceType) != resourcedomain.TypeVIPTrialCard { + return ledger.VipTrialCard{}, ledger.VipState{}, xerr.New(xerr.Conflict, "vip trial card resource type mismatch") + } + + var currentEntitlementID string + err = tx.QueryRowContext(ctx, ` + SELECT entitlement_id FROM user_resource_equipment + WHERE app_code = ? AND user_id = ? AND resource_type = ? + LIMIT 1 FOR UPDATE`, command.AppCode, command.UserID, resourcedomain.TypeVIPTrialCard).Scan(¤tEntitlementID) + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return ledger.VipTrialCard{}, ledger.VipState{}, err + } + if currentEntitlementID != card.EntitlementID { + if err := r.equipUserResourceEntitlementTx(ctx, tx, command.UserID, entitlement, nowMS); err != nil { + return ledger.VipTrialCard{}, ledger.VipState{}, err + } + if err := r.insertWalletOutbox(ctx, tx, []walletOutboxEvent{ + resourceOutboxEvent("UserResourceChanged", command.RequestID, command.UserID, card.ResourceID, map[string]any{ + "action": "equip", + "resource_type": resourcedomain.TypeVIPTrialCard, + "entitlement_id": card.EntitlementID, + "updated_at_ms": nowMS, + }, nowMS), + resourceOutboxEvent("VipEffectiveChanged", command.RequestID, command.UserID, card.ResourceID, map[string]any{ + "source": ledger.VipEffectiveSourceTrial, + "level": card.Level, + "entitlement_id": card.EntitlementID, + "updated_at_ms": nowMS, + }, nowMS), + }); err != nil { + return ledger.VipTrialCard{}, ledger.VipState{}, err + } + } + if err := tx.Commit(); err != nil { + return ledger.VipTrialCard{}, ledger.VipState{}, err + } + card.Equipped = true + state, err := r.GetVipState(ctx, command.UserID) + return card, state, err +} + +// UnequipVipTrialCard 清理当前装备指针,不更新卡片或 entitlement,保证之后仍可在剩余绝对有效期内重新佩戴。 +func (r *Repository) UnequipVipTrialCard(ctx context.Context, command ledger.UnequipVipTrialCardCommand) (bool, ledger.VipState, error) { + if r == nil || r.db == nil { + return false, ledger.VipState{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + ctx = contextWithCommandApp(ctx, command.AppCode) + command.AppCode = appcode.FromContext(ctx) + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return false, ledger.VipState{}, err + } + defer func() { _ = tx.Rollback() }() + nowMS := time.Now().UnixMilli() + result, err := tx.ExecContext(ctx, ` + DELETE FROM user_resource_equipment + WHERE app_code = ? AND user_id = ? AND resource_type = ?`, + command.AppCode, command.UserID, resourcedomain.TypeVIPTrialCard, + ) + if err != nil { + return false, ledger.VipState{}, err + } + affected, err := result.RowsAffected() + if err != nil { + return false, ledger.VipState{}, err + } + if affected > 0 { + if err := r.insertWalletOutbox(ctx, tx, []walletOutboxEvent{ + resourceOutboxEvent("UserResourceChanged", command.RequestID, command.UserID, 0, map[string]any{ + "action": "unequip", + "resource_type": resourcedomain.TypeVIPTrialCard, + "updated_at_ms": nowMS, + }, nowMS), + resourceOutboxEvent("VipEffectiveChanged", command.RequestID, command.UserID, 0, map[string]any{ + "source": "paid_or_none", + "updated_at_ms": nowMS, + }, nowMS), + }); err != nil { + return false, ledger.VipState{}, err + } + } + if err := tx.Commit(); err != nil { + return false, ledger.VipState{}, err + } + state, err := r.GetVipState(ctx, command.UserID) + return affected > 0, state, err +} + +func (r *Repository) resolveVipTrialCardResourceID(ctx context.Context, tx *sql.Tx, level int32, requested int64) (int64, error) { + if requested > 0 { + return requested, nil + } + var resourceID int64 + err := tx.QueryRowContext(ctx, ` + SELECT resource_id FROM resources + WHERE app_code = ? AND resource_code = ? + LIMIT 1 FOR UPDATE`, + appcode.FromContext(ctx), fmt.Sprintf("vip_trial_card_%d", level), + ).Scan(&resourceID) + if errors.Is(err, sql.ErrNoRows) { + return 0, xerr.New(xerr.NotFound, "vip trial card resource not configured") + } + return resourceID, err +} + +func validateVipTrialCardResource(resource resourcedomain.Resource, expectedLevel int32) error { + if resourcedomain.NormalizeResourceType(resource.ResourceType) != resourcedomain.TypeVIPTrialCard { + return xerr.New(xerr.InvalidArgument, "resource is not a vip trial card") + } + var metadata struct { + VIPLevel int32 `json:"vip_level"` + } + if err := json.Unmarshal([]byte(resource.MetadataJSON), &metadata); err != nil || metadata.VIPLevel != expectedLevel { + return xerr.New(xerr.Conflict, "vip trial card resource level mismatch") + } + if resourcedomain.NormalizeGrantStrategy(resource.GrantStrategy) != resourcedomain.GrantStrategyNewEntitlement { + return xerr.New(xerr.Conflict, "vip trial card must use new_entitlement strategy") + } + return nil +} + +func vipResourceGrantSource(source string) string { + switch ledger.NormalizeVipGrantSource(source) { + case ledger.VipGrantSourceManagerCenter: + return resourcedomain.GrantSourceManagerCenter + case ledger.VipGrantSourceAdmin: + return resourcedomain.GrantSourceAdmin + default: + return strings.ToLower(strings.TrimSpace(source)) + } +} + +func (r *Repository) queryVipTrialCardByCommand(ctx context.Context, tx *sql.Tx, commandID string, nowMS int64, lock bool) (ledger.VipTrialCard, string, error) { + query := ` + SELECT trial_card_id, entitlement_id, resource_id, user_id, level, name, status, + duration_ms, effective_at_ms, expires_at_ms, grant_source, source_grant_id, + created_at_ms, updated_at_ms, request_hash + FROM user_vip_trial_cards + WHERE app_code = ? AND command_id = ?` + if lock { + query += ` FOR UPDATE` + } + var card ledger.VipTrialCard + var requestHash string + err := tx.QueryRowContext(ctx, query, appcode.FromContext(ctx), commandID).Scan( + &card.TrialCardID, + &card.EntitlementID, + &card.ResourceID, + &card.UserID, + &card.Level, + &card.Name, + &card.Status, + &card.DurationMS, + &card.EffectiveAtMS, + &card.ExpiresAtMS, + &card.GrantSource, + &card.SourceGrantID, + &card.CreatedAtMS, + &card.UpdatedAtMS, + &requestHash, + ) + if err == nil && card.ExpiresAtMS > nowMS { + card.RemainingDurationMS = card.ExpiresAtMS - nowMS + } + return card, requestHash, err +} + +func (r *Repository) queryVipTrialCardForUpdate(ctx context.Context, tx *sql.Tx, userID int64, entitlementID string, nowMS int64) (ledger.VipTrialCard, error) { + row := tx.QueryRowContext(ctx, ` + SELECT trial_card_id, entitlement_id, resource_id, user_id, level, name, status, + 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 > ? + FOR UPDATE`, + appcode.FromContext(ctx), userID, entitlementID, ledger.VipTrialCardStatusActive, nowMS, nowMS, + ) + return scanVipTrialCard(row, nowMS) +} diff --git a/services/wallet-service/internal/storage/mysql/vip_types.go b/services/wallet-service/internal/storage/mysql/vip_types.go index 3f8e5c68..b5686180 100644 --- a/services/wallet-service/internal/storage/mysql/vip_types.go +++ b/services/wallet-service/internal/storage/mysql/vip_types.go @@ -15,15 +15,19 @@ type vipActivationCommand struct { RecordID string Level ledger.VipLevel Current ledger.UserVip + Program ledger.VipProgramConfig + ExpiryPolicy string NowMS int64 } type vipActivationResult struct { - VIP ledger.UserVip - PreviousLevel int32 - Action string - ResourceGrantID string - RewardItems []ledger.VipRewardItem + VIP ledger.UserVip + PreviousLevel int32 + PreviousExpiresAtMS int64 + ExpiryPolicy string + Action string + ResourceGrantID string + RewardItems []ledger.VipRewardItem } type vipRewardGrantCommand struct { 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 new file mode 100644 index 00000000..0bcd846e --- /dev/null +++ b/services/wallet-service/internal/storage/mysql/vip_user_settings_repository.go @@ -0,0 +1,90 @@ +package mysql + +import ( + "context" + "database/sql" + "errors" + "time" + + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + "hyapp/services/wallet-service/internal/domain/ledger" +) + +// UpdateVipUserSettings 用一条 partial upsert 原子修改用户明确提交的开关。 +// INSERT 分支给未提交字段使用默认 true;UPDATE 分支则保留原值,避免两个并发 PATCH 互相覆盖。 +func (r *Repository) UpdateVipUserSettings(ctx context.Context, command ledger.UpdateVipUserSettingsCommand) (ledger.VipUserSettings, error) { + if r == nil || r.db == nil { + return ledger.VipUserSettings{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + ctx = contextWithCommandApp(ctx, command.AppCode) + command.AppCode = appcode.FromContext(ctx) + if command.UserID <= 0 || (command.RoomEntryNoticeEnabled == nil && command.OnlineGlobalNoticeEnabled == nil) { + return ledger.VipUserSettings{}, xerr.New(xerr.InvalidArgument, "vip user settings update is incomplete") + } + + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return ledger.VipUserSettings{}, err + } + defer func() { _ = tx.Rollback() }() + nowMS := time.Now().UTC().UnixMilli() + roomValue := true + roomProvided := command.RoomEntryNoticeEnabled != nil + if roomProvided { + roomValue = *command.RoomEntryNoticeEnabled + } + onlineValue := true + onlineProvided := command.OnlineGlobalNoticeEnabled != nil + if onlineProvided { + onlineValue = *command.OnlineGlobalNoticeEnabled + } + if _, err := tx.ExecContext(ctx, ` + INSERT INTO user_vip_settings ( + app_code, user_id, room_entry_notice_enabled, online_global_notice_enabled, + created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + room_entry_notice_enabled = IF(?, ?, room_entry_notice_enabled), + online_global_notice_enabled = IF(?, ?, online_global_notice_enabled), + updated_at_ms = ?`, + command.AppCode, command.UserID, roomValue, onlineValue, nowMS, nowMS, + roomProvided, roomValue, onlineProvided, onlineValue, nowMS, + ); err != nil { + return ledger.VipUserSettings{}, err + } + settings, err := r.queryVipUserSettings(ctx, tx, command.UserID, false) + if err != nil { + return ledger.VipUserSettings{}, err + } + if err := tx.Commit(); err != nil { + return ledger.VipUserSettings{}, err + } + return settings, nil +} + +// queryVipUserSettings 统一处理“无行即默认开启”。调用方可以传事务,从而让 VipState 的 +// program、会员、体验卡、benefits 和 settings 保持在同一 repeatable-read 快照。 +func (r *Repository) queryVipUserSettings(ctx context.Context, querier interface { + QueryRowContext(context.Context, string, ...any) *sql.Row +}, userID int64, lock bool) (ledger.VipUserSettings, error) { + query := ` + SELECT app_code, user_id, room_entry_notice_enabled, + online_global_notice_enabled, updated_at_ms + FROM user_vip_settings + WHERE app_code = ? AND user_id = ?` + if lock { + query += ` FOR UPDATE` + } + 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, + ); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return ledger.DefaultVipUserSettings(appcode.FromContext(ctx), userID), nil + } + return ledger.VipUserSettings{}, err + } + return settings, nil +} diff --git a/services/wallet-service/internal/testutil/mysqltest/mysqltest.go b/services/wallet-service/internal/testutil/mysqltest/mysqltest.go index ba782c0c..f9a5bc00 100644 --- a/services/wallet-service/internal/testutil/mysqltest/mysqltest.go +++ b/services/wallet-service/internal/testutil/mysqltest/mysqltest.go @@ -672,6 +672,155 @@ func (r *Repository) SetVIPLevelRechargeThreshold(level int32, totalCoinAmount i } } +// SetVIPLevelStatusForApp 只用于测试需要经过真实购买/体验卡入口的等级启停。 +func (r *Repository) SetVIPLevelStatusForApp(appCode string, level int32, status string, priceCoin int64) { + r.t.Helper() + if _, err := r.schema.DB.ExecContext(context.Background(), ` + UPDATE vip_levels + SET status = ?, price_coin = ?, updated_at_ms = ? + WHERE app_code = ? AND level = ?`, + status, priceCoin, time.Now().UTC().UnixMilli(), appCode, level, + ); err != nil { + r.t.Fatalf("set vip level status failed: %v", err) + } +} + +// SetVIPDailyCoinRebateAmount 写入测试专用等级金额并递增 program 版本,模拟后台完整配置发布。 +// amount<=0 时仍写入,供服务端校验/运行防线测试构造异常历史数据。 +func (r *Repository) SetVIPDailyCoinRebateAmount(appCode string, level int32, amount int64, status string) { + r.t.Helper() + nowMS := time.Now().UTC().UnixMilli() + _, err := r.schema.DB.ExecContext(context.Background(), ` + INSERT INTO vip_level_benefits ( + app_code, level, benefit_code, name, benefit_type, unlock_level, status, + trial_enabled, resource_id, resource_type, execution_scope, auto_equip, + sort_order, metadata_json, created_at_ms, updated_at_ms + ) VALUES (?, ?, 'daily_coin_rebate', '金币返现', 'function', ?, ?, FALSE, 0, '', 'wallet', FALSE, 250, + JSON_OBJECT('coin_amount', ?), ?, ?) + ON DUPLICATE KEY UPDATE + status = VALUES(status), trial_enabled = FALSE, execution_scope = 'wallet', + metadata_json = VALUES(metadata_json), updated_at_ms = VALUES(updated_at_ms)`, + appCode, level, level, status, amount, nowMS, nowMS, + ) + if err != nil { + r.t.Fatalf("set vip daily coin rebate amount failed: %v", err) + } + if _, err := r.schema.DB.ExecContext(context.Background(), ` + UPDATE vip_program_configs + SET config_version = config_version + 1, updated_at_ms = ? + WHERE app_code = ?`, nowMS, appCode); err != nil { + r.t.Fatalf("advance vip program version failed: %v", err) + } +} + +// SeedPaidVIPAtWindow 构造有完整 history 的付费 VIP,用于精确覆盖 UTC 日切边界。 +func (r *Repository) SeedPaidVIPAtWindow(appCode string, userID int64, level int32, startedAtMS int64, expiresAtMS int64) { + r.t.Helper() + var name string + var programType string + var configVersion int64 + if err := r.schema.DB.QueryRowContext(context.Background(), ` + SELECT l.name, p.program_type, p.config_version + FROM vip_levels l + JOIN vip_program_configs p ON p.app_code = l.app_code + WHERE l.app_code = ? AND l.level = ?`, appCode, level, + ).Scan(&name, &programType, &configVersion); err != nil { + r.t.Fatalf("read vip seed level failed: %v", err) + } + _, err := r.schema.DB.ExecContext(context.Background(), ` + INSERT INTO user_vip_memberships ( + app_code, user_id, level, name, status, program_type, config_version, + started_at_ms, expires_at_ms, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, 'active', ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + level = VALUES(level), name = VALUES(name), status = 'active', + program_type = VALUES(program_type), config_version = VALUES(config_version), + started_at_ms = VALUES(started_at_ms), expires_at_ms = VALUES(expires_at_ms), + updated_at_ms = VALUES(updated_at_ms)`, + appCode, userID, level, name, programType, configVersion, + startedAtMS, expiresAtMS, startedAtMS, startedAtMS, + ) + if err != nil { + r.t.Fatalf("seed paid vip membership failed: %v", err) + } + if _, err := r.schema.DB.ExecContext(context.Background(), ` + INSERT INTO user_vip_history ( + app_code, user_id, action, previous_level, new_level, previous_expires_at_ms, + new_expires_at_ms, program_type, config_version, order_id, created_at_ms + ) VALUES (?, ?, 'test_seed', 0, ?, 0, ?, ?, ?, '', ?)`, + appCode, userID, level, expiresAtMS, programType, configVersion, startedAtMS, + ); err != nil { + r.t.Fatalf("seed paid vip history failed: %v", err) + } +} + +// SeedLegacyPaidVIPAtWindow 模拟 060 新增有效期列后的存量历史:会员主表仍有完整窗口, +// 但旧 history 因 ALTER DEFAULT 只有 0。运行时不得把这个 0 当作“日切时已过期”。 +func (r *Repository) SeedLegacyPaidVIPAtWindow(appCode string, userID int64, level int32, startedAtMS int64, expiresAtMS int64) { + r.t.Helper() + r.SeedPaidVIPAtWindow(appCode, userID, level, startedAtMS, expiresAtMS) + if _, err := r.schema.DB.ExecContext(context.Background(), ` + UPDATE user_vip_history + SET action = 'legacy_test_seed', previous_expires_at_ms = 0, new_expires_at_ms = 0 + WHERE app_code = ? AND user_id = ? AND action = 'test_seed' AND created_at_ms = ?`, + appCode, userID, startedAtMS, + ); err != nil { + r.t.Fatalf("convert paid vip history to legacy zero-expiry snapshot failed: %v", err) + } +} + +// ApplyVIPHistoryMigrationBaseline 在隔离真实 MySQL schema 中复制 060 的基线 INSERT。 +// baselineAtMS 可固定在待测日切前,用于验证后续日切能读取该完整快照;重复调用不应增行。 +func (r *Repository) ApplyVIPHistoryMigrationBaseline(baselineAtMS int64) { + r.t.Helper() + if _, err := r.schema.DB.ExecContext(context.Background(), ` + INSERT INTO user_vip_history ( + app_code, user_id, action, previous_level, new_level, previous_expires_at_ms, + new_expires_at_ms, program_type, config_version, order_id, created_at_ms + ) + SELECT + memberships.app_code, memberships.user_id, 'migration_baseline', 0, + memberships.level, 0, memberships.expires_at_ms, memberships.program_type, + memberships.config_version, 'vip_configurable_060_baseline', ? + FROM user_vip_memberships AS memberships + WHERE memberships.level > 0 + AND memberships.expires_at_ms > 0 + AND NOT EXISTS ( + SELECT 1 + FROM user_vip_history AS complete_history + WHERE complete_history.app_code = memberships.app_code + AND complete_history.user_id = memberships.user_id + AND complete_history.new_level > 0 + AND complete_history.new_expires_at_ms > 0 + ) + AND NOT EXISTS ( + SELECT 1 + FROM user_vip_history AS existing_baseline + WHERE existing_baseline.app_code = memberships.app_code + AND existing_baseline.user_id = memberships.user_id + AND existing_baseline.order_id = 'vip_configurable_060_baseline' + )`, baselineAtMS, + ); err != nil { + r.t.Fatalf("apply vip history migration baseline failed: %v", err) + } +} + +// WalletOutboxPayload returns the latest payload for a precise event assertion. +func (r *Repository) WalletOutboxPayload(appCode string, eventType string, userID int64) string { + r.t.Helper() + var payload string + if err := r.schema.DB.QueryRowContext(context.Background(), ` + SELECT CAST(payload AS CHAR) + FROM wallet_outbox + WHERE app_code = ? AND event_type = ? AND user_id = ? + ORDER BY created_at_ms DESC, event_id DESC LIMIT 1`, + appCode, eventType, userID, + ).Scan(&payload); err != nil { + r.t.Fatalf("read wallet outbox payload failed: %v", err) + } + return payload +} + // SetHostSalaryPolicy seeds the wallet runtime policy snapshot used by salary settlement tests. func (r *Repository) SetHostSalaryPolicy(policy ledger.HostSalaryPolicy) { r.t.Helper() @@ -752,7 +901,7 @@ func validateTableName(table string) string { "host_period_diamond_accounts", "host_period_diamond_entries", "host_agency_salary_policies", "host_agency_salary_policy_levels", "host_salary_settlement_progress", "host_salary_settlement_records", "coin_seller_stock_records", "gift_diamond_ratio_configs", "wallet_diamond_exchange_rules", - "vip_levels", "user_vip_memberships", "vip_purchase_orders", "user_vip_history", + "vip_program_configs", "vip_levels", "vip_level_benefits", "user_vip_memberships", "user_vip_settings", "vip_purchase_orders", "user_vip_history", "user_vip_trial_cards", "vip_command_locks", "vip_daily_coin_rebate_runs", "vip_daily_coin_rebates", "resources", "resource_groups", "resource_group_items", "resource_shop_items", "resource_shop_purchase_orders", "gift_type_configs", "gift_configs", "gift_config_regions", "user_gift_wall", "wallet_projection_events", "resource_grants", "resource_grant_items", "user_resource_entitlements", "user_resource_equipment": return table diff --git a/services/wallet-service/internal/transport/grpc/cron_server.go b/services/wallet-service/internal/transport/grpc/cron_server.go index c9bacc4b..13682ad1 100644 --- a/services/wallet-service/internal/transport/grpc/cron_server.go +++ b/services/wallet-service/internal/transport/grpc/cron_server.go @@ -2,6 +2,7 @@ package grpc import ( "context" + "time" walletv1 "hyapp.local/api/proto/wallet/v1" "hyapp/pkg/appcode" @@ -34,6 +35,27 @@ func (s *CronServer) ProcessHostSalaryMonthEndBatch(ctx context.Context, req *wa return s.processHostSalarySettlementBatch(ctx, req, ledger.HostSalarySettlementTypeMonthEnd) } +// ProcessVipDailyCoinRebateBatch 只把 UTC task_day 和页大小交给 wallet owner;金额快照、 +// 会员日切资格、游标和 available outbox 都在 wallet 的同一事务边界内完成。 +func (s *CronServer) ProcessVipDailyCoinRebateBatch(ctx context.Context, req *walletv1.ProcessVipDailyCoinRebateBatchRequest) (*walletv1.ProcessVipDailyCoinRebateBatchResponse, error) { + if s.svc == nil { + return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "wallet service is not configured")) + } + appCode := appcode.Normalize(req.GetAppCode()) + ctx = appcode.WithContext(ctx, appCode) + result, err := s.svc.ProcessVipDailyCoinRebateBatch(ctx, ledger.ProcessVipDailyCoinRebateBatchCommand{ + AppCode: appCode, TaskDay: req.GetTaskDay(), BatchSize: int(req.GetBatchSize()), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &walletv1.ProcessVipDailyCoinRebateBatchResponse{ + Run: vipDailyCoinRebateRunToProto(result.Run), ScannedCount: int32(result.ScannedCount), + CreatedCount: int32(result.CreatedCount), HasMore: result.HasMore, + ServerTimeMs: time.Now().UTC().UnixMilli(), + }, nil +} + func (s *CronServer) processHostSalarySettlementBatch(ctx context.Context, req *walletv1.CronBatchRequest, settlementType string) (*walletv1.CronBatchResponse, error) { if s.svc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "wallet service is not configured")) diff --git a/services/wallet-service/internal/transport/grpc/recharge.go b/services/wallet-service/internal/transport/grpc/recharge.go index 803a8fca..110b4f9d 100644 --- a/services/wallet-service/internal/transport/grpc/recharge.go +++ b/services/wallet-service/internal/transport/grpc/recharge.go @@ -62,6 +62,27 @@ func (s *Server) GetRechargeBillSummary(ctx context.Context, req *walletv1.GetRe }, nil } +// BatchGetUserRechargeStats 只读取用户累计聚合表,避免后台详情按用户回扫充值账单。 +func (s *Server) BatchGetUserRechargeStats(ctx context.Context, req *walletv1.BatchGetUserRechargeStatsRequest) (*walletv1.BatchGetUserRechargeStatsResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + items, err := s.svc.BatchGetUserRechargeStats(ctx, req.GetAppCode(), req.GetUserIds()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + resp := &walletv1.BatchGetUserRechargeStatsResponse{Items: make([]*walletv1.UserRechargeStats, 0, len(items))} + for _, item := range items { + resp.Items = append(resp.Items, &walletv1.UserRechargeStats{ + UserId: item.UserID, + RechargeCount: item.RechargeCount, + TotalCoinAmount: item.TotalCoinAmount, + TotalUsdMinorAmount: item.TotalUSDMinorAmount, + FirstRechargedAtMs: item.FirstRechargedAtMS, + UpdatedAtMs: item.UpdatedAtMS, + }) + } + return resp, nil +} + // GetRechargeBillOverview 暴露财务概览聚合:按日趋势、区域分布与谷歌实付覆盖度。 func (s *Server) GetRechargeBillOverview(ctx context.Context, req *walletv1.GetRechargeBillOverviewRequest) (*walletv1.GetRechargeBillOverviewResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) diff --git a/services/wallet-service/internal/transport/grpc/resource.go b/services/wallet-service/internal/transport/grpc/resource.go index 3632a885..361c3e1c 100644 --- a/services/wallet-service/internal/transport/grpc/resource.go +++ b/services/wallet-service/internal/transport/grpc/resource.go @@ -340,6 +340,7 @@ func (s *Server) ListUserResources(ctx context.Context, req *walletv1.ListUserRe func (s *Server) EquipUserResource(ctx context.Context, req *walletv1.EquipUserResourceRequest) (*walletv1.EquipUserResourceResponse, error) { item, err := s.svc.EquipUserResource(ctx, resourcedomain.EquipUserResourceCommand{ + RequestID: req.GetRequestId(), AppCode: req.GetAppCode(), UserID: req.GetUserId(), ResourceID: req.GetResourceId(), @@ -353,6 +354,7 @@ func (s *Server) EquipUserResource(ctx context.Context, req *walletv1.EquipUserR func (s *Server) UnequipUserResource(ctx context.Context, req *walletv1.UnequipUserResourceRequest) (*walletv1.UnequipUserResourceResponse, error) { result, err := s.svc.UnequipUserResource(ctx, resourcedomain.UnequipUserResourceCommand{ + RequestID: req.GetRequestId(), AppCode: req.GetAppCode(), UserID: req.GetUserId(), ResourceType: req.GetResourceType(), diff --git a/services/wallet-service/internal/transport/grpc/vip.go b/services/wallet-service/internal/transport/grpc/vip.go index 8b2d885e..5d8a2782 100644 --- a/services/wallet-service/internal/transport/grpc/vip.go +++ b/services/wallet-service/internal/transport/grpc/vip.go @@ -13,11 +13,16 @@ import ( // ListVipPackages 返回当前 VIP 和可购买包列表。 func (s *Server) ListVipPackages(ctx context.Context, req *walletv1.ListVipPackagesRequest) (*walletv1.ListVipPackagesResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) - current, levels, err := s.svc.ListVipPackages(ctx, req.GetUserId()) + state, levels, err := s.svc.ListVipPackages(ctx, req.GetUserId()) if err != nil { return nil, xerr.ToGRPCError(err) } - resp := &walletv1.ListVipPackagesResponse{CurrentVip: vipToProto(current), Packages: make([]*walletv1.VipLevel, 0, len(levels))} + resp := &walletv1.ListVipPackagesResponse{ + CurrentVip: vipToProto(state.EffectiveVip), + Packages: make([]*walletv1.VipLevel, 0, len(levels)), + State: vipStateToProto(state), + ProgramConfig: vipProgramConfigToProto(state.ProgramConfig), + } for _, level := range levels { resp.Packages = append(resp.Packages, vipLevelToProto(level)) } @@ -27,11 +32,42 @@ func (s *Server) ListVipPackages(ctx context.Context, req *walletv1.ListVipPacka // GetMyVip 返回当前登录用户 VIP 状态。 func (s *Server) GetMyVip(ctx context.Context, req *walletv1.GetMyVipRequest) (*walletv1.GetMyVipResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) - vip, err := s.svc.GetMyVip(ctx, req.GetUserId()) + state, err := s.svc.GetVipState(ctx, req.GetUserId()) if err != nil { return nil, xerr.ToGRPCError(err) } - return &walletv1.GetMyVipResponse{Vip: vipToProto(vip)}, nil + // 旧 vip 字段保留为最终生效投影,付费会员原始事实由 state.paid_vip 明确返回。 + return &walletv1.GetMyVipResponse{Vip: vipToProto(state.EffectiveVip), State: vipStateToProto(state)}, nil +} + +// GetVipProgramConfig 返回按 App 隔离的状态机配置和最高等级权益目录。 +func (s *Server) GetVipProgramConfig(ctx context.Context, req *walletv1.GetVipProgramConfigRequest) (*walletv1.GetVipProgramConfigResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + config, benefits, err := s.svc.GetVipProgramConfig(ctx) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &walletv1.GetVipProgramConfigResponse{ + Config: vipProgramConfigToProto(config), + Benefits: vipBenefitsToProto(benefits), + ServerTimeMs: time.Now().UnixMilli(), + }, nil +} + +// CheckVipBenefit 供权益 owner 精确判断单项能力,不允许调用方退化成等级比较。 +func (s *Server) CheckVipBenefit(ctx context.Context, req *walletv1.CheckVipBenefitRequest) (*walletv1.CheckVipBenefitResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + result, err := s.svc.CheckVipBenefit(ctx, req.GetUserId(), req.GetBenefitCode()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &walletv1.CheckVipBenefitResponse{ + Allowed: result.Allowed, + Benefit: vipBenefitToProto(result.Benefit), + State: vipStateToProto(result.State), + DenialReason: result.DenialReason, + EvaluatedAtMs: result.EvaluatedAtMS, + }, nil } // PurchaseVip 购买、续期或升级 VIP。 @@ -53,6 +89,7 @@ func (s *Server) PurchaseVip(ctx context.Context, req *walletv1.PurchaseVipReque CoinSpent: receipt.CoinSpent, CoinBalanceAfter: receipt.CoinBalanceAfter, RewardItems: vipRewardItemsToProto(receipt.RewardItems), + State: vipStateToProto(receipt.State), }, nil } @@ -76,17 +113,83 @@ func (s *Server) GrantVip(ctx context.Context, req *walletv1.GrantVipRequest) (* Vip: vipToProto(receipt.Vip), RewardItems: vipRewardItemsToProto(receipt.RewardItems), ServerTimeMs: time.Now().UnixMilli(), + State: vipStateToProto(receipt.State), + }, nil +} + +// GrantVipTrialCard 发卡但不自动佩戴,resource_id 省略时由钱包按 level 解析同 App 预置资源。 +func (s *Server) GrantVipTrialCard(ctx context.Context, req *walletv1.GrantVipTrialCardRequest) (*walletv1.GrantVipTrialCardResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + resourceID := int64(0) + if req.ResourceId != nil { + resourceID = req.GetResourceId() + } + receipt, err := s.svc.GrantVipTrialCard(ctx, ledger.GrantVipTrialCardCommand{ + AppCode: req.GetAppCode(), + CommandID: req.GetCommandId(), + TargetUserID: req.GetTargetUserId(), + Level: req.GetLevel(), + DurationMS: req.GetDurationMs(), + ResourceID: resourceID, + GrantSource: req.GetGrantSource(), + OperatorUserID: req.GetOperatorUserId(), + Reason: req.GetReason(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &walletv1.GrantVipTrialCardResponse{ + TrialCard: vipTrialCardToProto(receipt.TrialCard), + State: vipStateToProto(receipt.State), + ServerTimeMs: receipt.ServerTimeMS, + }, nil +} + +// EquipVipTrialCard 精确佩戴一个 entitlement;同类型旧装备仅解除指针,库存与到期时间保持不变。 +func (s *Server) EquipVipTrialCard(ctx context.Context, req *walletv1.EquipVipTrialCardRequest) (*walletv1.EquipVipTrialCardResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + card, state, err := s.svc.EquipVipTrialCard(ctx, ledger.EquipVipTrialCardCommand{ + AppCode: req.GetAppCode(), + RequestID: req.GetRequestId(), + UserID: req.GetUserId(), + EntitlementID: req.GetEntitlementId(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &walletv1.EquipVipTrialCardResponse{ + TrialCard: vipTrialCardToProto(card), + State: vipStateToProto(state), + ServerTimeMs: time.Now().UnixMilli(), + }, nil +} + +// UnequipVipTrialCard 卸下当前体验卡并返回回落后的最终 VIP 状态。 +func (s *Server) UnequipVipTrialCard(ctx context.Context, req *walletv1.UnequipVipTrialCardRequest) (*walletv1.UnequipVipTrialCardResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + unequipped, state, err := s.svc.UnequipVipTrialCard(ctx, ledger.UnequipVipTrialCardCommand{ + AppCode: req.GetAppCode(), + RequestID: req.GetRequestId(), + UserID: req.GetUserId(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &walletv1.UnequipVipTrialCardResponse{ + Unequipped: unequipped, + State: vipStateToProto(state), + ServerTimeMs: time.Now().UnixMilli(), }, nil } // ListAdminVipLevels 返回后台 VIP 配置。 func (s *Server) ListAdminVipLevels(ctx context.Context, req *walletv1.ListAdminVipLevelsRequest) (*walletv1.ListAdminVipLevelsResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) - levels, err := s.svc.ListAdminVipLevels(ctx) + config, levels, err := s.svc.ListAdminVipLevels(ctx) if err != nil { return nil, xerr.ToGRPCError(err) } - resp := &walletv1.ListAdminVipLevelsResponse{Levels: make([]*walletv1.VipLevel, 0, len(levels)), ServerTimeMs: time.Now().UnixMilli()} + resp := &walletv1.ListAdminVipLevelsResponse{Levels: make([]*walletv1.VipLevel, 0, len(levels)), ServerTimeMs: time.Now().UnixMilli(), ProgramConfig: vipProgramConfigToProto(config)} for _, level := range levels { resp.Levels = append(resp.Levels, vipLevelToProto(level)) } @@ -110,28 +213,151 @@ func (s *Server) UpdateAdminVipLevels(ctx context.Context, req *walletv1.UpdateA RewardResourceGroupID: item.GetRewardResourceGroupId(), RequiredRechargeCoinAmount: item.GetRequiredRechargeCoinAmount(), SortOrder: item.GetSortOrder(), + Benefits: vipBenefitsFromProto(item.GetBenefits()), }) } - levels, err := s.svc.UpdateAdminVipLevels(ctx, commands, req.GetOperatorUserId()) + config, levels, err := s.svc.UpdateAdminVipLevels(ctx, commands, req.GetOperatorUserId()) if err != nil { return nil, xerr.ToGRPCError(err) } - resp := &walletv1.UpdateAdminVipLevelsResponse{Levels: make([]*walletv1.VipLevel, 0, len(levels)), ServerTimeMs: time.Now().UnixMilli()} + resp := &walletv1.UpdateAdminVipLevelsResponse{Levels: make([]*walletv1.VipLevel, 0, len(levels)), ServerTimeMs: time.Now().UnixMilli(), ProgramConfig: vipProgramConfigToProto(config)} for _, level := range levels { resp.Levels = append(resp.Levels, vipLevelToProto(level)) } return resp, nil } +// UpdateAdminVipProgramConfig 保存 App 级策略,审计操作者只接受请求外层的服务端身份字段。 +func (s *Server) UpdateAdminVipProgramConfig(ctx context.Context, req *walletv1.UpdateAdminVipProgramConfigRequest) (*walletv1.UpdateAdminVipProgramConfigResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + config := vipProgramConfigFromProto(req.GetConfig()) + config.AppCode = req.GetAppCode() + updated, err := s.svc.UpdateAdminVipProgramConfig(ctx, ledger.AdminVipProgramConfigCommand{ + Config: config, + OperatorUserID: req.GetOperatorUserId(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &walletv1.UpdateAdminVipProgramConfigResponse{Config: vipProgramConfigToProto(updated), ServerTimeMs: time.Now().UnixMilli()}, nil +} + +// UpdateMyVipSettings 保留 proto optional 的 partial update 语义;未提交字段不能被零值 false 覆盖。 +func (s *Server) UpdateMyVipSettings(ctx context.Context, req *walletv1.UpdateMyVipSettingsRequest) (*walletv1.UpdateMyVipSettingsResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + var roomEntryNoticeEnabled *bool + if req.RoomEntryNoticeEnabled != nil { + value := req.GetRoomEntryNoticeEnabled() + roomEntryNoticeEnabled = &value + } + var onlineGlobalNoticeEnabled *bool + if req.OnlineGlobalNoticeEnabled != nil { + value := req.GetOnlineGlobalNoticeEnabled() + onlineGlobalNoticeEnabled = &value + } + settings, err := s.svc.UpdateVipUserSettings(ctx, ledger.UpdateVipUserSettingsCommand{ + AppCode: req.GetAppCode(), UserID: req.GetUserId(), + RoomEntryNoticeEnabled: roomEntryNoticeEnabled, OnlineGlobalNoticeEnabled: onlineGlobalNoticeEnabled, + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &walletv1.UpdateMyVipSettingsResponse{ + Settings: vipUserSettingsToProto(settings), ServerTimeMs: time.Now().UTC().UnixMilli(), + }, nil +} + +// GetMyCurrentVipDailyCoinRebate 返回当前 UTC 日可领取/已领取事实;未生成以 found=false 表达。 +func (s *Server) GetMyCurrentVipDailyCoinRebate(ctx context.Context, req *walletv1.GetMyCurrentVipDailyCoinRebateRequest) (*walletv1.GetMyCurrentVipDailyCoinRebateResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + rebate, found, err := s.svc.GetMyCurrentVipDailyCoinRebate(ctx, req.GetUserId()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + response := &walletv1.GetMyCurrentVipDailyCoinRebateResponse{Found: found, ServerTimeMs: time.Now().UTC().UnixMilli()} + if found { + response.Rebate = vipDailyCoinRebateToProto(rebate) + } + return response, nil +} + +// ListMyVipDailyCoinRebateStatuses 同时支持历史分页和通知按 rebate_ids 精确恢复;repository 始终附加 user_id 条件。 +func (s *Server) ListMyVipDailyCoinRebateStatuses(ctx context.Context, req *walletv1.ListMyVipDailyCoinRebateStatusesRequest) (*walletv1.ListMyVipDailyCoinRebateStatusesResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + items, total, err := s.svc.ListMyVipDailyCoinRebateStatuses(ctx, ledger.ListVipDailyCoinRebateStatusesQuery{ + AppCode: req.GetAppCode(), UserID: req.GetUserId(), Page: int(req.GetPage()), + PageSize: int(req.GetPageSize()), RebateIDs: append([]string(nil), req.GetRebateIds()...), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + response := &walletv1.ListMyVipDailyCoinRebateStatusesResponse{ + Rebates: make([]*walletv1.VipDailyCoinRebate, 0, len(items)), Total: total, + ServerTimeMs: time.Now().UTC().UnixMilli(), + } + for _, item := range items { + response.Rebates = append(response.Rebates, vipDailyCoinRebateToProto(item)) + } + return response, nil +} + +// ClaimVipDailyCoinRebate 不接收金额;wallet owner 从锁内返现行读取并返回稳定账后余额。 +func (s *Server) ClaimVipDailyCoinRebate(ctx context.Context, req *walletv1.ClaimVipDailyCoinRebateRequest) (*walletv1.ClaimVipDailyCoinRebateResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + receipt, err := s.svc.ClaimVipDailyCoinRebate(ctx, ledger.ClaimVipDailyCoinRebateCommand{ + AppCode: req.GetAppCode(), CommandID: req.GetCommandId(), UserID: req.GetUserId(), RebateID: req.GetRebateId(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &walletv1.ClaimVipDailyCoinRebateResponse{ + Rebate: vipDailyCoinRebateToProto(receipt.Rebate), TransactionId: receipt.TransactionID, + CoinBalance: balanceToProto(receipt.CoinBalance), ServerTimeMs: time.Now().UTC().UnixMilli(), + }, nil +} + func vipToProto(vip ledger.UserVip) *walletv1.UserVip { return &walletv1.UserVip{ - UserId: vip.UserID, - Level: vip.Level, - Name: vip.Name, - Active: vip.Active, - StartedAtMs: vip.StartedAtMS, - ExpiresAtMs: vip.ExpiresAtMS, - UpdatedAtMs: vip.UpdatedAtMS, + UserId: vip.UserID, + Level: vip.Level, + Name: vip.Name, + Active: vip.Active, + StartedAtMs: vip.StartedAtMS, + ExpiresAtMs: vip.ExpiresAtMS, + UpdatedAtMs: vip.UpdatedAtMS, + ProgramType: vip.ProgramType, + ConfigVersion: vip.ConfigVersion, + } +} + +func vipDailyCoinRebateRunToProto(run ledger.VipDailyCoinRebateRun) *walletv1.VipDailyCoinRebateRun { + return &walletv1.VipDailyCoinRebateRun{ + RunId: run.RunID, TaskDay: run.TaskDay, DayStartMs: run.DayStartMS, DayEndMs: run.DayEndMS, + ConfigVersion: run.ConfigVersion, LevelAmountsJson: run.LevelAmountsJSON, Status: run.Status, + LastUserId: run.LastUserID, ScannedCount: run.ScannedCount, CreatedCount: run.CreatedCount, + CreatedAtMs: run.CreatedAtMS, UpdatedAtMs: run.UpdatedAtMS, CompletedAtMs: run.CompletedAtMS, + } +} + +func vipDailyCoinRebateToProto(rebate ledger.VipDailyCoinRebate) *walletv1.VipDailyCoinRebate { + if rebate.RebateID == "" { + return nil + } + return &walletv1.VipDailyCoinRebate{ + RebateId: rebate.RebateID, UserId: rebate.UserID, TaskDay: rebate.TaskDay, + VipLevel: rebate.VipLevel, VipName: rebate.VipName, CoinAmount: rebate.CoinAmount, + Status: rebate.Status, AvailableAtMs: rebate.AvailableAtMS, ExpiresAtMs: rebate.ExpiresAtMS, + ConfigVersion: rebate.ConfigVersion, ClaimedAtMs: rebate.ClaimedAtMS, + WalletTransactionId: rebate.WalletTransactionID, CreatedAtMs: rebate.CreatedAtMS, UpdatedAtMs: rebate.UpdatedAtMS, + } +} + +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, } } @@ -152,6 +378,143 @@ func vipLevelToProto(level ledger.VipLevel) *walletv1.VipLevel { PurchaseLockedReason: level.PurchaseLockedReason, CreatedAtMs: level.CreatedAtMS, UpdatedAtMs: level.UpdatedAtMS, + Benefits: vipBenefitsToProto(level.Benefits), + ConfigVersion: level.ConfigVersion, + } +} + +func vipProgramConfigToProto(config ledger.VipProgramConfig) *walletv1.VipProgramConfig { + return &walletv1.VipProgramConfig{ + AppCode: config.AppCode, + ProgramType: config.ProgramType, + LevelCount: config.LevelCount, + SameLevelExpiryPolicy: config.SameLevelExpiryPolicy, + UpgradeExpiryPolicy: config.UpgradeExpiryPolicy, + DowngradePurchasePolicy: config.DowngradePurchasePolicy, + BenefitInheritancePolicy: config.BenefitInheritancePolicy, + GrantMode: config.GrantMode, + TrialCardEnabled: config.TrialCardEnabled, + Status: config.Status, + ConfigVersion: config.ConfigVersion, + UpdatedByAdminId: config.UpdatedByAdminID, + CreatedAtMs: config.CreatedAtMS, + UpdatedAtMs: config.UpdatedAtMS, + } +} + +func vipProgramConfigFromProto(config *walletv1.VipProgramConfig) ledger.VipProgramConfig { + if config == nil { + return ledger.VipProgramConfig{} + } + return ledger.VipProgramConfig{ + AppCode: config.GetAppCode(), + ProgramType: config.GetProgramType(), + LevelCount: config.GetLevelCount(), + SameLevelExpiryPolicy: config.GetSameLevelExpiryPolicy(), + UpgradeExpiryPolicy: config.GetUpgradeExpiryPolicy(), + DowngradePurchasePolicy: config.GetDowngradePurchasePolicy(), + BenefitInheritancePolicy: config.GetBenefitInheritancePolicy(), + GrantMode: config.GetGrantMode(), + TrialCardEnabled: config.GetTrialCardEnabled(), + Status: config.GetStatus(), + } +} + +func vipBenefitToProto(benefit ledger.VipBenefit) *walletv1.VipBenefit { + if benefit.BenefitCode == "" { + return nil + } + return &walletv1.VipBenefit{ + BenefitCode: benefit.BenefitCode, + Name: benefit.Name, + BenefitType: benefit.BenefitType, + UnlockLevel: benefit.UnlockLevel, + Status: benefit.Status, + TrialEnabled: benefit.TrialEnabled, + ResourceId: benefit.ResourceID, + ResourceType: benefit.ResourceType, + ExecutionScope: benefit.ExecutionScope, + AutoEquip: benefit.AutoEquip, + SortOrder: benefit.SortOrder, + MetadataJson: benefit.MetadataJSON, + CreatedAtMs: benefit.CreatedAtMS, + UpdatedAtMs: benefit.UpdatedAtMS, + } +} + +func vipBenefitsToProto(benefits []ledger.VipBenefit) []*walletv1.VipBenefit { + items := make([]*walletv1.VipBenefit, 0, len(benefits)) + for _, benefit := range benefits { + if item := vipBenefitToProto(benefit); item != nil { + items = append(items, item) + } + } + return items +} + +func vipBenefitsFromProto(benefits []*walletv1.VipBenefit) []ledger.VipBenefit { + items := make([]ledger.VipBenefit, 0, len(benefits)) + for _, benefit := range benefits { + if benefit == nil { + continue + } + items = append(items, ledger.VipBenefit{ + BenefitCode: benefit.GetBenefitCode(), + Name: benefit.GetName(), + BenefitType: benefit.GetBenefitType(), + UnlockLevel: benefit.GetUnlockLevel(), + Status: benefit.GetStatus(), + TrialEnabled: benefit.GetTrialEnabled(), + ResourceID: benefit.GetResourceId(), + ResourceType: benefit.GetResourceType(), + ExecutionScope: benefit.GetExecutionScope(), + AutoEquip: benefit.GetAutoEquip(), + SortOrder: benefit.GetSortOrder(), + MetadataJSON: benefit.GetMetadataJson(), + }) + } + return items +} + +func vipTrialCardToProto(card ledger.VipTrialCard) *walletv1.VipTrialCard { + if card.TrialCardID == "" { + return nil + } + return &walletv1.VipTrialCard{ + TrialCardId: card.TrialCardID, + EntitlementId: card.EntitlementID, + ResourceId: card.ResourceID, + UserId: card.UserID, + Level: card.Level, + Name: card.Name, + Status: card.Status, + Equipped: card.Equipped, + DurationMs: card.DurationMS, + EffectiveAtMs: card.EffectiveAtMS, + ExpiresAtMs: card.ExpiresAtMS, + RemainingDurationMs: card.RemainingDurationMS, + GrantSource: card.GrantSource, + SourceGrantId: card.SourceGrantID, + CreatedAtMs: card.CreatedAtMS, + UpdatedAtMs: card.UpdatedAtMS, + } +} + +func vipStateToProto(state ledger.VipState) *walletv1.VipState { + return &walletv1.VipState{ + PaidVip: vipToProto(state.PaidVip), + EquippedTrialCard: func() *walletv1.VipTrialCard { + if state.EquippedTrialCard == nil { + return nil + } + return vipTrialCardToProto(*state.EquippedTrialCard) + }(), + EffectiveVip: vipToProto(state.EffectiveVip), + EffectiveSource: state.EffectiveSource, + EffectiveBenefits: vipBenefitsToProto(state.EffectiveBenefits), + EvaluatedAtMs: state.EvaluatedAtMS, + ProgramConfig: vipProgramConfigToProto(state.ProgramConfig), + UserSettings: vipUserSettingsToProto(state.UserSettings), } }