机器人
This commit is contained in:
parent
da64d5f189
commit
0d111d9a88
@ -193,6 +193,7 @@ docs/flutter对接/Flutter App 通知与钱包余额对接.md
|
||||
| `hyapp_room_outbox` | `hyapp-room-outbox-producer` | `hyapp-activity-room-outbox` | activity-service 消费 `RoomGiftSent`、`RoomRocketIgnited` 等房间事实 |
|
||||
| `hyapp_room_outbox` | `hyapp-room-outbox-producer` | `hyapp-notice-room-outbox` | notice-service 消费 `RoomUserKicked` 等私有通知事实 |
|
||||
| `hyapp_room_outbox` | `hyapp-room-outbox-producer` | `hyapp-room-im-bridge` | room-service IM bridge 消费房间群系统消息和群成员控制事实 |
|
||||
| `hyapp_robot_room_outbox` | `hyapp-room-robot-outbox-producer` | `hyapp-test-room-robot-im-bridge` / `hyapp-room-robot-im-bridge` | room-service IM bridge 只消费机器人房间礼物、热度和麦位热度展示事实;本地/testbox 用 test group,线上用正式 group |
|
||||
| `hyapp_room_outbox` | `hyapp-room-outbox-producer` | `hyapp-user-mictime-room-outbox` | user-service 消费 `RoomMicChanged` 并更新用户麦时读模型 |
|
||||
| `hyapp_room_outbox` | `hyapp-room-outbox-producer` | `hyapp-statistics-room-outbox` | statistics-service 消费 `RoomGiftSent`、`RoomUserJoined` 并更新聚合表 |
|
||||
| `hyapp_user_outbox` | `hyapp-user-outbox-producer` | `hyapp-statistics-user-outbox` | statistics-service 消费 `UserRegistered` 并更新注册 cohort |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.6.2
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v7.35.0
|
||||
// source: proto/activity/v1/activity.proto
|
||||
|
||||
@ -80,10 +80,10 @@ type ActivityServiceServer interface {
|
||||
type UnimplementedActivityServiceServer struct{}
|
||||
|
||||
func (UnimplementedActivityServiceServer) PingActivity(context.Context, *PingActivityRequest) (*PingActivityResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method PingActivity not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PingActivity not implemented")
|
||||
}
|
||||
func (UnimplementedActivityServiceServer) GetActivityStatus(context.Context, *GetActivityStatusRequest) (*GetActivityStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetActivityStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetActivityStatus not implemented")
|
||||
}
|
||||
func (UnimplementedActivityServiceServer) mustEmbedUnimplementedActivityServiceServer() {}
|
||||
func (UnimplementedActivityServiceServer) testEmbeddedByValue() {}
|
||||
@ -96,7 +96,7 @@ type UnsafeActivityServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterActivityServiceServer(s grpc.ServiceRegistrar, srv ActivityServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedActivityServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedActivityServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -289,25 +289,25 @@ type MessageInboxServiceServer interface {
|
||||
type UnimplementedMessageInboxServiceServer struct{}
|
||||
|
||||
func (UnimplementedMessageInboxServiceServer) ListMessageTabs(context.Context, *ListMessageTabsRequest) (*ListMessageTabsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListMessageTabs not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListMessageTabs not implemented")
|
||||
}
|
||||
func (UnimplementedMessageInboxServiceServer) ListInboxMessages(context.Context, *ListInboxMessagesRequest) (*ListInboxMessagesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListInboxMessages not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListInboxMessages not implemented")
|
||||
}
|
||||
func (UnimplementedMessageInboxServiceServer) MarkInboxMessageRead(context.Context, *MarkInboxMessageReadRequest) (*MarkInboxMessageReadResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method MarkInboxMessageRead not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method MarkInboxMessageRead not implemented")
|
||||
}
|
||||
func (UnimplementedMessageInboxServiceServer) MarkInboxSectionRead(context.Context, *MarkInboxSectionReadRequest) (*MarkInboxSectionReadResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method MarkInboxSectionRead not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method MarkInboxSectionRead not implemented")
|
||||
}
|
||||
func (UnimplementedMessageInboxServiceServer) DeleteInboxMessage(context.Context, *DeleteInboxMessageRequest) (*DeleteInboxMessageResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method DeleteInboxMessage not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeleteInboxMessage not implemented")
|
||||
}
|
||||
func (UnimplementedMessageInboxServiceServer) CreateInboxMessage(context.Context, *CreateInboxMessageRequest) (*CreateInboxMessageResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateInboxMessage not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateInboxMessage not implemented")
|
||||
}
|
||||
func (UnimplementedMessageInboxServiceServer) CreateFanoutJob(context.Context, *CreateFanoutJobRequest) (*CreateFanoutJobResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateFanoutJob not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateFanoutJob not implemented")
|
||||
}
|
||||
func (UnimplementedMessageInboxServiceServer) mustEmbedUnimplementedMessageInboxServiceServer() {}
|
||||
func (UnimplementedMessageInboxServiceServer) testEmbeddedByValue() {}
|
||||
@ -320,7 +320,7 @@ type UnsafeMessageInboxServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterMessageInboxServiceServer(s grpc.ServiceRegistrar, srv MessageInboxServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedMessageInboxServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedMessageInboxServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -623,25 +623,25 @@ type ActivityCronServiceServer interface {
|
||||
type UnimplementedActivityCronServiceServer struct{}
|
||||
|
||||
func (UnimplementedActivityCronServiceServer) ProcessMessageFanoutBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessMessageFanoutBatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessMessageFanoutBatch not implemented")
|
||||
}
|
||||
func (UnimplementedActivityCronServiceServer) ProcessLevelRewardBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessLevelRewardBatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessLevelRewardBatch not implemented")
|
||||
}
|
||||
func (UnimplementedActivityCronServiceServer) ProcessAchievementRewardBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessAchievementRewardBatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessAchievementRewardBatch not implemented")
|
||||
}
|
||||
func (UnimplementedActivityCronServiceServer) ProcessRoomTurnoverRewardSettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessRoomTurnoverRewardSettlementBatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessRoomTurnoverRewardSettlementBatch not implemented")
|
||||
}
|
||||
func (UnimplementedActivityCronServiceServer) ProcessWeeklyStarSettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessWeeklyStarSettlementBatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessWeeklyStarSettlementBatch not implemented")
|
||||
}
|
||||
func (UnimplementedActivityCronServiceServer) ProcessCPWeeklyRankSettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessCPWeeklyRankSettlementBatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessCPWeeklyRankSettlementBatch not implemented")
|
||||
}
|
||||
func (UnimplementedActivityCronServiceServer) ProcessAgencyOpeningSettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessAgencyOpeningSettlementBatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessAgencyOpeningSettlementBatch not implemented")
|
||||
}
|
||||
func (UnimplementedActivityCronServiceServer) mustEmbedUnimplementedActivityCronServiceServer() {}
|
||||
func (UnimplementedActivityCronServiceServer) testEmbeddedByValue() {}
|
||||
@ -654,7 +654,7 @@ type UnsafeActivityCronServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterActivityCronServiceServer(s grpc.ServiceRegistrar, srv ActivityCronServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedActivityCronServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedActivityCronServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -905,13 +905,13 @@ type TaskServiceServer interface {
|
||||
type UnimplementedTaskServiceServer struct{}
|
||||
|
||||
func (UnimplementedTaskServiceServer) ListUserTasks(context.Context, *ListUserTasksRequest) (*ListUserTasksResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListUserTasks not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListUserTasks not implemented")
|
||||
}
|
||||
func (UnimplementedTaskServiceServer) ClaimTaskReward(context.Context, *ClaimTaskRewardRequest) (*ClaimTaskRewardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ClaimTaskReward not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ClaimTaskReward not implemented")
|
||||
}
|
||||
func (UnimplementedTaskServiceServer) ConsumeTaskEvent(context.Context, *ConsumeTaskEventRequest) (*ConsumeTaskEventResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ConsumeTaskEvent not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ConsumeTaskEvent not implemented")
|
||||
}
|
||||
func (UnimplementedTaskServiceServer) mustEmbedUnimplementedTaskServiceServer() {}
|
||||
func (UnimplementedTaskServiceServer) testEmbeddedByValue() {}
|
||||
@ -924,7 +924,7 @@ type UnsafeTaskServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterTaskServiceServer(s grpc.ServiceRegistrar, srv TaskServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedTaskServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedTaskServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -1139,25 +1139,25 @@ type GrowthLevelServiceServer interface {
|
||||
type UnimplementedGrowthLevelServiceServer struct{}
|
||||
|
||||
func (UnimplementedGrowthLevelServiceServer) GetMyLevelOverview(context.Context, *GetMyLevelOverviewRequest) (*GetMyLevelOverviewResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetMyLevelOverview not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetMyLevelOverview not implemented")
|
||||
}
|
||||
func (UnimplementedGrowthLevelServiceServer) GetLevelTrack(context.Context, *GetLevelTrackRequest) (*GetLevelTrackResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetLevelTrack not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetLevelTrack not implemented")
|
||||
}
|
||||
func (UnimplementedGrowthLevelServiceServer) BatchGetUserLevelDisplayProfiles(context.Context, *BatchGetUserLevelDisplayProfilesRequest) (*BatchGetUserLevelDisplayProfilesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method BatchGetUserLevelDisplayProfiles not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method BatchGetUserLevelDisplayProfiles not implemented")
|
||||
}
|
||||
func (UnimplementedGrowthLevelServiceServer) ListLevelRewards(context.Context, *ListLevelRewardsRequest) (*ListLevelRewardsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListLevelRewards not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListLevelRewards not implemented")
|
||||
}
|
||||
func (UnimplementedGrowthLevelServiceServer) ConsumeLevelEvent(context.Context, *ConsumeLevelEventRequest) (*ConsumeLevelEventResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ConsumeLevelEvent not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ConsumeLevelEvent not implemented")
|
||||
}
|
||||
func (UnimplementedGrowthLevelServiceServer) SetUserLevel(context.Context, *SetUserLevelRequest) (*SetUserLevelResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetUserLevel not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetUserLevel not implemented")
|
||||
}
|
||||
func (UnimplementedGrowthLevelServiceServer) IssueRegistrationLevelBadges(context.Context, *IssueRegistrationLevelBadgesRequest) (*IssueRegistrationLevelBadgesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method IssueRegistrationLevelBadges not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method IssueRegistrationLevelBadges not implemented")
|
||||
}
|
||||
func (UnimplementedGrowthLevelServiceServer) mustEmbedUnimplementedGrowthLevelServiceServer() {}
|
||||
func (UnimplementedGrowthLevelServiceServer) testEmbeddedByValue() {}
|
||||
@ -1170,7 +1170,7 @@ type UnsafeGrowthLevelServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterGrowthLevelServiceServer(s grpc.ServiceRegistrar, srv GrowthLevelServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedGrowthLevelServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedGrowthLevelServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -1434,16 +1434,16 @@ type AchievementServiceServer interface {
|
||||
type UnimplementedAchievementServiceServer struct{}
|
||||
|
||||
func (UnimplementedAchievementServiceServer) ListAchievements(context.Context, *ListAchievementsRequest) (*ListAchievementsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListAchievements not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListAchievements not implemented")
|
||||
}
|
||||
func (UnimplementedAchievementServiceServer) ConsumeAchievementEvent(context.Context, *ConsumeAchievementEventRequest) (*ConsumeAchievementEventResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ConsumeAchievementEvent not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ConsumeAchievementEvent not implemented")
|
||||
}
|
||||
func (UnimplementedAchievementServiceServer) ListMyBadges(context.Context, *ListMyBadgesRequest) (*ListMyBadgesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListMyBadges not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListMyBadges not implemented")
|
||||
}
|
||||
func (UnimplementedAchievementServiceServer) SetBadgeDisplay(context.Context, *SetBadgeDisplayRequest) (*SetBadgeDisplayResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetBadgeDisplay not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetBadgeDisplay not implemented")
|
||||
}
|
||||
func (UnimplementedAchievementServiceServer) mustEmbedUnimplementedAchievementServiceServer() {}
|
||||
func (UnimplementedAchievementServiceServer) testEmbeddedByValue() {}
|
||||
@ -1456,7 +1456,7 @@ type UnsafeAchievementServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAchievementServiceServer(s grpc.ServiceRegistrar, srv AchievementServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAchievementServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAchievementServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -1628,10 +1628,10 @@ type LuckyGiftServiceServer interface {
|
||||
type UnimplementedLuckyGiftServiceServer struct{}
|
||||
|
||||
func (UnimplementedLuckyGiftServiceServer) CheckLuckyGift(context.Context, *CheckLuckyGiftRequest) (*CheckLuckyGiftResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CheckLuckyGift not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CheckLuckyGift not implemented")
|
||||
}
|
||||
func (UnimplementedLuckyGiftServiceServer) ExecuteLuckyGiftDraw(context.Context, *ExecuteLuckyGiftDrawRequest) (*ExecuteLuckyGiftDrawResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ExecuteLuckyGiftDraw not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ExecuteLuckyGiftDraw not implemented")
|
||||
}
|
||||
func (UnimplementedLuckyGiftServiceServer) mustEmbedUnimplementedLuckyGiftServiceServer() {}
|
||||
func (UnimplementedLuckyGiftServiceServer) testEmbeddedByValue() {}
|
||||
@ -1644,7 +1644,7 @@ type UnsafeLuckyGiftServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterLuckyGiftServiceServer(s grpc.ServiceRegistrar, srv LuckyGiftServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedLuckyGiftServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedLuckyGiftServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -1759,7 +1759,7 @@ type RoomTurnoverRewardServiceServer interface {
|
||||
type UnimplementedRoomTurnoverRewardServiceServer struct{}
|
||||
|
||||
func (UnimplementedRoomTurnoverRewardServiceServer) GetRoomTurnoverRewardStatus(context.Context, *GetRoomTurnoverRewardStatusRequest) (*GetRoomTurnoverRewardStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetRoomTurnoverRewardStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRoomTurnoverRewardStatus not implemented")
|
||||
}
|
||||
func (UnimplementedRoomTurnoverRewardServiceServer) mustEmbedUnimplementedRoomTurnoverRewardServiceServer() {
|
||||
}
|
||||
@ -1773,7 +1773,7 @@ type UnsafeRoomTurnoverRewardServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterRoomTurnoverRewardServiceServer(s grpc.ServiceRegistrar, srv RoomTurnoverRewardServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedRoomTurnoverRewardServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedRoomTurnoverRewardServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -1892,13 +1892,13 @@ type WeeklyStarServiceServer interface {
|
||||
type UnimplementedWeeklyStarServiceServer struct{}
|
||||
|
||||
func (UnimplementedWeeklyStarServiceServer) GetWeeklyStarCurrent(context.Context, *GetWeeklyStarCurrentRequest) (*GetWeeklyStarCurrentResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetWeeklyStarCurrent not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetWeeklyStarCurrent not implemented")
|
||||
}
|
||||
func (UnimplementedWeeklyStarServiceServer) ListWeeklyStarLeaderboard(context.Context, *ListWeeklyStarLeaderboardRequest) (*ListWeeklyStarLeaderboardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListWeeklyStarLeaderboard not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListWeeklyStarLeaderboard not implemented")
|
||||
}
|
||||
func (UnimplementedWeeklyStarServiceServer) ListWeeklyStarHistory(context.Context, *ListWeeklyStarHistoryRequest) (*ListWeeklyStarHistoryResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListWeeklyStarHistory not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListWeeklyStarHistory not implemented")
|
||||
}
|
||||
func (UnimplementedWeeklyStarServiceServer) mustEmbedUnimplementedWeeklyStarServiceServer() {}
|
||||
func (UnimplementedWeeklyStarServiceServer) testEmbeddedByValue() {}
|
||||
@ -1911,7 +1911,7 @@ type UnsafeWeeklyStarServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterWeeklyStarServiceServer(s grpc.ServiceRegistrar, srv WeeklyStarServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedWeeklyStarServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedWeeklyStarServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -2048,7 +2048,7 @@ type CPWeeklyRankServiceServer interface {
|
||||
type UnimplementedCPWeeklyRankServiceServer struct{}
|
||||
|
||||
func (UnimplementedCPWeeklyRankServiceServer) GetCPWeeklyRankStatus(context.Context, *GetCPWeeklyRankStatusRequest) (*GetCPWeeklyRankStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetCPWeeklyRankStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetCPWeeklyRankStatus not implemented")
|
||||
}
|
||||
func (UnimplementedCPWeeklyRankServiceServer) mustEmbedUnimplementedCPWeeklyRankServiceServer() {}
|
||||
func (UnimplementedCPWeeklyRankServiceServer) testEmbeddedByValue() {}
|
||||
@ -2061,7 +2061,7 @@ type UnsafeCPWeeklyRankServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterCPWeeklyRankServiceServer(s grpc.ServiceRegistrar, srv CPWeeklyRankServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedCPWeeklyRankServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedCPWeeklyRankServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -2180,13 +2180,13 @@ type AgencyOpeningServiceServer interface {
|
||||
type UnimplementedAgencyOpeningServiceServer struct{}
|
||||
|
||||
func (UnimplementedAgencyOpeningServiceServer) GetAgencyOpeningStatus(context.Context, *GetAgencyOpeningStatusRequest) (*GetAgencyOpeningStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetAgencyOpeningStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetAgencyOpeningStatus not implemented")
|
||||
}
|
||||
func (UnimplementedAgencyOpeningServiceServer) ApplyAgencyOpening(context.Context, *ApplyAgencyOpeningRequest) (*ApplyAgencyOpeningResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ApplyAgencyOpening not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ApplyAgencyOpening not implemented")
|
||||
}
|
||||
func (UnimplementedAgencyOpeningServiceServer) ListAgencyOpeningLeaderboard(context.Context, *ListAgencyOpeningApplicationsRequest) (*ListAgencyOpeningApplicationsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListAgencyOpeningLeaderboard not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListAgencyOpeningLeaderboard not implemented")
|
||||
}
|
||||
func (UnimplementedAgencyOpeningServiceServer) mustEmbedUnimplementedAgencyOpeningServiceServer() {}
|
||||
func (UnimplementedAgencyOpeningServiceServer) testEmbeddedByValue() {}
|
||||
@ -2199,7 +2199,7 @@ type UnsafeAgencyOpeningServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAgencyOpeningServiceServer(s grpc.ServiceRegistrar, srv AgencyOpeningServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAgencyOpeningServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAgencyOpeningServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -2388,19 +2388,19 @@ type BroadcastServiceServer interface {
|
||||
type UnimplementedBroadcastServiceServer struct{}
|
||||
|
||||
func (UnimplementedBroadcastServiceServer) EnsureBroadcastGroups(context.Context, *EnsureBroadcastGroupsRequest) (*EnsureBroadcastGroupsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method EnsureBroadcastGroups not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method EnsureBroadcastGroups not implemented")
|
||||
}
|
||||
func (UnimplementedBroadcastServiceServer) PublishRegionBroadcast(context.Context, *PublishRegionBroadcastRequest) (*PublishBroadcastResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method PublishRegionBroadcast not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PublishRegionBroadcast not implemented")
|
||||
}
|
||||
func (UnimplementedBroadcastServiceServer) PublishGlobalBroadcast(context.Context, *PublishGlobalBroadcastRequest) (*PublishBroadcastResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method PublishGlobalBroadcast not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PublishGlobalBroadcast not implemented")
|
||||
}
|
||||
func (UnimplementedBroadcastServiceServer) RemoveRegionBroadcastMember(context.Context, *RemoveRegionBroadcastMemberRequest) (*RemoveRegionBroadcastMemberResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RemoveRegionBroadcastMember not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RemoveRegionBroadcastMember not implemented")
|
||||
}
|
||||
func (UnimplementedBroadcastServiceServer) ProcessBroadcastOutboxBatch(context.Context, *CronBatchRequest) (*ProcessBroadcastOutboxBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessBroadcastOutboxBatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessBroadcastOutboxBatch not implemented")
|
||||
}
|
||||
func (UnimplementedBroadcastServiceServer) mustEmbedUnimplementedBroadcastServiceServer() {}
|
||||
func (UnimplementedBroadcastServiceServer) testEmbeddedByValue() {}
|
||||
@ -2413,7 +2413,7 @@ type UnsafeBroadcastServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterBroadcastServiceServer(s grpc.ServiceRegistrar, srv BroadcastServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedBroadcastServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedBroadcastServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -2594,7 +2594,7 @@ type RoomEventConsumerServiceServer interface {
|
||||
type UnimplementedRoomEventConsumerServiceServer struct{}
|
||||
|
||||
func (UnimplementedRoomEventConsumerServiceServer) ConsumeRoomEvent(context.Context, *ConsumeRoomEventRequest) (*ConsumeRoomEventResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ConsumeRoomEvent not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ConsumeRoomEvent not implemented")
|
||||
}
|
||||
func (UnimplementedRoomEventConsumerServiceServer) mustEmbedUnimplementedRoomEventConsumerServiceServer() {
|
||||
}
|
||||
@ -2608,7 +2608,7 @@ type UnsafeRoomEventConsumerServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterRoomEventConsumerServiceServer(s grpc.ServiceRegistrar, srv RoomEventConsumerServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedRoomEventConsumerServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedRoomEventConsumerServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -2727,13 +2727,13 @@ type AdminTaskServiceServer interface {
|
||||
type UnimplementedAdminTaskServiceServer struct{}
|
||||
|
||||
func (UnimplementedAdminTaskServiceServer) ListTaskDefinitions(context.Context, *ListTaskDefinitionsRequest) (*ListTaskDefinitionsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListTaskDefinitions not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListTaskDefinitions not implemented")
|
||||
}
|
||||
func (UnimplementedAdminTaskServiceServer) UpsertTaskDefinition(context.Context, *UpsertTaskDefinitionRequest) (*UpsertTaskDefinitionResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpsertTaskDefinition not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpsertTaskDefinition not implemented")
|
||||
}
|
||||
func (UnimplementedAdminTaskServiceServer) SetTaskDefinitionStatus(context.Context, *SetTaskDefinitionStatusRequest) (*SetTaskDefinitionStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetTaskDefinitionStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetTaskDefinitionStatus not implemented")
|
||||
}
|
||||
func (UnimplementedAdminTaskServiceServer) mustEmbedUnimplementedAdminTaskServiceServer() {}
|
||||
func (UnimplementedAdminTaskServiceServer) testEmbeddedByValue() {}
|
||||
@ -2746,7 +2746,7 @@ type UnsafeAdminTaskServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAdminTaskServiceServer(s grpc.ServiceRegistrar, srv AdminTaskServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAdminTaskServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAdminTaskServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -2896,10 +2896,10 @@ type RegistrationRewardServiceServer interface {
|
||||
type UnimplementedRegistrationRewardServiceServer struct{}
|
||||
|
||||
func (UnimplementedRegistrationRewardServiceServer) GetRegistrationRewardEligibility(context.Context, *GetRegistrationRewardEligibilityRequest) (*GetRegistrationRewardEligibilityResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetRegistrationRewardEligibility not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRegistrationRewardEligibility not implemented")
|
||||
}
|
||||
func (UnimplementedRegistrationRewardServiceServer) IssueRegistrationReward(context.Context, *IssueRegistrationRewardRequest) (*IssueRegistrationRewardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method IssueRegistrationReward not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method IssueRegistrationReward not implemented")
|
||||
}
|
||||
func (UnimplementedRegistrationRewardServiceServer) mustEmbedUnimplementedRegistrationRewardServiceServer() {
|
||||
}
|
||||
@ -2913,7 +2913,7 @@ type UnsafeRegistrationRewardServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterRegistrationRewardServiceServer(s grpc.ServiceRegistrar, srv RegistrationRewardServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedRegistrationRewardServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedRegistrationRewardServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -3054,13 +3054,13 @@ type AdminRegistrationRewardServiceServer interface {
|
||||
type UnimplementedAdminRegistrationRewardServiceServer struct{}
|
||||
|
||||
func (UnimplementedAdminRegistrationRewardServiceServer) GetRegistrationRewardConfig(context.Context, *GetRegistrationRewardConfigRequest) (*GetRegistrationRewardConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetRegistrationRewardConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRegistrationRewardConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminRegistrationRewardServiceServer) UpdateRegistrationRewardConfig(context.Context, *UpdateRegistrationRewardConfigRequest) (*UpdateRegistrationRewardConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateRegistrationRewardConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateRegistrationRewardConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminRegistrationRewardServiceServer) ListRegistrationRewardClaims(context.Context, *ListRegistrationRewardClaimsRequest) (*ListRegistrationRewardClaimsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRegistrationRewardClaims not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRegistrationRewardClaims not implemented")
|
||||
}
|
||||
func (UnimplementedAdminRegistrationRewardServiceServer) mustEmbedUnimplementedAdminRegistrationRewardServiceServer() {
|
||||
}
|
||||
@ -3074,7 +3074,7 @@ type UnsafeAdminRegistrationRewardServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAdminRegistrationRewardServiceServer(s grpc.ServiceRegistrar, srv AdminRegistrationRewardServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAdminRegistrationRewardServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAdminRegistrationRewardServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -3224,10 +3224,10 @@ type FirstRechargeRewardServiceServer interface {
|
||||
type UnimplementedFirstRechargeRewardServiceServer struct{}
|
||||
|
||||
func (UnimplementedFirstRechargeRewardServiceServer) GetFirstRechargeRewardStatus(context.Context, *GetFirstRechargeRewardStatusRequest) (*GetFirstRechargeRewardStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetFirstRechargeRewardStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetFirstRechargeRewardStatus not implemented")
|
||||
}
|
||||
func (UnimplementedFirstRechargeRewardServiceServer) ConsumeFirstRechargeReward(context.Context, *ConsumeFirstRechargeRewardRequest) (*ConsumeFirstRechargeRewardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ConsumeFirstRechargeReward not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ConsumeFirstRechargeReward not implemented")
|
||||
}
|
||||
func (UnimplementedFirstRechargeRewardServiceServer) mustEmbedUnimplementedFirstRechargeRewardServiceServer() {
|
||||
}
|
||||
@ -3241,7 +3241,7 @@ type UnsafeFirstRechargeRewardServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterFirstRechargeRewardServiceServer(s grpc.ServiceRegistrar, srv FirstRechargeRewardServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedFirstRechargeRewardServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedFirstRechargeRewardServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -3382,13 +3382,13 @@ type AdminFirstRechargeRewardServiceServer interface {
|
||||
type UnimplementedAdminFirstRechargeRewardServiceServer struct{}
|
||||
|
||||
func (UnimplementedAdminFirstRechargeRewardServiceServer) GetFirstRechargeRewardConfig(context.Context, *GetFirstRechargeRewardConfigRequest) (*GetFirstRechargeRewardConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetFirstRechargeRewardConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetFirstRechargeRewardConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminFirstRechargeRewardServiceServer) UpdateFirstRechargeRewardConfig(context.Context, *UpdateFirstRechargeRewardConfigRequest) (*UpdateFirstRechargeRewardConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateFirstRechargeRewardConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateFirstRechargeRewardConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminFirstRechargeRewardServiceServer) ListFirstRechargeRewardClaims(context.Context, *ListFirstRechargeRewardClaimsRequest) (*ListFirstRechargeRewardClaimsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListFirstRechargeRewardClaims not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListFirstRechargeRewardClaims not implemented")
|
||||
}
|
||||
func (UnimplementedAdminFirstRechargeRewardServiceServer) mustEmbedUnimplementedAdminFirstRechargeRewardServiceServer() {
|
||||
}
|
||||
@ -3402,7 +3402,7 @@ type UnsafeAdminFirstRechargeRewardServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAdminFirstRechargeRewardServiceServer(s grpc.ServiceRegistrar, srv AdminFirstRechargeRewardServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAdminFirstRechargeRewardServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAdminFirstRechargeRewardServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -3552,10 +3552,10 @@ type CumulativeRechargeRewardServiceServer interface {
|
||||
type UnimplementedCumulativeRechargeRewardServiceServer struct{}
|
||||
|
||||
func (UnimplementedCumulativeRechargeRewardServiceServer) GetCumulativeRechargeRewardStatus(context.Context, *GetCumulativeRechargeRewardStatusRequest) (*GetCumulativeRechargeRewardStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetCumulativeRechargeRewardStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetCumulativeRechargeRewardStatus not implemented")
|
||||
}
|
||||
func (UnimplementedCumulativeRechargeRewardServiceServer) ConsumeCumulativeRechargeReward(context.Context, *ConsumeCumulativeRechargeRewardRequest) (*ConsumeCumulativeRechargeRewardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ConsumeCumulativeRechargeReward not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ConsumeCumulativeRechargeReward not implemented")
|
||||
}
|
||||
func (UnimplementedCumulativeRechargeRewardServiceServer) mustEmbedUnimplementedCumulativeRechargeRewardServiceServer() {
|
||||
}
|
||||
@ -3569,7 +3569,7 @@ type UnsafeCumulativeRechargeRewardServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterCumulativeRechargeRewardServiceServer(s grpc.ServiceRegistrar, srv CumulativeRechargeRewardServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedCumulativeRechargeRewardServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedCumulativeRechargeRewardServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -3710,13 +3710,13 @@ type InviteActivityRewardServiceServer interface {
|
||||
type UnimplementedInviteActivityRewardServiceServer struct{}
|
||||
|
||||
func (UnimplementedInviteActivityRewardServiceServer) GetInviteActivityRewardStatus(context.Context, *GetInviteActivityRewardStatusRequest) (*GetInviteActivityRewardStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetInviteActivityRewardStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetInviteActivityRewardStatus not implemented")
|
||||
}
|
||||
func (UnimplementedInviteActivityRewardServiceServer) ClaimInviteActivityReward(context.Context, *ClaimInviteActivityRewardRequest) (*ClaimInviteActivityRewardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ClaimInviteActivityReward not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ClaimInviteActivityReward not implemented")
|
||||
}
|
||||
func (UnimplementedInviteActivityRewardServiceServer) ListInviteActivityLeaderboard(context.Context, *ListInviteActivityLeaderboardRequest) (*ListInviteActivityLeaderboardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListInviteActivityLeaderboard not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListInviteActivityLeaderboard not implemented")
|
||||
}
|
||||
func (UnimplementedInviteActivityRewardServiceServer) mustEmbedUnimplementedInviteActivityRewardServiceServer() {
|
||||
}
|
||||
@ -3730,7 +3730,7 @@ type UnsafeInviteActivityRewardServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterInviteActivityRewardServiceServer(s grpc.ServiceRegistrar, srv InviteActivityRewardServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedInviteActivityRewardServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedInviteActivityRewardServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -3893,13 +3893,13 @@ type AdminCumulativeRechargeRewardServiceServer interface {
|
||||
type UnimplementedAdminCumulativeRechargeRewardServiceServer struct{}
|
||||
|
||||
func (UnimplementedAdminCumulativeRechargeRewardServiceServer) GetCumulativeRechargeRewardConfig(context.Context, *GetCumulativeRechargeRewardConfigRequest) (*GetCumulativeRechargeRewardConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetCumulativeRechargeRewardConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetCumulativeRechargeRewardConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminCumulativeRechargeRewardServiceServer) UpdateCumulativeRechargeRewardConfig(context.Context, *UpdateCumulativeRechargeRewardConfigRequest) (*UpdateCumulativeRechargeRewardConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateCumulativeRechargeRewardConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateCumulativeRechargeRewardConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminCumulativeRechargeRewardServiceServer) ListCumulativeRechargeRewardGrants(context.Context, *ListCumulativeRechargeRewardGrantsRequest) (*ListCumulativeRechargeRewardGrantsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListCumulativeRechargeRewardGrants not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListCumulativeRechargeRewardGrants not implemented")
|
||||
}
|
||||
func (UnimplementedAdminCumulativeRechargeRewardServiceServer) mustEmbedUnimplementedAdminCumulativeRechargeRewardServiceServer() {
|
||||
}
|
||||
@ -3913,7 +3913,7 @@ type UnsafeAdminCumulativeRechargeRewardServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAdminCumulativeRechargeRewardServiceServer(s grpc.ServiceRegistrar, srv AdminCumulativeRechargeRewardServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAdminCumulativeRechargeRewardServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAdminCumulativeRechargeRewardServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -4089,16 +4089,16 @@ type AdminInviteActivityRewardServiceServer interface {
|
||||
type UnimplementedAdminInviteActivityRewardServiceServer struct{}
|
||||
|
||||
func (UnimplementedAdminInviteActivityRewardServiceServer) GetInviteActivityRewardConfig(context.Context, *GetInviteActivityRewardConfigRequest) (*GetInviteActivityRewardConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetInviteActivityRewardConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetInviteActivityRewardConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminInviteActivityRewardServiceServer) UpdateInviteActivityRewardConfig(context.Context, *UpdateInviteActivityRewardConfigRequest) (*UpdateInviteActivityRewardConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateInviteActivityRewardConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateInviteActivityRewardConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminInviteActivityRewardServiceServer) ListInviteActivityRewardClaims(context.Context, *ListInviteActivityRewardClaimsRequest) (*ListInviteActivityRewardClaimsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListInviteActivityRewardClaims not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListInviteActivityRewardClaims not implemented")
|
||||
}
|
||||
func (UnimplementedAdminInviteActivityRewardServiceServer) ListInviteActivityRewardSummaries(context.Context, *ListInviteActivityRewardSummariesRequest) (*ListInviteActivityRewardSummariesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListInviteActivityRewardSummaries not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListInviteActivityRewardSummaries not implemented")
|
||||
}
|
||||
func (UnimplementedAdminInviteActivityRewardServiceServer) mustEmbedUnimplementedAdminInviteActivityRewardServiceServer() {
|
||||
}
|
||||
@ -4112,7 +4112,7 @@ type UnsafeAdminInviteActivityRewardServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAdminInviteActivityRewardServiceServer(s grpc.ServiceRegistrar, srv AdminInviteActivityRewardServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAdminInviteActivityRewardServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAdminInviteActivityRewardServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -4310,16 +4310,16 @@ type AdminRoomTurnoverRewardServiceServer interface {
|
||||
type UnimplementedAdminRoomTurnoverRewardServiceServer struct{}
|
||||
|
||||
func (UnimplementedAdminRoomTurnoverRewardServiceServer) GetRoomTurnoverRewardConfig(context.Context, *GetRoomTurnoverRewardConfigRequest) (*GetRoomTurnoverRewardConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetRoomTurnoverRewardConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRoomTurnoverRewardConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminRoomTurnoverRewardServiceServer) UpdateRoomTurnoverRewardConfig(context.Context, *UpdateRoomTurnoverRewardConfigRequest) (*UpdateRoomTurnoverRewardConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateRoomTurnoverRewardConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateRoomTurnoverRewardConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminRoomTurnoverRewardServiceServer) ListRoomTurnoverRewardSettlements(context.Context, *ListRoomTurnoverRewardSettlementsRequest) (*ListRoomTurnoverRewardSettlementsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRoomTurnoverRewardSettlements not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRoomTurnoverRewardSettlements not implemented")
|
||||
}
|
||||
func (UnimplementedAdminRoomTurnoverRewardServiceServer) RetryRoomTurnoverRewardSettlement(context.Context, *RetryRoomTurnoverRewardSettlementRequest) (*RetryRoomTurnoverRewardSettlementResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RetryRoomTurnoverRewardSettlement not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RetryRoomTurnoverRewardSettlement not implemented")
|
||||
}
|
||||
func (UnimplementedAdminRoomTurnoverRewardServiceServer) mustEmbedUnimplementedAdminRoomTurnoverRewardServiceServer() {
|
||||
}
|
||||
@ -4333,7 +4333,7 @@ type UnsafeAdminRoomTurnoverRewardServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAdminRoomTurnoverRewardServiceServer(s grpc.ServiceRegistrar, srv AdminRoomTurnoverRewardServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAdminRoomTurnoverRewardServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAdminRoomTurnoverRewardServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -4570,25 +4570,25 @@ type AdminWeeklyStarServiceServer interface {
|
||||
type UnimplementedAdminWeeklyStarServiceServer struct{}
|
||||
|
||||
func (UnimplementedAdminWeeklyStarServiceServer) ListWeeklyStarCycles(context.Context, *ListWeeklyStarCyclesRequest) (*ListWeeklyStarCyclesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListWeeklyStarCycles not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListWeeklyStarCycles not implemented")
|
||||
}
|
||||
func (UnimplementedAdminWeeklyStarServiceServer) CreateWeeklyStarCycle(context.Context, *UpsertWeeklyStarCycleRequest) (*UpsertWeeklyStarCycleResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateWeeklyStarCycle not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateWeeklyStarCycle not implemented")
|
||||
}
|
||||
func (UnimplementedAdminWeeklyStarServiceServer) GetWeeklyStarCycle(context.Context, *GetWeeklyStarCycleRequest) (*GetWeeklyStarCycleResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetWeeklyStarCycle not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetWeeklyStarCycle not implemented")
|
||||
}
|
||||
func (UnimplementedAdminWeeklyStarServiceServer) UpdateWeeklyStarCycle(context.Context, *UpsertWeeklyStarCycleRequest) (*UpsertWeeklyStarCycleResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateWeeklyStarCycle not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateWeeklyStarCycle not implemented")
|
||||
}
|
||||
func (UnimplementedAdminWeeklyStarServiceServer) SetWeeklyStarCycleStatus(context.Context, *SetWeeklyStarCycleStatusRequest) (*SetWeeklyStarCycleStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetWeeklyStarCycleStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetWeeklyStarCycleStatus not implemented")
|
||||
}
|
||||
func (UnimplementedAdminWeeklyStarServiceServer) ListWeeklyStarLeaderboard(context.Context, *ListWeeklyStarLeaderboardRequest) (*ListWeeklyStarLeaderboardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListWeeklyStarLeaderboard not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListWeeklyStarLeaderboard not implemented")
|
||||
}
|
||||
func (UnimplementedAdminWeeklyStarServiceServer) ListWeeklyStarSettlements(context.Context, *ListWeeklyStarSettlementsRequest) (*ListWeeklyStarSettlementsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListWeeklyStarSettlements not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListWeeklyStarSettlements not implemented")
|
||||
}
|
||||
func (UnimplementedAdminWeeklyStarServiceServer) mustEmbedUnimplementedAdminWeeklyStarServiceServer() {
|
||||
}
|
||||
@ -4602,7 +4602,7 @@ type UnsafeAdminWeeklyStarServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAdminWeeklyStarServiceServer(s grpc.ServiceRegistrar, srv AdminWeeklyStarServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAdminWeeklyStarServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAdminWeeklyStarServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -4853,13 +4853,13 @@ type AdminCPWeeklyRankServiceServer interface {
|
||||
type UnimplementedAdminCPWeeklyRankServiceServer struct{}
|
||||
|
||||
func (UnimplementedAdminCPWeeklyRankServiceServer) GetCPWeeklyRankConfig(context.Context, *GetCPWeeklyRankConfigRequest) (*GetCPWeeklyRankConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetCPWeeklyRankConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetCPWeeklyRankConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminCPWeeklyRankServiceServer) UpdateCPWeeklyRankConfig(context.Context, *UpdateCPWeeklyRankConfigRequest) (*UpdateCPWeeklyRankConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateCPWeeklyRankConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateCPWeeklyRankConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminCPWeeklyRankServiceServer) ListCPWeeklyRankSettlements(context.Context, *ListCPWeeklyRankSettlementsRequest) (*ListCPWeeklyRankSettlementsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListCPWeeklyRankSettlements not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListCPWeeklyRankSettlements not implemented")
|
||||
}
|
||||
func (UnimplementedAdminCPWeeklyRankServiceServer) mustEmbedUnimplementedAdminCPWeeklyRankServiceServer() {
|
||||
}
|
||||
@ -4873,7 +4873,7 @@ type UnsafeAdminCPWeeklyRankServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAdminCPWeeklyRankServiceServer(s grpc.ServiceRegistrar, srv AdminCPWeeklyRankServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAdminCPWeeklyRankServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAdminCPWeeklyRankServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -5075,22 +5075,22 @@ type AdminAgencyOpeningServiceServer interface {
|
||||
type UnimplementedAdminAgencyOpeningServiceServer struct{}
|
||||
|
||||
func (UnimplementedAdminAgencyOpeningServiceServer) ListAgencyOpeningCycles(context.Context, *ListAgencyOpeningCyclesRequest) (*ListAgencyOpeningCyclesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListAgencyOpeningCycles not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListAgencyOpeningCycles not implemented")
|
||||
}
|
||||
func (UnimplementedAdminAgencyOpeningServiceServer) CreateAgencyOpeningCycle(context.Context, *UpsertAgencyOpeningCycleRequest) (*UpsertAgencyOpeningCycleResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateAgencyOpeningCycle not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateAgencyOpeningCycle not implemented")
|
||||
}
|
||||
func (UnimplementedAdminAgencyOpeningServiceServer) GetAgencyOpeningCycle(context.Context, *GetAgencyOpeningCycleRequest) (*GetAgencyOpeningCycleResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetAgencyOpeningCycle not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetAgencyOpeningCycle not implemented")
|
||||
}
|
||||
func (UnimplementedAdminAgencyOpeningServiceServer) UpdateAgencyOpeningCycle(context.Context, *UpsertAgencyOpeningCycleRequest) (*UpsertAgencyOpeningCycleResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateAgencyOpeningCycle not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateAgencyOpeningCycle not implemented")
|
||||
}
|
||||
func (UnimplementedAdminAgencyOpeningServiceServer) SetAgencyOpeningCycleStatus(context.Context, *SetAgencyOpeningCycleStatusRequest) (*SetAgencyOpeningCycleStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetAgencyOpeningCycleStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetAgencyOpeningCycleStatus not implemented")
|
||||
}
|
||||
func (UnimplementedAdminAgencyOpeningServiceServer) ListAgencyOpeningApplications(context.Context, *ListAgencyOpeningApplicationsRequest) (*ListAgencyOpeningApplicationsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListAgencyOpeningApplications not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListAgencyOpeningApplications not implemented")
|
||||
}
|
||||
func (UnimplementedAdminAgencyOpeningServiceServer) mustEmbedUnimplementedAdminAgencyOpeningServiceServer() {
|
||||
}
|
||||
@ -5104,7 +5104,7 @@ type UnsafeAdminAgencyOpeningServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAdminAgencyOpeningServiceServer(s grpc.ServiceRegistrar, srv AdminAgencyOpeningServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAdminAgencyOpeningServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAdminAgencyOpeningServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -5320,10 +5320,10 @@ type SevenDayCheckInServiceServer interface {
|
||||
type UnimplementedSevenDayCheckInServiceServer struct{}
|
||||
|
||||
func (UnimplementedSevenDayCheckInServiceServer) GetSevenDayCheckInStatus(context.Context, *GetSevenDayCheckInStatusRequest) (*GetSevenDayCheckInStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetSevenDayCheckInStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetSevenDayCheckInStatus not implemented")
|
||||
}
|
||||
func (UnimplementedSevenDayCheckInServiceServer) SignSevenDayCheckIn(context.Context, *SignSevenDayCheckInRequest) (*SignSevenDayCheckInResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SignSevenDayCheckIn not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SignSevenDayCheckIn not implemented")
|
||||
}
|
||||
func (UnimplementedSevenDayCheckInServiceServer) mustEmbedUnimplementedSevenDayCheckInServiceServer() {
|
||||
}
|
||||
@ -5337,7 +5337,7 @@ type UnsafeSevenDayCheckInServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterSevenDayCheckInServiceServer(s grpc.ServiceRegistrar, srv SevenDayCheckInServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedSevenDayCheckInServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedSevenDayCheckInServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -5478,13 +5478,13 @@ type AdminSevenDayCheckInServiceServer interface {
|
||||
type UnimplementedAdminSevenDayCheckInServiceServer struct{}
|
||||
|
||||
func (UnimplementedAdminSevenDayCheckInServiceServer) GetSevenDayCheckInConfig(context.Context, *GetSevenDayCheckInConfigRequest) (*GetSevenDayCheckInConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetSevenDayCheckInConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetSevenDayCheckInConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminSevenDayCheckInServiceServer) UpdateSevenDayCheckInConfig(context.Context, *UpdateSevenDayCheckInConfigRequest) (*UpdateSevenDayCheckInConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateSevenDayCheckInConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateSevenDayCheckInConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminSevenDayCheckInServiceServer) ListSevenDayCheckInClaims(context.Context, *ListSevenDayCheckInClaimsRequest) (*ListSevenDayCheckInClaimsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListSevenDayCheckInClaims not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListSevenDayCheckInClaims not implemented")
|
||||
}
|
||||
func (UnimplementedAdminSevenDayCheckInServiceServer) mustEmbedUnimplementedAdminSevenDayCheckInServiceServer() {
|
||||
}
|
||||
@ -5498,7 +5498,7 @@ type UnsafeAdminSevenDayCheckInServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAdminSevenDayCheckInServiceServer(s grpc.ServiceRegistrar, srv AdminSevenDayCheckInServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAdminSevenDayCheckInServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAdminSevenDayCheckInServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -5674,16 +5674,16 @@ type AdminGrowthLevelServiceServer interface {
|
||||
type UnimplementedAdminGrowthLevelServiceServer struct{}
|
||||
|
||||
func (UnimplementedAdminGrowthLevelServiceServer) ListLevelConfig(context.Context, *ListLevelConfigRequest) (*ListLevelConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListLevelConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListLevelConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminGrowthLevelServiceServer) UpsertLevelTrack(context.Context, *UpsertLevelTrackRequest) (*UpsertLevelTrackResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpsertLevelTrack not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpsertLevelTrack not implemented")
|
||||
}
|
||||
func (UnimplementedAdminGrowthLevelServiceServer) UpsertLevelRule(context.Context, *UpsertLevelRuleRequest) (*UpsertLevelRuleResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpsertLevelRule not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpsertLevelRule not implemented")
|
||||
}
|
||||
func (UnimplementedAdminGrowthLevelServiceServer) UpsertLevelTier(context.Context, *UpsertLevelTierRequest) (*UpsertLevelTierResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpsertLevelTier not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpsertLevelTier not implemented")
|
||||
}
|
||||
func (UnimplementedAdminGrowthLevelServiceServer) mustEmbedUnimplementedAdminGrowthLevelServiceServer() {
|
||||
}
|
||||
@ -5697,7 +5697,7 @@ type UnsafeAdminGrowthLevelServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAdminGrowthLevelServiceServer(s grpc.ServiceRegistrar, srv AdminGrowthLevelServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAdminGrowthLevelServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAdminGrowthLevelServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -5869,10 +5869,10 @@ type AdminAchievementServiceServer interface {
|
||||
type UnimplementedAdminAchievementServiceServer struct{}
|
||||
|
||||
func (UnimplementedAdminAchievementServiceServer) ListAchievementDefinitions(context.Context, *ListAchievementsRequest) (*ListAchievementsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListAchievementDefinitions not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListAchievementDefinitions not implemented")
|
||||
}
|
||||
func (UnimplementedAdminAchievementServiceServer) UpsertAchievementDefinition(context.Context, *UpsertAchievementDefinitionRequest) (*UpsertAchievementDefinitionResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpsertAchievementDefinition not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpsertAchievementDefinition not implemented")
|
||||
}
|
||||
func (UnimplementedAdminAchievementServiceServer) mustEmbedUnimplementedAdminAchievementServiceServer() {
|
||||
}
|
||||
@ -5886,7 +5886,7 @@ type UnsafeAdminAchievementServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAdminAchievementServiceServer(s grpc.ServiceRegistrar, srv AdminAchievementServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAdminAchievementServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAdminAchievementServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -6053,19 +6053,19 @@ type AdminLuckyGiftServiceServer interface {
|
||||
type UnimplementedAdminLuckyGiftServiceServer struct{}
|
||||
|
||||
func (UnimplementedAdminLuckyGiftServiceServer) GetLuckyGiftConfig(context.Context, *GetLuckyGiftConfigRequest) (*GetLuckyGiftConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetLuckyGiftConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetLuckyGiftConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminLuckyGiftServiceServer) UpsertLuckyGiftConfig(context.Context, *UpsertLuckyGiftConfigRequest) (*UpsertLuckyGiftConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpsertLuckyGiftConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpsertLuckyGiftConfig not implemented")
|
||||
}
|
||||
func (UnimplementedAdminLuckyGiftServiceServer) ListLuckyGiftConfigs(context.Context, *ListLuckyGiftConfigsRequest) (*ListLuckyGiftConfigsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListLuckyGiftConfigs not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListLuckyGiftConfigs not implemented")
|
||||
}
|
||||
func (UnimplementedAdminLuckyGiftServiceServer) ListLuckyGiftDraws(context.Context, *ListLuckyGiftDrawsRequest) (*ListLuckyGiftDrawsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListLuckyGiftDraws not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListLuckyGiftDraws not implemented")
|
||||
}
|
||||
func (UnimplementedAdminLuckyGiftServiceServer) GetLuckyGiftDrawSummary(context.Context, *GetLuckyGiftDrawSummaryRequest) (*GetLuckyGiftDrawSummaryResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetLuckyGiftDrawSummary not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetLuckyGiftDrawSummary not implemented")
|
||||
}
|
||||
func (UnimplementedAdminLuckyGiftServiceServer) mustEmbedUnimplementedAdminLuckyGiftServiceServer() {}
|
||||
func (UnimplementedAdminLuckyGiftServiceServer) testEmbeddedByValue() {}
|
||||
@ -6078,7 +6078,7 @@ type UnsafeAdminLuckyGiftServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAdminLuckyGiftServiceServer(s grpc.ServiceRegistrar, srv AdminLuckyGiftServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAdminLuckyGiftServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAdminLuckyGiftServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -170,6 +170,8 @@ message RoomGiftSent {
|
||||
bool is_robot_gift = 20;
|
||||
// synthetic_lucky_gift 标记幸运礼物只用于房间表现,不写真实抽奖流水、不扣真实奖池、不发真实奖励。
|
||||
bool synthetic_lucky_gift = 21;
|
||||
// real_room_robot_gift 标记真人房机器人送出的真实热度礼物,用于 Databi 单独统计机器人投放价值。
|
||||
bool real_room_robot_gift = 22;
|
||||
}
|
||||
|
||||
// RoomRobotLuckyGiftDrawn 是机器人房间专用幸运礼物展示事件。
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.6.2
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v7.35.0
|
||||
// source: proto/game/v1/game.proto
|
||||
|
||||
@ -271,55 +271,55 @@ type GameAppServiceServer interface {
|
||||
type UnimplementedGameAppServiceServer struct{}
|
||||
|
||||
func (UnimplementedGameAppServiceServer) ListGames(context.Context, *ListGamesRequest) (*ListGamesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListGames not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListGames not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) ListRecentGames(context.Context, *ListRecentGamesRequest) (*ListGamesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRecentGames not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRecentGames not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) ListExploreWinners(context.Context, *ListExploreWinnersRequest) (*ListExploreWinnersResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListExploreWinners not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListExploreWinners not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) GetBridgeScript(context.Context, *GetBridgeScriptRequest) (*GetBridgeScriptResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetBridgeScript not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetBridgeScript not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) LaunchGame(context.Context, *LaunchGameRequest) (*LaunchGameResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method LaunchGame not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method LaunchGame not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) GetDiceConfig(context.Context, *GetDiceConfigRequest) (*DiceConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetDiceConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetDiceConfig not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) MatchDice(context.Context, *MatchDiceRequest) (*DiceMatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method MatchDice not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method MatchDice not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) CreateDiceMatch(context.Context, *CreateDiceMatchRequest) (*DiceMatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateDiceMatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateDiceMatch not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) JoinDiceMatch(context.Context, *JoinDiceMatchRequest) (*DiceMatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method JoinDiceMatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method JoinDiceMatch not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) GetDiceMatch(context.Context, *GetDiceMatchRequest) (*DiceMatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetDiceMatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetDiceMatch not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) RollDiceMatch(context.Context, *RollDiceMatchRequest) (*DiceMatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RollDiceMatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RollDiceMatch not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) CancelDiceMatch(context.Context, *CancelDiceMatchRequest) (*DiceMatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CancelDiceMatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CancelDiceMatch not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) GetRoomRPSConfig(context.Context, *GetRoomRPSConfigRequest) (*RoomRPSConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetRoomRPSConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRoomRPSConfig not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) ListRoomRPSChallenges(context.Context, *ListRoomRPSChallengesRequest) (*ListRoomRPSChallengesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRoomRPSChallenges not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRoomRPSChallenges not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) CreateRoomRPSChallenge(context.Context, *CreateRoomRPSChallengeRequest) (*RoomRPSChallengeResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateRoomRPSChallenge not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateRoomRPSChallenge not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) AcceptRoomRPSChallenge(context.Context, *AcceptRoomRPSChallengeRequest) (*RoomRPSChallengeResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AcceptRoomRPSChallenge not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AcceptRoomRPSChallenge not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) GetRoomRPSChallenge(context.Context, *GetRoomRPSChallengeRequest) (*RoomRPSChallengeResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetRoomRPSChallenge not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRoomRPSChallenge not implemented")
|
||||
}
|
||||
func (UnimplementedGameAppServiceServer) mustEmbedUnimplementedGameAppServiceServer() {}
|
||||
func (UnimplementedGameAppServiceServer) testEmbeddedByValue() {}
|
||||
@ -332,7 +332,7 @@ type UnsafeGameAppServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterGameAppServiceServer(s grpc.ServiceRegistrar, srv GameAppServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedGameAppServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedGameAppServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -773,7 +773,7 @@ type GameCallbackServiceServer interface {
|
||||
type UnimplementedGameCallbackServiceServer struct{}
|
||||
|
||||
func (UnimplementedGameCallbackServiceServer) HandleCallback(context.Context, *CallbackRequest) (*CallbackResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method HandleCallback not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method HandleCallback not implemented")
|
||||
}
|
||||
func (UnimplementedGameCallbackServiceServer) mustEmbedUnimplementedGameCallbackServiceServer() {}
|
||||
func (UnimplementedGameCallbackServiceServer) testEmbeddedByValue() {}
|
||||
@ -786,7 +786,7 @@ type UnsafeGameCallbackServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterGameCallbackServiceServer(s grpc.ServiceRegistrar, srv GameCallbackServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedGameCallbackServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedGameCallbackServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -879,7 +879,7 @@ type GameCronServiceServer interface {
|
||||
type UnimplementedGameCronServiceServer struct{}
|
||||
|
||||
func (UnimplementedGameCronServiceServer) ProcessLevelEventOutboxBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessLevelEventOutboxBatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessLevelEventOutboxBatch not implemented")
|
||||
}
|
||||
func (UnimplementedGameCronServiceServer) mustEmbedUnimplementedGameCronServiceServer() {}
|
||||
func (UnimplementedGameCronServiceServer) testEmbeddedByValue() {}
|
||||
@ -892,7 +892,7 @@ type UnsafeGameCronServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterGameCronServiceServer(s grpc.ServiceRegistrar, srv GameCronServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedGameCronServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedGameCronServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -1267,73 +1267,73 @@ type GameAdminServiceServer interface {
|
||||
type UnimplementedGameAdminServiceServer struct{}
|
||||
|
||||
func (UnimplementedGameAdminServiceServer) ListPlatforms(context.Context, *ListPlatformsRequest) (*ListPlatformsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListPlatforms not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListPlatforms not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) UpsertPlatform(context.Context, *UpsertPlatformRequest) (*PlatformResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpsertPlatform not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpsertPlatform not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) ListCatalog(context.Context, *ListCatalogRequest) (*ListCatalogResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListCatalog not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListCatalog not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) UpsertCatalog(context.Context, *UpsertCatalogRequest) (*CatalogResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpsertCatalog not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpsertCatalog not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) SetGameStatus(context.Context, *SetGameStatusRequest) (*CatalogResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetGameStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetGameStatus not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) DeleteCatalog(context.Context, *DeleteCatalogRequest) (*DeleteCatalogResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method DeleteCatalog not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeleteCatalog not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) ListSelfGames(context.Context, *ListSelfGamesRequest) (*ListSelfGamesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListSelfGames not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListSelfGames not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) UpdateDiceConfig(context.Context, *UpdateDiceConfigRequest) (*DiceConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateDiceConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateDiceConfig not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) GetSelfGameNewUserPolicy(context.Context, *GetSelfGameNewUserPolicyRequest) (*SelfGameNewUserPolicyResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetSelfGameNewUserPolicy not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetSelfGameNewUserPolicy not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) UpdateSelfGameNewUserPolicy(context.Context, *UpdateSelfGameNewUserPolicyRequest) (*SelfGameNewUserPolicyResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateSelfGameNewUserPolicy not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateSelfGameNewUserPolicy not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) ListSelfGameStakePools(context.Context, *ListSelfGameStakePoolsRequest) (*ListSelfGameStakePoolsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListSelfGameStakePools not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListSelfGameStakePools not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) UpdateSelfGameStakePool(context.Context, *UpdateSelfGameStakePoolRequest) (*SelfGameStakePoolResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateSelfGameStakePool not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateSelfGameStakePool not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) AdjustSelfGameStakePool(context.Context, *AdjustSelfGameStakePoolRequest) (*AdjustSelfGameStakePoolResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdjustSelfGameStakePool not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdjustSelfGameStakePool not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) ListDiceRobots(context.Context, *ListDiceRobotsRequest) (*ListDiceRobotsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListDiceRobots not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListDiceRobots not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) RegisterDiceRobots(context.Context, *RegisterDiceRobotsRequest) (*RegisterDiceRobotsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RegisterDiceRobots not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RegisterDiceRobots not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) SetDiceRobotStatus(context.Context, *SetDiceRobotStatusRequest) (*DiceRobotResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetDiceRobotStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetDiceRobotStatus not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) DeleteDiceRobot(context.Context, *DeleteDiceRobotRequest) (*DeleteDiceRobotResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method DeleteDiceRobot not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeleteDiceRobot not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) GetRoomRPSConfig(context.Context, *GetRoomRPSConfigRequest) (*RoomRPSConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetRoomRPSConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRoomRPSConfig not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) UpdateRoomRPSConfig(context.Context, *UpdateRoomRPSConfigRequest) (*RoomRPSConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateRoomRPSConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateRoomRPSConfig not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) ListRoomRPSChallenges(context.Context, *ListRoomRPSChallengesRequest) (*ListRoomRPSChallengesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRoomRPSChallenges not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRoomRPSChallenges not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) GetRoomRPSChallenge(context.Context, *GetRoomRPSChallengeRequest) (*RoomRPSChallengeResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetRoomRPSChallenge not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRoomRPSChallenge not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) RetryRoomRPSSettlement(context.Context, *RetryRoomRPSSettlementRequest) (*RoomRPSChallengeResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RetryRoomRPSSettlement not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RetryRoomRPSSettlement not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) ExpireRoomRPSChallenge(context.Context, *ExpireRoomRPSChallengeRequest) (*RoomRPSChallengeResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ExpireRoomRPSChallenge not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ExpireRoomRPSChallenge not implemented")
|
||||
}
|
||||
func (UnimplementedGameAdminServiceServer) mustEmbedUnimplementedGameAdminServiceServer() {}
|
||||
func (UnimplementedGameAdminServiceServer) testEmbeddedByValue() {}
|
||||
@ -1346,7 +1346,7 @@ type UnsafeGameAdminServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterGameAdminServiceServer(s grpc.ServiceRegistrar, srv GameAdminServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedGameAdminServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedGameAdminServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.11
|
||||
// protoc-gen-go v1.35.1
|
||||
// protoc v7.35.0
|
||||
// source: proto/robot/v1/robot.proto
|
||||
|
||||
@ -11,7 +11,6 @@ import (
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -23,14 +22,15 @@ const (
|
||||
|
||||
// RequestMeta 是 robot-service 内部 RPC 的租户和追踪上下文;不要把 app_code 放到业务字段里绕过统一鉴权链路。
|
||||
type RequestMeta struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"`
|
||||
Caller string `protobuf:"bytes,2,opt,name=caller,proto3" json:"caller,omitempty"`
|
||||
ActorUserId int64 `protobuf:"varint,3,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"`
|
||||
SentAtMs int64 `protobuf:"varint,4,opt,name=sent_at_ms,json=sentAtMs,proto3" json:"sent_at_ms,omitempty"`
|
||||
AppCode string `protobuf:"bytes,5,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"`
|
||||
Caller string `protobuf:"bytes,2,opt,name=caller,proto3" json:"caller,omitempty"`
|
||||
ActorUserId int64 `protobuf:"varint,3,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"`
|
||||
SentAtMs int64 `protobuf:"varint,4,opt,name=sent_at_ms,json=sentAtMs,proto3" json:"sent_at_ms,omitempty"`
|
||||
AppCode string `protobuf:"bytes,5,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RequestMeta) Reset() {
|
||||
@ -99,20 +99,21 @@ func (x *RequestMeta) GetAppCode() string {
|
||||
}
|
||||
|
||||
type Robot struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"`
|
||||
RobotScope string `protobuf:"bytes,2,opt,name=robot_scope,json=robotScope,proto3" json:"robot_scope,omitempty"`
|
||||
GameId string `protobuf:"bytes,3,opt,name=game_id,json=gameId,proto3" json:"game_id,omitempty"`
|
||||
RoomScene string `protobuf:"bytes,4,opt,name=room_scene,json=roomScene,proto3" json:"room_scene,omitempty"`
|
||||
UserId int64 `protobuf:"varint,5,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"`
|
||||
CreatedByAdminId int64 `protobuf:"varint,7,opt,name=created_by_admin_id,json=createdByAdminId,proto3" json:"created_by_admin_id,omitempty"`
|
||||
CreatedAtMs int64 `protobuf:"varint,8,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"`
|
||||
UpdatedAtMs int64 `protobuf:"varint,9,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"`
|
||||
LastUsedAtMs int64 `protobuf:"varint,10,opt,name=last_used_at_ms,json=lastUsedAtMs,proto3" json:"last_used_at_ms,omitempty"`
|
||||
UsedCount int64 `protobuf:"varint,11,opt,name=used_count,json=usedCount,proto3" json:"used_count,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"`
|
||||
RobotScope string `protobuf:"bytes,2,opt,name=robot_scope,json=robotScope,proto3" json:"robot_scope,omitempty"`
|
||||
GameId string `protobuf:"bytes,3,opt,name=game_id,json=gameId,proto3" json:"game_id,omitempty"`
|
||||
RoomScene string `protobuf:"bytes,4,opt,name=room_scene,json=roomScene,proto3" json:"room_scene,omitempty"`
|
||||
UserId int64 `protobuf:"varint,5,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"`
|
||||
CreatedByAdminId int64 `protobuf:"varint,7,opt,name=created_by_admin_id,json=createdByAdminId,proto3" json:"created_by_admin_id,omitempty"`
|
||||
CreatedAtMs int64 `protobuf:"varint,8,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"`
|
||||
UpdatedAtMs int64 `protobuf:"varint,9,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"`
|
||||
LastUsedAtMs int64 `protobuf:"varint,10,opt,name=last_used_at_ms,json=lastUsedAtMs,proto3" json:"last_used_at_ms,omitempty"`
|
||||
UsedCount int64 `protobuf:"varint,11,opt,name=used_count,json=usedCount,proto3" json:"used_count,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Robot) Reset() {
|
||||
@ -223,14 +224,15 @@ func (x *Robot) GetUsedCount() int64 {
|
||||
}
|
||||
|
||||
type ListGameRobotsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
GameId string `protobuf:"bytes,2,opt,name=game_id,json=gameId,proto3" json:"game_id,omitempty"`
|
||||
Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
|
||||
PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"`
|
||||
Cursor string `protobuf:"bytes,5,opt,name=cursor,proto3" json:"cursor,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
GameId string `protobuf:"bytes,2,opt,name=game_id,json=gameId,proto3" json:"game_id,omitempty"`
|
||||
Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
|
||||
PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"`
|
||||
Cursor string `protobuf:"bytes,5,opt,name=cursor,proto3" json:"cursor,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ListGameRobotsRequest) Reset() {
|
||||
@ -299,12 +301,13 @@ func (x *ListGameRobotsRequest) GetCursor() string {
|
||||
}
|
||||
|
||||
type ListGameRobotsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Robots []*Robot `protobuf:"bytes,1,rep,name=robots,proto3" json:"robots,omitempty"`
|
||||
NextCursor string `protobuf:"bytes,2,opt,name=next_cursor,json=nextCursor,proto3" json:"next_cursor,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Robots []*Robot `protobuf:"bytes,1,rep,name=robots,proto3" json:"robots,omitempty"`
|
||||
NextCursor string `protobuf:"bytes,2,opt,name=next_cursor,json=nextCursor,proto3" json:"next_cursor,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ListGameRobotsResponse) Reset() {
|
||||
@ -359,12 +362,13 @@ func (x *ListGameRobotsResponse) GetServerTimeMs() int64 {
|
||||
}
|
||||
|
||||
type RegisterGameRobotsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
GameId string `protobuf:"bytes,2,opt,name=game_id,json=gameId,proto3" json:"game_id,omitempty"`
|
||||
UserIds []int64 `protobuf:"varint,3,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
GameId string `protobuf:"bytes,2,opt,name=game_id,json=gameId,proto3" json:"game_id,omitempty"`
|
||||
UserIds []int64 `protobuf:"varint,3,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RegisterGameRobotsRequest) Reset() {
|
||||
@ -419,11 +423,12 @@ func (x *RegisterGameRobotsRequest) GetUserIds() []int64 {
|
||||
}
|
||||
|
||||
type RegisterGameRobotsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Robots []*Robot `protobuf:"bytes,1,rep,name=robots,proto3" json:"robots,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Robots []*Robot `protobuf:"bytes,1,rep,name=robots,proto3" json:"robots,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RegisterGameRobotsResponse) Reset() {
|
||||
@ -471,14 +476,15 @@ func (x *RegisterGameRobotsResponse) GetServerTimeMs() int64 {
|
||||
}
|
||||
|
||||
type PickGameRobotRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
GameId string `protobuf:"bytes,2,opt,name=game_id,json=gameId,proto3" json:"game_id,omitempty"`
|
||||
MatchId string `protobuf:"bytes,3,opt,name=match_id,json=matchId,proto3" json:"match_id,omitempty"`
|
||||
SelectedAtMs int64 `protobuf:"varint,4,opt,name=selected_at_ms,json=selectedAtMs,proto3" json:"selected_at_ms,omitempty"`
|
||||
ExcludeUserIds []int64 `protobuf:"varint,5,rep,packed,name=exclude_user_ids,json=excludeUserIds,proto3" json:"exclude_user_ids,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
GameId string `protobuf:"bytes,2,opt,name=game_id,json=gameId,proto3" json:"game_id,omitempty"`
|
||||
MatchId string `protobuf:"bytes,3,opt,name=match_id,json=matchId,proto3" json:"match_id,omitempty"`
|
||||
SelectedAtMs int64 `protobuf:"varint,4,opt,name=selected_at_ms,json=selectedAtMs,proto3" json:"selected_at_ms,omitempty"`
|
||||
ExcludeUserIds []int64 `protobuf:"varint,5,rep,packed,name=exclude_user_ids,json=excludeUserIds,proto3" json:"exclude_user_ids,omitempty"`
|
||||
}
|
||||
|
||||
func (x *PickGameRobotRequest) Reset() {
|
||||
@ -547,11 +553,12 @@ func (x *PickGameRobotRequest) GetExcludeUserIds() []int64 {
|
||||
}
|
||||
|
||||
type GameRobotResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Robot *Robot `protobuf:"bytes,1,opt,name=robot,proto3" json:"robot,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Robot *Robot `protobuf:"bytes,1,opt,name=robot,proto3" json:"robot,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
}
|
||||
|
||||
func (x *GameRobotResponse) Reset() {
|
||||
@ -599,13 +606,14 @@ func (x *GameRobotResponse) GetServerTimeMs() int64 {
|
||||
}
|
||||
|
||||
type SetGameRobotStatusRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
GameId string `protobuf:"bytes,2,opt,name=game_id,json=gameId,proto3" json:"game_id,omitempty"`
|
||||
UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
GameId string `protobuf:"bytes,2,opt,name=game_id,json=gameId,proto3" json:"game_id,omitempty"`
|
||||
UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SetGameRobotStatusRequest) Reset() {
|
||||
@ -667,12 +675,13 @@ func (x *SetGameRobotStatusRequest) GetStatus() string {
|
||||
}
|
||||
|
||||
type DeleteGameRobotRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
GameId string `protobuf:"bytes,2,opt,name=game_id,json=gameId,proto3" json:"game_id,omitempty"`
|
||||
UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
GameId string `protobuf:"bytes,2,opt,name=game_id,json=gameId,proto3" json:"game_id,omitempty"`
|
||||
UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
}
|
||||
|
||||
func (x *DeleteGameRobotRequest) Reset() {
|
||||
@ -727,11 +736,12 @@ func (x *DeleteGameRobotRequest) GetUserId() int64 {
|
||||
}
|
||||
|
||||
type DeleteGameRobotResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
}
|
||||
|
||||
func (x *DeleteGameRobotResponse) Reset() {
|
||||
@ -779,14 +789,15 @@ func (x *DeleteGameRobotResponse) GetServerTimeMs() int64 {
|
||||
}
|
||||
|
||||
type ListRoomRobotsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
RoomScene string `protobuf:"bytes,2,opt,name=room_scene,json=roomScene,proto3" json:"room_scene,omitempty"`
|
||||
Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
|
||||
PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"`
|
||||
Cursor string `protobuf:"bytes,5,opt,name=cursor,proto3" json:"cursor,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
RoomScene string `protobuf:"bytes,2,opt,name=room_scene,json=roomScene,proto3" json:"room_scene,omitempty"`
|
||||
Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
|
||||
PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"`
|
||||
Cursor string `protobuf:"bytes,5,opt,name=cursor,proto3" json:"cursor,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ListRoomRobotsRequest) Reset() {
|
||||
@ -855,12 +866,13 @@ func (x *ListRoomRobotsRequest) GetCursor() string {
|
||||
}
|
||||
|
||||
type ListRoomRobotsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Robots []*Robot `protobuf:"bytes,1,rep,name=robots,proto3" json:"robots,omitempty"`
|
||||
NextCursor string `protobuf:"bytes,2,opt,name=next_cursor,json=nextCursor,proto3" json:"next_cursor,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Robots []*Robot `protobuf:"bytes,1,rep,name=robots,proto3" json:"robots,omitempty"`
|
||||
NextCursor string `protobuf:"bytes,2,opt,name=next_cursor,json=nextCursor,proto3" json:"next_cursor,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ListRoomRobotsResponse) Reset() {
|
||||
@ -915,12 +927,13 @@ func (x *ListRoomRobotsResponse) GetServerTimeMs() int64 {
|
||||
}
|
||||
|
||||
type RegisterRoomRobotsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
RoomScene string `protobuf:"bytes,2,opt,name=room_scene,json=roomScene,proto3" json:"room_scene,omitempty"`
|
||||
UserIds []int64 `protobuf:"varint,3,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
RoomScene string `protobuf:"bytes,2,opt,name=room_scene,json=roomScene,proto3" json:"room_scene,omitempty"`
|
||||
UserIds []int64 `protobuf:"varint,3,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RegisterRoomRobotsRequest) Reset() {
|
||||
@ -975,11 +988,12 @@ func (x *RegisterRoomRobotsRequest) GetUserIds() []int64 {
|
||||
}
|
||||
|
||||
type RegisterRoomRobotsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Robots []*Robot `protobuf:"bytes,1,rep,name=robots,proto3" json:"robots,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Robots []*Robot `protobuf:"bytes,1,rep,name=robots,proto3" json:"robots,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RegisterRoomRobotsResponse) Reset() {
|
||||
@ -1027,13 +1041,14 @@ func (x *RegisterRoomRobotsResponse) GetServerTimeMs() int64 {
|
||||
}
|
||||
|
||||
type SetRoomRobotStatusRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
RoomScene string `protobuf:"bytes,2,opt,name=room_scene,json=roomScene,proto3" json:"room_scene,omitempty"`
|
||||
UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
RoomScene string `protobuf:"bytes,2,opt,name=room_scene,json=roomScene,proto3" json:"room_scene,omitempty"`
|
||||
UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SetRoomRobotStatusRequest) Reset() {
|
||||
@ -1095,12 +1110,13 @@ func (x *SetRoomRobotStatusRequest) GetStatus() string {
|
||||
}
|
||||
|
||||
type DeleteRoomRobotRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
RoomScene string `protobuf:"bytes,2,opt,name=room_scene,json=roomScene,proto3" json:"room_scene,omitempty"`
|
||||
UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
RoomScene string `protobuf:"bytes,2,opt,name=room_scene,json=roomScene,proto3" json:"room_scene,omitempty"`
|
||||
UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
}
|
||||
|
||||
func (x *DeleteRoomRobotRequest) Reset() {
|
||||
@ -1155,11 +1171,12 @@ func (x *DeleteRoomRobotRequest) GetUserId() int64 {
|
||||
}
|
||||
|
||||
type DeleteRoomRobotResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
}
|
||||
|
||||
func (x *DeleteRoomRobotResponse) Reset() {
|
||||
@ -1207,13 +1224,14 @@ func (x *DeleteRoomRobotResponse) GetServerTimeMs() int64 {
|
||||
}
|
||||
|
||||
type PickRoomRobotRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
RoomScene string `protobuf:"bytes,2,opt,name=room_scene,json=roomScene,proto3" json:"room_scene,omitempty"`
|
||||
RoomId string `protobuf:"bytes,3,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"`
|
||||
SelectedAtMs int64 `protobuf:"varint,4,opt,name=selected_at_ms,json=selectedAtMs,proto3" json:"selected_at_ms,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
RoomScene string `protobuf:"bytes,2,opt,name=room_scene,json=roomScene,proto3" json:"room_scene,omitempty"`
|
||||
RoomId string `protobuf:"bytes,3,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"`
|
||||
SelectedAtMs int64 `protobuf:"varint,4,opt,name=selected_at_ms,json=selectedAtMs,proto3" json:"selected_at_ms,omitempty"`
|
||||
}
|
||||
|
||||
func (x *PickRoomRobotRequest) Reset() {
|
||||
@ -1275,11 +1293,12 @@ func (x *PickRoomRobotRequest) GetSelectedAtMs() int64 {
|
||||
}
|
||||
|
||||
type RoomRobotResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Robot *Robot `protobuf:"bytes,1,opt,name=robot,proto3" json:"robot,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Robot *Robot `protobuf:"bytes,1,opt,name=robot,proto3" json:"robot,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RoomRobotResponse) Reset() {
|
||||
@ -1328,136 +1347,276 @@ func (x *RoomRobotResponse) GetServerTimeMs() int64 {
|
||||
|
||||
var File_proto_robot_v1_robot_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_proto_robot_v1_robot_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x1aproto/robot/v1/robot.proto\x12\x0ehyapp.robot.v1\"\xa1\x01\n" +
|
||||
"\vRequestMeta\x12\x1d\n" +
|
||||
"\n" +
|
||||
"request_id\x18\x01 \x01(\tR\trequestId\x12\x16\n" +
|
||||
"\x06caller\x18\x02 \x01(\tR\x06caller\x12\"\n" +
|
||||
"\ractor_user_id\x18\x03 \x01(\x03R\vactorUserId\x12\x1c\n" +
|
||||
"\n" +
|
||||
"sent_at_ms\x18\x04 \x01(\x03R\bsentAtMs\x12\x19\n" +
|
||||
"\bapp_code\x18\x05 \x01(\tR\aappCode\"\xe9\x02\n" +
|
||||
"\x05Robot\x12\x19\n" +
|
||||
"\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x1f\n" +
|
||||
"\vrobot_scope\x18\x02 \x01(\tR\n" +
|
||||
"robotScope\x12\x17\n" +
|
||||
"\agame_id\x18\x03 \x01(\tR\x06gameId\x12\x1d\n" +
|
||||
"\n" +
|
||||
"room_scene\x18\x04 \x01(\tR\troomScene\x12\x17\n" +
|
||||
"\auser_id\x18\x05 \x01(\x03R\x06userId\x12\x16\n" +
|
||||
"\x06status\x18\x06 \x01(\tR\x06status\x12-\n" +
|
||||
"\x13created_by_admin_id\x18\a \x01(\x03R\x10createdByAdminId\x12\"\n" +
|
||||
"\rcreated_at_ms\x18\b \x01(\x03R\vcreatedAtMs\x12\"\n" +
|
||||
"\rupdated_at_ms\x18\t \x01(\x03R\vupdatedAtMs\x12%\n" +
|
||||
"\x0flast_used_at_ms\x18\n" +
|
||||
" \x01(\x03R\flastUsedAtMs\x12\x1d\n" +
|
||||
"\n" +
|
||||
"used_count\x18\v \x01(\x03R\tusedCount\"\xae\x01\n" +
|
||||
"\x15ListGameRobotsRequest\x12/\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1b.hyapp.robot.v1.RequestMetaR\x04meta\x12\x17\n" +
|
||||
"\agame_id\x18\x02 \x01(\tR\x06gameId\x12\x16\n" +
|
||||
"\x06status\x18\x03 \x01(\tR\x06status\x12\x1b\n" +
|
||||
"\tpage_size\x18\x04 \x01(\x05R\bpageSize\x12\x16\n" +
|
||||
"\x06cursor\x18\x05 \x01(\tR\x06cursor\"\x8e\x01\n" +
|
||||
"\x16ListGameRobotsResponse\x12-\n" +
|
||||
"\x06robots\x18\x01 \x03(\v2\x15.hyapp.robot.v1.RobotR\x06robots\x12\x1f\n" +
|
||||
"\vnext_cursor\x18\x02 \x01(\tR\n" +
|
||||
"nextCursor\x12$\n" +
|
||||
"\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\x80\x01\n" +
|
||||
"\x19RegisterGameRobotsRequest\x12/\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1b.hyapp.robot.v1.RequestMetaR\x04meta\x12\x17\n" +
|
||||
"\agame_id\x18\x02 \x01(\tR\x06gameId\x12\x19\n" +
|
||||
"\buser_ids\x18\x03 \x03(\x03R\auserIds\"q\n" +
|
||||
"\x1aRegisterGameRobotsResponse\x12-\n" +
|
||||
"\x06robots\x18\x01 \x03(\v2\x15.hyapp.robot.v1.RobotR\x06robots\x12$\n" +
|
||||
"\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xcb\x01\n" +
|
||||
"\x14PickGameRobotRequest\x12/\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1b.hyapp.robot.v1.RequestMetaR\x04meta\x12\x17\n" +
|
||||
"\agame_id\x18\x02 \x01(\tR\x06gameId\x12\x19\n" +
|
||||
"\bmatch_id\x18\x03 \x01(\tR\amatchId\x12$\n" +
|
||||
"\x0eselected_at_ms\x18\x04 \x01(\x03R\fselectedAtMs\x12(\n" +
|
||||
"\x10exclude_user_ids\x18\x05 \x03(\x03R\x0eexcludeUserIds\"f\n" +
|
||||
"\x11GameRobotResponse\x12+\n" +
|
||||
"\x05robot\x18\x01 \x01(\v2\x15.hyapp.robot.v1.RobotR\x05robot\x12$\n" +
|
||||
"\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\x96\x01\n" +
|
||||
"\x19SetGameRobotStatusRequest\x12/\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1b.hyapp.robot.v1.RequestMetaR\x04meta\x12\x17\n" +
|
||||
"\agame_id\x18\x02 \x01(\tR\x06gameId\x12\x17\n" +
|
||||
"\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x16\n" +
|
||||
"\x06status\x18\x04 \x01(\tR\x06status\"{\n" +
|
||||
"\x16DeleteGameRobotRequest\x12/\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1b.hyapp.robot.v1.RequestMetaR\x04meta\x12\x17\n" +
|
||||
"\agame_id\x18\x02 \x01(\tR\x06gameId\x12\x17\n" +
|
||||
"\auser_id\x18\x03 \x01(\x03R\x06userId\"Y\n" +
|
||||
"\x17DeleteGameRobotResponse\x12\x18\n" +
|
||||
"\adeleted\x18\x01 \x01(\bR\adeleted\x12$\n" +
|
||||
"\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xb4\x01\n" +
|
||||
"\x15ListRoomRobotsRequest\x12/\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1b.hyapp.robot.v1.RequestMetaR\x04meta\x12\x1d\n" +
|
||||
"\n" +
|
||||
"room_scene\x18\x02 \x01(\tR\troomScene\x12\x16\n" +
|
||||
"\x06status\x18\x03 \x01(\tR\x06status\x12\x1b\n" +
|
||||
"\tpage_size\x18\x04 \x01(\x05R\bpageSize\x12\x16\n" +
|
||||
"\x06cursor\x18\x05 \x01(\tR\x06cursor\"\x8e\x01\n" +
|
||||
"\x16ListRoomRobotsResponse\x12-\n" +
|
||||
"\x06robots\x18\x01 \x03(\v2\x15.hyapp.robot.v1.RobotR\x06robots\x12\x1f\n" +
|
||||
"\vnext_cursor\x18\x02 \x01(\tR\n" +
|
||||
"nextCursor\x12$\n" +
|
||||
"\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\x86\x01\n" +
|
||||
"\x19RegisterRoomRobotsRequest\x12/\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1b.hyapp.robot.v1.RequestMetaR\x04meta\x12\x1d\n" +
|
||||
"\n" +
|
||||
"room_scene\x18\x02 \x01(\tR\troomScene\x12\x19\n" +
|
||||
"\buser_ids\x18\x03 \x03(\x03R\auserIds\"q\n" +
|
||||
"\x1aRegisterRoomRobotsResponse\x12-\n" +
|
||||
"\x06robots\x18\x01 \x03(\v2\x15.hyapp.robot.v1.RobotR\x06robots\x12$\n" +
|
||||
"\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\x9c\x01\n" +
|
||||
"\x19SetRoomRobotStatusRequest\x12/\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1b.hyapp.robot.v1.RequestMetaR\x04meta\x12\x1d\n" +
|
||||
"\n" +
|
||||
"room_scene\x18\x02 \x01(\tR\troomScene\x12\x17\n" +
|
||||
"\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x16\n" +
|
||||
"\x06status\x18\x04 \x01(\tR\x06status\"\x81\x01\n" +
|
||||
"\x16DeleteRoomRobotRequest\x12/\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1b.hyapp.robot.v1.RequestMetaR\x04meta\x12\x1d\n" +
|
||||
"\n" +
|
||||
"room_scene\x18\x02 \x01(\tR\troomScene\x12\x17\n" +
|
||||
"\auser_id\x18\x03 \x01(\x03R\x06userId\"Y\n" +
|
||||
"\x17DeleteRoomRobotResponse\x12\x18\n" +
|
||||
"\adeleted\x18\x01 \x01(\bR\adeleted\x12$\n" +
|
||||
"\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xa5\x01\n" +
|
||||
"\x14PickRoomRobotRequest\x12/\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1b.hyapp.robot.v1.RequestMetaR\x04meta\x12\x1d\n" +
|
||||
"\n" +
|
||||
"room_scene\x18\x02 \x01(\tR\troomScene\x12\x17\n" +
|
||||
"\aroom_id\x18\x03 \x01(\tR\x06roomId\x12$\n" +
|
||||
"\x0eselected_at_ms\x18\x04 \x01(\x03R\fselectedAtMs\"f\n" +
|
||||
"\x11RoomRobotResponse\x12+\n" +
|
||||
"\x05robot\x18\x01 \x01(\v2\x15.hyapp.robot.v1.RobotR\x05robot\x12$\n" +
|
||||
"\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs2\x82\x04\n" +
|
||||
"\x10GameRobotService\x12_\n" +
|
||||
"\x0eListGameRobots\x12%.hyapp.robot.v1.ListGameRobotsRequest\x1a&.hyapp.robot.v1.ListGameRobotsResponse\x12k\n" +
|
||||
"\x12RegisterGameRobots\x12).hyapp.robot.v1.RegisterGameRobotsRequest\x1a*.hyapp.robot.v1.RegisterGameRobotsResponse\x12X\n" +
|
||||
"\rPickGameRobot\x12$.hyapp.robot.v1.PickGameRobotRequest\x1a!.hyapp.robot.v1.GameRobotResponse\x12b\n" +
|
||||
"\x12SetGameRobotStatus\x12).hyapp.robot.v1.SetGameRobotStatusRequest\x1a!.hyapp.robot.v1.GameRobotResponse\x12b\n" +
|
||||
"\x0fDeleteGameRobot\x12&.hyapp.robot.v1.DeleteGameRobotRequest\x1a'.hyapp.robot.v1.DeleteGameRobotResponse2\x82\x04\n" +
|
||||
"\x10RoomRobotService\x12_\n" +
|
||||
"\x0eListRoomRobots\x12%.hyapp.robot.v1.ListRoomRobotsRequest\x1a&.hyapp.robot.v1.ListRoomRobotsResponse\x12k\n" +
|
||||
"\x12RegisterRoomRobots\x12).hyapp.robot.v1.RegisterRoomRobotsRequest\x1a*.hyapp.robot.v1.RegisterRoomRobotsResponse\x12X\n" +
|
||||
"\rPickRoomRobot\x12$.hyapp.robot.v1.PickRoomRobotRequest\x1a!.hyapp.robot.v1.RoomRobotResponse\x12b\n" +
|
||||
"\x12SetRoomRobotStatus\x12).hyapp.robot.v1.SetRoomRobotStatusRequest\x1a!.hyapp.robot.v1.RoomRobotResponse\x12b\n" +
|
||||
"\x0fDeleteRoomRobot\x12&.hyapp.robot.v1.DeleteRoomRobotRequest\x1a'.hyapp.robot.v1.DeleteRoomRobotResponseB(Z&hyapp.local/api/proto/robot/v1;robotv1b\x06proto3"
|
||||
var file_proto_robot_v1_robot_proto_rawDesc = []byte{
|
||||
0x0a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2f, 0x76, 0x31,
|
||||
0x2f, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x68, 0x79,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x22, 0xa1, 0x01, 0x0a,
|
||||
0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a,
|
||||
0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x63,
|
||||
0x61, 0x6c, 0x6c, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x6c,
|
||||
0x6c, 0x65, 0x72, 0x12, 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, 0x1c, 0x0a, 0x0a, 0x73, 0x65, 0x6e, 0x74, 0x5f,
|
||||
0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x73, 0x65, 0x6e,
|
||||
0x74, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64,
|
||||
0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65,
|
||||
0x22, 0xe9, 0x02, 0x0a, 0x05, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70,
|
||||
0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70,
|
||||
0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x73,
|
||||
0x63, 0x6f, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x6f, 0x62, 0x6f,
|
||||
0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x69,
|
||||
0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12,
|
||||
0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x18, 0x04, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x65, 0x6e, 0x65, 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, 0x73, 0x74, 0x61, 0x74, 0x75,
|
||||
0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
|
||||
0x2d, 0x0a, 0x13, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x64,
|
||||
0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 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,
|
||||
0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74,
|
||||
0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74,
|
||||
0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x25, 0x0a, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75,
|
||||
0x73, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52,
|
||||
0x0c, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x73, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1d, 0x0a,
|
||||
0x0a, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28,
|
||||
0x03, 0x52, 0x09, 0x75, 0x73, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xae, 0x01, 0x0a,
|
||||
0x15, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62,
|
||||
0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74,
|
||||
0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x61, 0x6d, 0x65, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x61, 0x6d, 0x65, 0x49, 0x64,
|
||||
0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 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, 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18,
|
||||
0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x22, 0x8e, 0x01,
|
||||
0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x72, 0x6f, 0x62, 0x6f,
|
||||
0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70,
|
||||
0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52,
|
||||
0x06, 0x72, 0x6f, 0x62, 0x6f, 0x74, 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, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76,
|
||||
0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
|
||||
0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x80,
|
||||
0x01, 0x0a, 0x19, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x47, 0x61, 0x6d, 0x65, 0x52,
|
||||
0x6f, 0x62, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04,
|
||||
0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61,
|
||||
0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a,
|
||||
0x07, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
|
||||
0x67, 0x61, 0x6d, 0x65, 0x49, 0x64, 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, 0x71, 0x0a, 0x1a, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x47, 0x61, 0x6d,
|
||||
0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x2d, 0x0a, 0x06, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||
0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x06, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x12, 0x24,
|
||||
0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69,
|
||||
0x6d, 0x65, 0x4d, 0x73, 0x22, 0xcb, 0x01, 0x0a, 0x14, 0x50, 0x69, 0x63, 0x6b, 0x47, 0x61, 0x6d,
|
||||
0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a,
|
||||
0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17,
|
||||
0x0a, 0x07, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x06, 0x67, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x74, 0x63, 0x68,
|
||||
0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68,
|
||||
0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x61,
|
||||
0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x65,
|
||||
0x63, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x63, 0x6c,
|
||||
0x75, 0x64, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03,
|
||||
0x28, 0x03, 0x52, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49,
|
||||
0x64, 0x73, 0x22, 0x66, 0x0a, 0x11, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x72, 0x6f, 0x62, 0x6f, 0x74,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72,
|
||||
0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x05, 0x72,
|
||||
0x6f, 0x62, 0x6f, 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, 0x96, 0x01, 0x0a, 0x19, 0x53,
|
||||
0x65, 0x74, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75,
|
||||
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72,
|
||||
0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d,
|
||||
0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x61, 0x6d,
|
||||
0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x61, 0x6d, 0x65,
|
||||
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, 0x16, 0x0a, 0x06, 0x73,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61,
|
||||
0x74, 0x75, 0x73, 0x22, 0x7b, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x61, 0x6d,
|
||||
0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a,
|
||||
0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17,
|
||||
0x0a, 0x07, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x06, 0x67, 0x61, 0x6d, 0x65, 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, 0x59, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f,
|
||||
0x62, 0x6f, 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, 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, 0x01, 0x0a, 0x15,
|
||||
0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f,
|
||||
0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61,
|
||||
0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x73,
|
||||
0x63, 0x65, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x6d,
|
||||
0x53, 0x63, 0x65, 0x6e, 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, 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, 0x16, 0x0a, 0x06, 0x63, 0x75,
|
||||
0x72, 0x73, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73,
|
||||
0x6f, 0x72, 0x22, 0x8e, 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52,
|
||||
0x6f, 0x62, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a,
|
||||
0x06, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e,
|
||||
0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52,
|
||||
0x6f, 0x62, 0x6f, 0x74, 0x52, 0x06, 0x72, 0x6f, 0x62, 0x6f, 0x74, 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, 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, 0x86, 0x01, 0x0a, 0x19, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
|
||||
0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65,
|
||||
0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x65, 0x6e, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x65, 0x6e,
|
||||
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, 0x71, 0x0a, 0x1a,
|
||||
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f,
|
||||
0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x72, 0x6f,
|
||||
0x62, 0x6f, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61,
|
||||
0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x62, 0x6f,
|
||||
0x74, 0x52, 0x06, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72,
|
||||
0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22,
|
||||
0x9c, 0x01, 0x0a, 0x19, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74,
|
||||
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a,
|
||||
0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x1d,
|
||||
0x0a, 0x0a, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x65, 0x6e, 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, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x81,
|
||||
0x01, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62,
|
||||
0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74,
|
||||
0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e,
|
||||
0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f,
|
||||
0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
|
||||
0x72, 0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x65, 0x6e, 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, 0x59, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d,
|
||||
0x52, 0x6f, 0x62, 0x6f, 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, 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, 0xa5, 0x01,
|
||||
0x0a, 0x14, 0x50, 0x69, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62,
|
||||
0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74,
|
||||
0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x6f, 0x6d, 0x5f,
|
||||
0x73, 0x63, 0x65, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x6f,
|
||||
0x6d, 0x53, 0x63, 0x65, 0x6e, 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, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d,
|
||||
0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65,
|
||||
0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0x66, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62,
|
||||
0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x72, 0x6f,
|
||||
0x62, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x79, 0x61, 0x70,
|
||||
0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x62, 0x6f, 0x74,
|
||||
0x52, 0x05, 0x72, 0x6f, 0x62, 0x6f, 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, 0x32, 0x82, 0x04,
|
||||
0x0a, 0x10, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69,
|
||||
0x63, 0x65, 0x12, 0x5f, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f,
|
||||
0x62, 0x6f, 0x74, 0x73, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62,
|
||||
0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f,
|
||||
0x62, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x12, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x47,
|
||||
0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70,
|
||||
0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73,
|
||||
0x74, 0x65, 0x72, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62,
|
||||
0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x47, 0x61,
|
||||
0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x12, 0x58, 0x0a, 0x0d, 0x50, 0x69, 0x63, 0x6b, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f,
|
||||
0x74, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x50, 0x69, 0x63, 0x6b, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e,
|
||||
0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62,
|
||||
0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x12, 0x53, 0x65,
|
||||
0x74, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x53, 0x65, 0x74, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x53, 0x74,
|
||||
0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x79,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x61, 0x6d,
|
||||
0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62,
|
||||
0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f,
|
||||
0x74, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62,
|
||||
0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70,
|
||||
0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74,
|
||||
0x65, 0x47, 0x61, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x32, 0x82, 0x04, 0x0a, 0x10, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74,
|
||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x52,
|
||||
0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70,
|
||||
0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52,
|
||||
0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x12, 0x52, 0x65, 0x67, 0x69,
|
||||
0x73, 0x74, 0x65, 0x72, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x12, 0x29,
|
||||
0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f,
|
||||
0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70,
|
||||
0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73,
|
||||
0x74, 0x65, 0x72, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x0d, 0x50, 0x69, 0x63, 0x6b, 0x52, 0x6f, 0x6f,
|
||||
0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72,
|
||||
0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x6d,
|
||||
0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68,
|
||||
0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f,
|
||||
0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x62, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x53,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f,
|
||||
0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f,
|
||||
0x62, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f,
|
||||
0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72,
|
||||
0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f,
|
||||
0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27,
|
||||
0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x28, 0x5a, 0x26, 0x68, 0x79, 0x61, 0x70, 0x70,
|
||||
0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x2f, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x76,
|
||||
0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_proto_robot_v1_robot_proto_rawDescOnce sync.Once
|
||||
file_proto_robot_v1_robot_proto_rawDescData []byte
|
||||
file_proto_robot_v1_robot_proto_rawDescData = file_proto_robot_v1_robot_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_proto_robot_v1_robot_proto_rawDescGZIP() []byte {
|
||||
file_proto_robot_v1_robot_proto_rawDescOnce.Do(func() {
|
||||
file_proto_robot_v1_robot_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_robot_v1_robot_proto_rawDesc), len(file_proto_robot_v1_robot_proto_rawDesc)))
|
||||
file_proto_robot_v1_robot_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_robot_v1_robot_proto_rawDescData)
|
||||
})
|
||||
return file_proto_robot_v1_robot_proto_rawDescData
|
||||
}
|
||||
@ -1538,7 +1697,7 @@ func file_proto_robot_v1_robot_proto_init() {
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_robot_v1_robot_proto_rawDesc), len(file_proto_robot_v1_robot_proto_rawDesc)),
|
||||
RawDescriptor: file_proto_robot_v1_robot_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 20,
|
||||
NumExtensions: 0,
|
||||
@ -1549,6 +1708,7 @@ func file_proto_robot_v1_robot_proto_init() {
|
||||
MessageInfos: file_proto_robot_v1_robot_proto_msgTypes,
|
||||
}.Build()
|
||||
File_proto_robot_v1_robot_proto = out.File
|
||||
file_proto_robot_v1_robot_proto_rawDesc = nil
|
||||
file_proto_robot_v1_robot_proto_goTypes = nil
|
||||
file_proto_robot_v1_robot_proto_depIdxs = nil
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.6.2
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v7.35.0
|
||||
// source: proto/robot/v1/robot.proto
|
||||
|
||||
@ -115,19 +115,19 @@ type GameRobotServiceServer interface {
|
||||
type UnimplementedGameRobotServiceServer struct{}
|
||||
|
||||
func (UnimplementedGameRobotServiceServer) ListGameRobots(context.Context, *ListGameRobotsRequest) (*ListGameRobotsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListGameRobots not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListGameRobots not implemented")
|
||||
}
|
||||
func (UnimplementedGameRobotServiceServer) RegisterGameRobots(context.Context, *RegisterGameRobotsRequest) (*RegisterGameRobotsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RegisterGameRobots not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RegisterGameRobots not implemented")
|
||||
}
|
||||
func (UnimplementedGameRobotServiceServer) PickGameRobot(context.Context, *PickGameRobotRequest) (*GameRobotResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method PickGameRobot not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PickGameRobot not implemented")
|
||||
}
|
||||
func (UnimplementedGameRobotServiceServer) SetGameRobotStatus(context.Context, *SetGameRobotStatusRequest) (*GameRobotResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetGameRobotStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetGameRobotStatus not implemented")
|
||||
}
|
||||
func (UnimplementedGameRobotServiceServer) DeleteGameRobot(context.Context, *DeleteGameRobotRequest) (*DeleteGameRobotResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method DeleteGameRobot not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeleteGameRobot not implemented")
|
||||
}
|
||||
func (UnimplementedGameRobotServiceServer) mustEmbedUnimplementedGameRobotServiceServer() {}
|
||||
func (UnimplementedGameRobotServiceServer) testEmbeddedByValue() {}
|
||||
@ -140,7 +140,7 @@ type UnsafeGameRobotServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterGameRobotServiceServer(s grpc.ServiceRegistrar, srv GameRobotServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedGameRobotServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedGameRobotServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -369,19 +369,19 @@ type RoomRobotServiceServer interface {
|
||||
type UnimplementedRoomRobotServiceServer struct{}
|
||||
|
||||
func (UnimplementedRoomRobotServiceServer) ListRoomRobots(context.Context, *ListRoomRobotsRequest) (*ListRoomRobotsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRoomRobots not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRoomRobots not implemented")
|
||||
}
|
||||
func (UnimplementedRoomRobotServiceServer) RegisterRoomRobots(context.Context, *RegisterRoomRobotsRequest) (*RegisterRoomRobotsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RegisterRoomRobots not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RegisterRoomRobots not implemented")
|
||||
}
|
||||
func (UnimplementedRoomRobotServiceServer) PickRoomRobot(context.Context, *PickRoomRobotRequest) (*RoomRobotResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method PickRoomRobot not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PickRoomRobot not implemented")
|
||||
}
|
||||
func (UnimplementedRoomRobotServiceServer) SetRoomRobotStatus(context.Context, *SetRoomRobotStatusRequest) (*RoomRobotResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetRoomRobotStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetRoomRobotStatus not implemented")
|
||||
}
|
||||
func (UnimplementedRoomRobotServiceServer) DeleteRoomRobot(context.Context, *DeleteRoomRobotRequest) (*DeleteRoomRobotResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method DeleteRoomRobot not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeleteRoomRobot not implemented")
|
||||
}
|
||||
func (UnimplementedRoomRobotServiceServer) mustEmbedUnimplementedRoomRobotServiceServer() {}
|
||||
func (UnimplementedRoomRobotServiceServer) testEmbeddedByValue() {}
|
||||
@ -394,7 +394,7 @@ type UnsafeRoomRobotServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterRoomRobotServiceServer(s grpc.ServiceRegistrar, srv RoomRobotServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedRoomRobotServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedRoomRobotServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -268,6 +268,59 @@ message AdminUpdateRoomSeatConfigResponse {
|
||||
int64 server_time_ms = 2;
|
||||
}
|
||||
|
||||
message AdminHumanRoomRobotCountryPool {
|
||||
string country_code = 1;
|
||||
repeated int64 robot_user_ids = 2;
|
||||
}
|
||||
|
||||
message AdminHumanRoomRobotConfig {
|
||||
string app_code = 1;
|
||||
bool enabled = 2;
|
||||
int32 candidate_room_max_online = 3;
|
||||
int32 room_full_stop_online = 4;
|
||||
int64 robot_stay_min_ms = 5;
|
||||
int64 robot_stay_max_ms = 6;
|
||||
int64 robot_replace_min_ms = 7;
|
||||
int64 robot_replace_max_ms = 8;
|
||||
int64 normal_gift_interval_ms = 9;
|
||||
repeated string gift_ids = 10;
|
||||
repeated string lucky_gift_ids = 11;
|
||||
repeated string super_lucky_gift_ids = 12;
|
||||
int64 lucky_combo_min = 13;
|
||||
int64 lucky_combo_max = 14;
|
||||
int64 lucky_pause_min_ms = 15;
|
||||
int64 lucky_pause_max_ms = 16;
|
||||
int64 max_gift_senders = 17;
|
||||
repeated AdminHumanRoomRobotCountryPool country_pools = 18;
|
||||
uint64 updated_by_admin_id = 19;
|
||||
int64 created_at_ms = 20;
|
||||
int64 updated_at_ms = 21;
|
||||
int64 normal_gift_interval_min_ms = 22;
|
||||
int64 normal_gift_interval_max_ms = 23;
|
||||
int32 room_target_min_online = 24;
|
||||
int32 room_target_max_online = 25;
|
||||
}
|
||||
|
||||
message AdminGetHumanRoomRobotConfigRequest {
|
||||
RequestMeta meta = 1;
|
||||
}
|
||||
|
||||
message AdminGetHumanRoomRobotConfigResponse {
|
||||
AdminHumanRoomRobotConfig config = 1;
|
||||
int64 server_time_ms = 2;
|
||||
}
|
||||
|
||||
message AdminUpdateHumanRoomRobotConfigRequest {
|
||||
RequestMeta meta = 1;
|
||||
AdminHumanRoomRobotConfig config = 2;
|
||||
uint64 admin_id = 3;
|
||||
}
|
||||
|
||||
message AdminUpdateHumanRoomRobotConfigResponse {
|
||||
AdminHumanRoomRobotConfig config = 1;
|
||||
int64 server_time_ms = 2;
|
||||
}
|
||||
|
||||
message AdminRoomPinRoom {
|
||||
string room_id = 1;
|
||||
string room_short_id = 2;
|
||||
@ -346,6 +399,11 @@ message AdminRobotRoomGiftRule {
|
||||
int64 lucky_combo_max = 5;
|
||||
int64 lucky_pause_min_ms = 6;
|
||||
int64 lucky_pause_max_ms = 7;
|
||||
int64 robot_stay_min_ms = 8;
|
||||
int64 robot_stay_max_ms = 9;
|
||||
int64 robot_replace_min_ms = 10;
|
||||
int64 robot_replace_max_ms = 11;
|
||||
int64 max_gift_senders = 12;
|
||||
}
|
||||
|
||||
message AdminRobotRoom {
|
||||
@ -362,6 +420,8 @@ message AdminRobotRoom {
|
||||
uint64 created_by_admin_id = 11;
|
||||
int64 created_at_ms = 12;
|
||||
int64 updated_at_ms = 13;
|
||||
int32 active_robot_count = 14;
|
||||
int32 seat_count = 15;
|
||||
}
|
||||
|
||||
message AdminListRobotRoomsRequest {
|
||||
@ -388,6 +448,8 @@ message AdminCreateRobotRoomRequest {
|
||||
int64 visible_region_id = 8;
|
||||
AdminRobotRoomGiftRule gift_rule = 9;
|
||||
uint64 admin_id = 10;
|
||||
string owner_country_code = 11;
|
||||
int32 seat_count = 12;
|
||||
}
|
||||
|
||||
message AdminCreateRobotRoomResponse {
|
||||
@ -1005,6 +1067,8 @@ message ListRoomsRequest {
|
||||
string country_code = 8;
|
||||
// viewer_country_code 是当前用户国家,用于区域内国家优先排序,不作为客户端可选筛选条件。
|
||||
string viewer_country_code = 9;
|
||||
// all_visible_regions 只能由 gateway 根据后台白名单配置注入;为 true 时列表不按 visible_region_id 过滤。
|
||||
bool all_visible_regions = 10;
|
||||
}
|
||||
|
||||
// ListRoomFeedsRequest 查询 Mine 页 visited/friend/following/followed 房间流。
|
||||
@ -1232,6 +1296,7 @@ service RoomCommandService {
|
||||
rpc AdminDeleteRoom(AdminDeleteRoomRequest) returns (AdminDeleteRoomResponse);
|
||||
rpc AdminUpdateRoomRocketConfig(AdminUpdateRoomRocketConfigRequest) returns (AdminUpdateRoomRocketConfigResponse);
|
||||
rpc AdminUpdateRoomSeatConfig(AdminUpdateRoomSeatConfigRequest) returns (AdminUpdateRoomSeatConfigResponse);
|
||||
rpc AdminUpdateHumanRoomRobotConfig(AdminUpdateHumanRoomRobotConfigRequest) returns (AdminUpdateHumanRoomRobotConfigResponse);
|
||||
rpc AdminCreateRoomPin(AdminCreateRoomPinRequest) returns (AdminCreateRoomPinResponse);
|
||||
rpc AdminCancelRoomPin(AdminCancelRoomPinRequest) returns (AdminCancelRoomPinResponse);
|
||||
rpc AdminCreateRobotRoom(AdminCreateRobotRoomRequest) returns (AdminCreateRobotRoomResponse);
|
||||
@ -1268,6 +1333,7 @@ service RoomQueryService {
|
||||
rpc AdminGetRoom(AdminGetRoomRequest) returns (AdminGetRoomResponse);
|
||||
rpc AdminGetRoomRocketConfig(AdminGetRoomRocketConfigRequest) returns (AdminGetRoomRocketConfigResponse);
|
||||
rpc AdminGetRoomSeatConfig(AdminGetRoomSeatConfigRequest) returns (AdminGetRoomSeatConfigResponse);
|
||||
rpc AdminGetHumanRoomRobotConfig(AdminGetHumanRoomRobotConfigRequest) returns (AdminGetHumanRoomRobotConfigResponse);
|
||||
rpc AdminListRoomPins(AdminListRoomPinsRequest) returns (AdminListRoomPinsResponse);
|
||||
rpc AdminListRobotRooms(AdminListRobotRoomsRequest) returns (AdminListRobotRoomsResponse);
|
||||
rpc AdminFilterAvailableRoomRobots(AdminFilterAvailableRoomRobotsRequest) returns (AdminFilterAvailableRoomRobotsResponse);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.6.2
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v7.35.0
|
||||
// source: proto/room/v1/room.proto
|
||||
|
||||
@ -19,40 +19,41 @@ import (
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
RoomCommandService_CreateRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/CreateRoom"
|
||||
RoomCommandService_UpdateRoomProfile_FullMethodName = "/hyapp.room.v1.RoomCommandService/UpdateRoomProfile"
|
||||
RoomCommandService_SaveRoomBackground_FullMethodName = "/hyapp.room.v1.RoomCommandService/SaveRoomBackground"
|
||||
RoomCommandService_SetRoomBackground_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetRoomBackground"
|
||||
RoomCommandService_JoinRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/JoinRoom"
|
||||
RoomCommandService_RoomHeartbeat_FullMethodName = "/hyapp.room.v1.RoomCommandService/RoomHeartbeat"
|
||||
RoomCommandService_LeaveRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/LeaveRoom"
|
||||
RoomCommandService_CloseRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/CloseRoom"
|
||||
RoomCommandService_AdminUpdateRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminUpdateRoom"
|
||||
RoomCommandService_AdminDeleteRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminDeleteRoom"
|
||||
RoomCommandService_AdminUpdateRoomRocketConfig_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminUpdateRoomRocketConfig"
|
||||
RoomCommandService_AdminUpdateRoomSeatConfig_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminUpdateRoomSeatConfig"
|
||||
RoomCommandService_AdminCreateRoomPin_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminCreateRoomPin"
|
||||
RoomCommandService_AdminCancelRoomPin_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminCancelRoomPin"
|
||||
RoomCommandService_AdminCreateRobotRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminCreateRobotRoom"
|
||||
RoomCommandService_AdminSetRobotRoomStatus_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminSetRobotRoomStatus"
|
||||
RoomCommandService_MicUp_FullMethodName = "/hyapp.room.v1.RoomCommandService/MicUp"
|
||||
RoomCommandService_MicDown_FullMethodName = "/hyapp.room.v1.RoomCommandService/MicDown"
|
||||
RoomCommandService_ChangeMicSeat_FullMethodName = "/hyapp.room.v1.RoomCommandService/ChangeMicSeat"
|
||||
RoomCommandService_ConfirmMicPublishing_FullMethodName = "/hyapp.room.v1.RoomCommandService/ConfirmMicPublishing"
|
||||
RoomCommandService_MicHeartbeat_FullMethodName = "/hyapp.room.v1.RoomCommandService/MicHeartbeat"
|
||||
RoomCommandService_SetMicMute_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetMicMute"
|
||||
RoomCommandService_ApplyRTCEvent_FullMethodName = "/hyapp.room.v1.RoomCommandService/ApplyRTCEvent"
|
||||
RoomCommandService_SetMicSeatLock_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetMicSeatLock"
|
||||
RoomCommandService_SetChatEnabled_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetChatEnabled"
|
||||
RoomCommandService_SetRoomPassword_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetRoomPassword"
|
||||
RoomCommandService_SetRoomAdmin_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetRoomAdmin"
|
||||
RoomCommandService_MuteUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/MuteUser"
|
||||
RoomCommandService_KickUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/KickUser"
|
||||
RoomCommandService_UnbanUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/UnbanUser"
|
||||
RoomCommandService_SystemEvictUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/SystemEvictUser"
|
||||
RoomCommandService_SendGift_FullMethodName = "/hyapp.room.v1.RoomCommandService/SendGift"
|
||||
RoomCommandService_FollowRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/FollowRoom"
|
||||
RoomCommandService_UnfollowRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/UnfollowRoom"
|
||||
RoomCommandService_CreateRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/CreateRoom"
|
||||
RoomCommandService_UpdateRoomProfile_FullMethodName = "/hyapp.room.v1.RoomCommandService/UpdateRoomProfile"
|
||||
RoomCommandService_SaveRoomBackground_FullMethodName = "/hyapp.room.v1.RoomCommandService/SaveRoomBackground"
|
||||
RoomCommandService_SetRoomBackground_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetRoomBackground"
|
||||
RoomCommandService_JoinRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/JoinRoom"
|
||||
RoomCommandService_RoomHeartbeat_FullMethodName = "/hyapp.room.v1.RoomCommandService/RoomHeartbeat"
|
||||
RoomCommandService_LeaveRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/LeaveRoom"
|
||||
RoomCommandService_CloseRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/CloseRoom"
|
||||
RoomCommandService_AdminUpdateRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminUpdateRoom"
|
||||
RoomCommandService_AdminDeleteRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminDeleteRoom"
|
||||
RoomCommandService_AdminUpdateRoomRocketConfig_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminUpdateRoomRocketConfig"
|
||||
RoomCommandService_AdminUpdateRoomSeatConfig_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminUpdateRoomSeatConfig"
|
||||
RoomCommandService_AdminUpdateHumanRoomRobotConfig_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminUpdateHumanRoomRobotConfig"
|
||||
RoomCommandService_AdminCreateRoomPin_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminCreateRoomPin"
|
||||
RoomCommandService_AdminCancelRoomPin_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminCancelRoomPin"
|
||||
RoomCommandService_AdminCreateRobotRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminCreateRobotRoom"
|
||||
RoomCommandService_AdminSetRobotRoomStatus_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminSetRobotRoomStatus"
|
||||
RoomCommandService_MicUp_FullMethodName = "/hyapp.room.v1.RoomCommandService/MicUp"
|
||||
RoomCommandService_MicDown_FullMethodName = "/hyapp.room.v1.RoomCommandService/MicDown"
|
||||
RoomCommandService_ChangeMicSeat_FullMethodName = "/hyapp.room.v1.RoomCommandService/ChangeMicSeat"
|
||||
RoomCommandService_ConfirmMicPublishing_FullMethodName = "/hyapp.room.v1.RoomCommandService/ConfirmMicPublishing"
|
||||
RoomCommandService_MicHeartbeat_FullMethodName = "/hyapp.room.v1.RoomCommandService/MicHeartbeat"
|
||||
RoomCommandService_SetMicMute_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetMicMute"
|
||||
RoomCommandService_ApplyRTCEvent_FullMethodName = "/hyapp.room.v1.RoomCommandService/ApplyRTCEvent"
|
||||
RoomCommandService_SetMicSeatLock_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetMicSeatLock"
|
||||
RoomCommandService_SetChatEnabled_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetChatEnabled"
|
||||
RoomCommandService_SetRoomPassword_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetRoomPassword"
|
||||
RoomCommandService_SetRoomAdmin_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetRoomAdmin"
|
||||
RoomCommandService_MuteUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/MuteUser"
|
||||
RoomCommandService_KickUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/KickUser"
|
||||
RoomCommandService_UnbanUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/UnbanUser"
|
||||
RoomCommandService_SystemEvictUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/SystemEvictUser"
|
||||
RoomCommandService_SendGift_FullMethodName = "/hyapp.room.v1.RoomCommandService/SendGift"
|
||||
RoomCommandService_FollowRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/FollowRoom"
|
||||
RoomCommandService_UnfollowRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/UnfollowRoom"
|
||||
)
|
||||
|
||||
// RoomCommandServiceClient is the client API for RoomCommandService service.
|
||||
@ -73,6 +74,7 @@ type RoomCommandServiceClient interface {
|
||||
AdminDeleteRoom(ctx context.Context, in *AdminDeleteRoomRequest, opts ...grpc.CallOption) (*AdminDeleteRoomResponse, error)
|
||||
AdminUpdateRoomRocketConfig(ctx context.Context, in *AdminUpdateRoomRocketConfigRequest, opts ...grpc.CallOption) (*AdminUpdateRoomRocketConfigResponse, error)
|
||||
AdminUpdateRoomSeatConfig(ctx context.Context, in *AdminUpdateRoomSeatConfigRequest, opts ...grpc.CallOption) (*AdminUpdateRoomSeatConfigResponse, error)
|
||||
AdminUpdateHumanRoomRobotConfig(ctx context.Context, in *AdminUpdateHumanRoomRobotConfigRequest, opts ...grpc.CallOption) (*AdminUpdateHumanRoomRobotConfigResponse, error)
|
||||
AdminCreateRoomPin(ctx context.Context, in *AdminCreateRoomPinRequest, opts ...grpc.CallOption) (*AdminCreateRoomPinResponse, error)
|
||||
AdminCancelRoomPin(ctx context.Context, in *AdminCancelRoomPinRequest, opts ...grpc.CallOption) (*AdminCancelRoomPinResponse, error)
|
||||
AdminCreateRobotRoom(ctx context.Context, in *AdminCreateRobotRoomRequest, opts ...grpc.CallOption) (*AdminCreateRobotRoomResponse, error)
|
||||
@ -225,6 +227,16 @@ func (c *roomCommandServiceClient) AdminUpdateRoomSeatConfig(ctx context.Context
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *roomCommandServiceClient) AdminUpdateHumanRoomRobotConfig(ctx context.Context, in *AdminUpdateHumanRoomRobotConfigRequest, opts ...grpc.CallOption) (*AdminUpdateHumanRoomRobotConfigResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(AdminUpdateHumanRoomRobotConfigResponse)
|
||||
err := c.cc.Invoke(ctx, RoomCommandService_AdminUpdateHumanRoomRobotConfig_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *roomCommandServiceClient) AdminCreateRoomPin(ctx context.Context, in *AdminCreateRoomPinRequest, opts ...grpc.CallOption) (*AdminCreateRoomPinResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(AdminCreateRoomPinResponse)
|
||||
@ -463,6 +475,7 @@ type RoomCommandServiceServer interface {
|
||||
AdminDeleteRoom(context.Context, *AdminDeleteRoomRequest) (*AdminDeleteRoomResponse, error)
|
||||
AdminUpdateRoomRocketConfig(context.Context, *AdminUpdateRoomRocketConfigRequest) (*AdminUpdateRoomRocketConfigResponse, error)
|
||||
AdminUpdateRoomSeatConfig(context.Context, *AdminUpdateRoomSeatConfigRequest) (*AdminUpdateRoomSeatConfigResponse, error)
|
||||
AdminUpdateHumanRoomRobotConfig(context.Context, *AdminUpdateHumanRoomRobotConfigRequest) (*AdminUpdateHumanRoomRobotConfigResponse, error)
|
||||
AdminCreateRoomPin(context.Context, *AdminCreateRoomPinRequest) (*AdminCreateRoomPinResponse, error)
|
||||
AdminCancelRoomPin(context.Context, *AdminCancelRoomPinRequest) (*AdminCancelRoomPinResponse, error)
|
||||
AdminCreateRobotRoom(context.Context, *AdminCreateRobotRoomRequest) (*AdminCreateRobotRoomResponse, error)
|
||||
@ -496,106 +509,109 @@ type RoomCommandServiceServer interface {
|
||||
type UnimplementedRoomCommandServiceServer struct{}
|
||||
|
||||
func (UnimplementedRoomCommandServiceServer) CreateRoom(context.Context, *CreateRoomRequest) (*CreateRoomResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateRoom not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateRoom not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) UpdateRoomProfile(context.Context, *UpdateRoomProfileRequest) (*UpdateRoomProfileResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateRoomProfile not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateRoomProfile not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) SaveRoomBackground(context.Context, *SaveRoomBackgroundRequest) (*SaveRoomBackgroundResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SaveRoomBackground not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SaveRoomBackground not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) SetRoomBackground(context.Context, *SetRoomBackgroundRequest) (*SetRoomBackgroundResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetRoomBackground not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetRoomBackground not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) JoinRoom(context.Context, *JoinRoomRequest) (*JoinRoomResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method JoinRoom not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method JoinRoom not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) RoomHeartbeat(context.Context, *RoomHeartbeatRequest) (*RoomHeartbeatResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RoomHeartbeat not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RoomHeartbeat not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) LeaveRoom(context.Context, *LeaveRoomRequest) (*LeaveRoomResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method LeaveRoom not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method LeaveRoom not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) CloseRoom(context.Context, *CloseRoomRequest) (*CloseRoomResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CloseRoom not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CloseRoom not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) AdminUpdateRoom(context.Context, *AdminUpdateRoomRequest) (*AdminUpdateRoomResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminUpdateRoom not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminUpdateRoom not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) AdminDeleteRoom(context.Context, *AdminDeleteRoomRequest) (*AdminDeleteRoomResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminDeleteRoom not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminDeleteRoom not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) AdminUpdateRoomRocketConfig(context.Context, *AdminUpdateRoomRocketConfigRequest) (*AdminUpdateRoomRocketConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminUpdateRoomRocketConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminUpdateRoomRocketConfig not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) AdminUpdateRoomSeatConfig(context.Context, *AdminUpdateRoomSeatConfigRequest) (*AdminUpdateRoomSeatConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminUpdateRoomSeatConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminUpdateRoomSeatConfig not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) AdminUpdateHumanRoomRobotConfig(context.Context, *AdminUpdateHumanRoomRobotConfigRequest) (*AdminUpdateHumanRoomRobotConfigResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminUpdateHumanRoomRobotConfig not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) AdminCreateRoomPin(context.Context, *AdminCreateRoomPinRequest) (*AdminCreateRoomPinResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminCreateRoomPin not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminCreateRoomPin not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) AdminCancelRoomPin(context.Context, *AdminCancelRoomPinRequest) (*AdminCancelRoomPinResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminCancelRoomPin not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminCancelRoomPin not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) AdminCreateRobotRoom(context.Context, *AdminCreateRobotRoomRequest) (*AdminCreateRobotRoomResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminCreateRobotRoom not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminCreateRobotRoom not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) AdminSetRobotRoomStatus(context.Context, *AdminSetRobotRoomStatusRequest) (*AdminSetRobotRoomStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminSetRobotRoomStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminSetRobotRoomStatus not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) MicUp(context.Context, *MicUpRequest) (*MicUpResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method MicUp not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method MicUp not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) MicDown(context.Context, *MicDownRequest) (*MicDownResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method MicDown not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method MicDown not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) ChangeMicSeat(context.Context, *ChangeMicSeatRequest) (*ChangeMicSeatResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ChangeMicSeat not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ChangeMicSeat not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) ConfirmMicPublishing(context.Context, *ConfirmMicPublishingRequest) (*ConfirmMicPublishingResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ConfirmMicPublishing not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ConfirmMicPublishing not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) MicHeartbeat(context.Context, *MicHeartbeatRequest) (*MicHeartbeatResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method MicHeartbeat not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method MicHeartbeat not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) SetMicMute(context.Context, *SetMicMuteRequest) (*SetMicMuteResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetMicMute not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetMicMute not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) ApplyRTCEvent(context.Context, *ApplyRTCEventRequest) (*ApplyRTCEventResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ApplyRTCEvent not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ApplyRTCEvent not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) SetMicSeatLock(context.Context, *SetMicSeatLockRequest) (*SetMicSeatLockResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetMicSeatLock not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetMicSeatLock not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) SetChatEnabled(context.Context, *SetChatEnabledRequest) (*SetChatEnabledResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetChatEnabled not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetChatEnabled not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) SetRoomPassword(context.Context, *SetRoomPasswordRequest) (*SetRoomPasswordResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetRoomPassword not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetRoomPassword not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) SetRoomAdmin(context.Context, *SetRoomAdminRequest) (*SetRoomAdminResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetRoomAdmin not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetRoomAdmin not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) MuteUser(context.Context, *MuteUserRequest) (*MuteUserResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method MuteUser not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method MuteUser not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) KickUser(context.Context, *KickUserRequest) (*KickUserResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method KickUser not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method KickUser not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) UnbanUser(context.Context, *UnbanUserRequest) (*UnbanUserResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UnbanUser not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UnbanUser not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) SystemEvictUser(context.Context, *SystemEvictUserRequest) (*SystemEvictUserResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SystemEvictUser not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SystemEvictUser not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) SendGift(context.Context, *SendGiftRequest) (*SendGiftResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SendGift not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SendGift not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) FollowRoom(context.Context, *FollowRoomRequest) (*FollowRoomResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method FollowRoom not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method FollowRoom not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) UnfollowRoom(context.Context, *UnfollowRoomRequest) (*UnfollowRoomResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UnfollowRoom not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UnfollowRoom not implemented")
|
||||
}
|
||||
func (UnimplementedRoomCommandServiceServer) mustEmbedUnimplementedRoomCommandServiceServer() {}
|
||||
func (UnimplementedRoomCommandServiceServer) testEmbeddedByValue() {}
|
||||
@ -608,7 +624,7 @@ type UnsafeRoomCommandServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterRoomCommandServiceServer(s grpc.ServiceRegistrar, srv RoomCommandServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedRoomCommandServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedRoomCommandServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -834,6 +850,24 @@ func _RoomCommandService_AdminUpdateRoomSeatConfig_Handler(srv interface{}, ctx
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _RoomCommandService_AdminUpdateHumanRoomRobotConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AdminUpdateHumanRoomRobotConfigRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(RoomCommandServiceServer).AdminUpdateHumanRoomRobotConfig(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: RoomCommandService_AdminUpdateHumanRoomRobotConfig_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RoomCommandServiceServer).AdminUpdateHumanRoomRobotConfig(ctx, req.(*AdminUpdateHumanRoomRobotConfigRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _RoomCommandService_AdminCreateRoomPin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AdminCreateRoomPinRequest)
|
||||
if err := dec(in); err != nil {
|
||||
@ -1285,6 +1319,10 @@ var RoomCommandService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "AdminUpdateRoomSeatConfig",
|
||||
Handler: _RoomCommandService_AdminUpdateRoomSeatConfig_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "AdminUpdateHumanRoomRobotConfig",
|
||||
Handler: _RoomCommandService_AdminUpdateHumanRoomRobotConfig_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "AdminCreateRoomPin",
|
||||
Handler: _RoomCommandService_AdminCreateRoomPin_Handler,
|
||||
@ -1440,10 +1478,10 @@ type RoomGuardServiceServer interface {
|
||||
type UnimplementedRoomGuardServiceServer struct{}
|
||||
|
||||
func (UnimplementedRoomGuardServiceServer) CheckSpeakPermission(context.Context, *CheckSpeakPermissionRequest) (*CheckSpeakPermissionResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CheckSpeakPermission not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CheckSpeakPermission not implemented")
|
||||
}
|
||||
func (UnimplementedRoomGuardServiceServer) VerifyRoomPresence(context.Context, *VerifyRoomPresenceRequest) (*VerifyRoomPresenceResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method VerifyRoomPresence not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method VerifyRoomPresence not implemented")
|
||||
}
|
||||
func (UnimplementedRoomGuardServiceServer) mustEmbedUnimplementedRoomGuardServiceServer() {}
|
||||
func (UnimplementedRoomGuardServiceServer) testEmbeddedByValue() {}
|
||||
@ -1456,7 +1494,7 @@ type UnsafeRoomGuardServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterRoomGuardServiceServer(s grpc.ServiceRegistrar, srv RoomGuardServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedRoomGuardServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedRoomGuardServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -1527,6 +1565,7 @@ const (
|
||||
RoomQueryService_AdminGetRoom_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminGetRoom"
|
||||
RoomQueryService_AdminGetRoomRocketConfig_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminGetRoomRocketConfig"
|
||||
RoomQueryService_AdminGetRoomSeatConfig_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminGetRoomSeatConfig"
|
||||
RoomQueryService_AdminGetHumanRoomRobotConfig_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminGetHumanRoomRobotConfig"
|
||||
RoomQueryService_AdminListRoomPins_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminListRoomPins"
|
||||
RoomQueryService_AdminListRobotRooms_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminListRobotRooms"
|
||||
RoomQueryService_AdminFilterAvailableRoomRobots_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminFilterAvailableRoomRobots"
|
||||
@ -1552,6 +1591,7 @@ type RoomQueryServiceClient interface {
|
||||
AdminGetRoom(ctx context.Context, in *AdminGetRoomRequest, opts ...grpc.CallOption) (*AdminGetRoomResponse, error)
|
||||
AdminGetRoomRocketConfig(ctx context.Context, in *AdminGetRoomRocketConfigRequest, opts ...grpc.CallOption) (*AdminGetRoomRocketConfigResponse, error)
|
||||
AdminGetRoomSeatConfig(ctx context.Context, in *AdminGetRoomSeatConfigRequest, opts ...grpc.CallOption) (*AdminGetRoomSeatConfigResponse, error)
|
||||
AdminGetHumanRoomRobotConfig(ctx context.Context, in *AdminGetHumanRoomRobotConfigRequest, opts ...grpc.CallOption) (*AdminGetHumanRoomRobotConfigResponse, error)
|
||||
AdminListRoomPins(ctx context.Context, in *AdminListRoomPinsRequest, opts ...grpc.CallOption) (*AdminListRoomPinsResponse, error)
|
||||
AdminListRobotRooms(ctx context.Context, in *AdminListRobotRoomsRequest, opts ...grpc.CallOption) (*AdminListRobotRoomsResponse, error)
|
||||
AdminFilterAvailableRoomRobots(ctx context.Context, in *AdminFilterAvailableRoomRobotsRequest, opts ...grpc.CallOption) (*AdminFilterAvailableRoomRobotsResponse, error)
|
||||
@ -1615,6 +1655,16 @@ func (c *roomQueryServiceClient) AdminGetRoomSeatConfig(ctx context.Context, in
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *roomQueryServiceClient) AdminGetHumanRoomRobotConfig(ctx context.Context, in *AdminGetHumanRoomRobotConfigRequest, opts ...grpc.CallOption) (*AdminGetHumanRoomRobotConfigResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(AdminGetHumanRoomRobotConfigResponse)
|
||||
err := c.cc.Invoke(ctx, RoomQueryService_AdminGetHumanRoomRobotConfig_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *roomQueryServiceClient) AdminListRoomPins(ctx context.Context, in *AdminListRoomPinsRequest, opts ...grpc.CallOption) (*AdminListRoomPinsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(AdminListRoomPinsResponse)
|
||||
@ -1755,6 +1805,7 @@ type RoomQueryServiceServer interface {
|
||||
AdminGetRoom(context.Context, *AdminGetRoomRequest) (*AdminGetRoomResponse, error)
|
||||
AdminGetRoomRocketConfig(context.Context, *AdminGetRoomRocketConfigRequest) (*AdminGetRoomRocketConfigResponse, error)
|
||||
AdminGetRoomSeatConfig(context.Context, *AdminGetRoomSeatConfigRequest) (*AdminGetRoomSeatConfigResponse, error)
|
||||
AdminGetHumanRoomRobotConfig(context.Context, *AdminGetHumanRoomRobotConfigRequest) (*AdminGetHumanRoomRobotConfigResponse, error)
|
||||
AdminListRoomPins(context.Context, *AdminListRoomPinsRequest) (*AdminListRoomPinsResponse, error)
|
||||
AdminListRobotRooms(context.Context, *AdminListRobotRoomsRequest) (*AdminListRobotRoomsResponse, error)
|
||||
AdminFilterAvailableRoomRobots(context.Context, *AdminFilterAvailableRoomRobotsRequest) (*AdminFilterAvailableRoomRobotsResponse, error)
|
||||
@ -1779,55 +1830,58 @@ type RoomQueryServiceServer interface {
|
||||
type UnimplementedRoomQueryServiceServer struct{}
|
||||
|
||||
func (UnimplementedRoomQueryServiceServer) AdminListRooms(context.Context, *AdminListRoomsRequest) (*AdminListRoomsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminListRooms not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminListRooms not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) AdminGetRoom(context.Context, *AdminGetRoomRequest) (*AdminGetRoomResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminGetRoom not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminGetRoom not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) AdminGetRoomRocketConfig(context.Context, *AdminGetRoomRocketConfigRequest) (*AdminGetRoomRocketConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminGetRoomRocketConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminGetRoomRocketConfig not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) AdminGetRoomSeatConfig(context.Context, *AdminGetRoomSeatConfigRequest) (*AdminGetRoomSeatConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminGetRoomSeatConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminGetRoomSeatConfig not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) AdminGetHumanRoomRobotConfig(context.Context, *AdminGetHumanRoomRobotConfigRequest) (*AdminGetHumanRoomRobotConfigResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminGetHumanRoomRobotConfig not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) AdminListRoomPins(context.Context, *AdminListRoomPinsRequest) (*AdminListRoomPinsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminListRoomPins not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminListRoomPins not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) AdminListRobotRooms(context.Context, *AdminListRobotRoomsRequest) (*AdminListRobotRoomsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminListRobotRooms not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminListRobotRooms not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) AdminFilterAvailableRoomRobots(context.Context, *AdminFilterAvailableRoomRobotsRequest) (*AdminFilterAvailableRoomRobotsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminFilterAvailableRoomRobots not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminFilterAvailableRoomRobots not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) ListRooms(context.Context, *ListRoomsRequest) (*ListRoomsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRooms not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRooms not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) ListRoomFeeds(context.Context, *ListRoomFeedsRequest) (*ListRoomsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRoomFeeds not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRoomFeeds not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) ListRoomGiftLeaderboard(context.Context, *ListRoomGiftLeaderboardRequest) (*ListRoomGiftLeaderboardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRoomGiftLeaderboard not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRoomGiftLeaderboard not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) GetMyRoom(context.Context, *GetMyRoomRequest) (*GetMyRoomResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetMyRoom not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetMyRoom not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) GetCurrentRoom(context.Context, *GetCurrentRoomRequest) (*GetCurrentRoomResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetCurrentRoom not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetCurrentRoom not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) GetRoomSnapshot(context.Context, *GetRoomSnapshotRequest) (*GetRoomSnapshotResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetRoomSnapshot not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRoomSnapshot not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) ListRoomBackgrounds(context.Context, *ListRoomBackgroundsRequest) (*ListRoomBackgroundsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRoomBackgrounds not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRoomBackgrounds not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) GetRoomRocket(context.Context, *GetRoomRocketRequest) (*GetRoomRocketResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetRoomRocket not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRoomRocket not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) ListRoomOnlineUsers(context.Context, *ListRoomOnlineUsersRequest) (*ListRoomOnlineUsersResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRoomOnlineUsers not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRoomOnlineUsers not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) ListRoomBannedUsers(context.Context, *ListRoomBannedUsersRequest) (*ListRoomBannedUsersResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRoomBannedUsers not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRoomBannedUsers not implemented")
|
||||
}
|
||||
func (UnimplementedRoomQueryServiceServer) mustEmbedUnimplementedRoomQueryServiceServer() {}
|
||||
func (UnimplementedRoomQueryServiceServer) testEmbeddedByValue() {}
|
||||
@ -1840,7 +1894,7 @@ type UnsafeRoomQueryServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterRoomQueryServiceServer(s grpc.ServiceRegistrar, srv RoomQueryServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedRoomQueryServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedRoomQueryServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -1922,6 +1976,24 @@ func _RoomQueryService_AdminGetRoomSeatConfig_Handler(srv interface{}, ctx conte
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _RoomQueryService_AdminGetHumanRoomRobotConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AdminGetHumanRoomRobotConfigRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(RoomQueryServiceServer).AdminGetHumanRoomRobotConfig(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: RoomQueryService_AdminGetHumanRoomRobotConfig_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RoomQueryServiceServer).AdminGetHumanRoomRobotConfig(ctx, req.(*AdminGetHumanRoomRobotConfigRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _RoomQueryService_AdminListRoomPins_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AdminListRoomPinsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
@ -2179,6 +2251,10 @@ var RoomQueryService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "AdminGetRoomSeatConfig",
|
||||
Handler: _RoomQueryService_AdminGetRoomSeatConfig_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "AdminGetHumanRoomRobotConfig",
|
||||
Handler: _RoomQueryService_AdminGetHumanRoomRobotConfig_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "AdminListRoomPins",
|
||||
Handler: _RoomQueryService_AdminListRoomPins_Handler,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.11
|
||||
// protoc-gen-go v1.35.1
|
||||
// protoc v7.35.0
|
||||
// source: proto/user/v1/auth.proto
|
||||
|
||||
@ -11,7 +11,6 @@ import (
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -23,12 +22,13 @@ const (
|
||||
|
||||
// LoginPasswordRequest 使用当前 display_user_id 和已设置密码登录。
|
||||
type LoginPasswordRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
DisplayUserId string `protobuf:"bytes,2,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"`
|
||||
Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
DisplayUserId string `protobuf:"bytes,2,opt,name=display_user_id,json=displayUserId,proto3" json:"display_user_id,omitempty"`
|
||||
Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
|
||||
}
|
||||
|
||||
func (x *LoginPasswordRequest) Reset() {
|
||||
@ -84,29 +84,30 @@ func (x *LoginPasswordRequest) GetPassword() string {
|
||||
|
||||
// LoginThirdPartyRequest 使用三方凭证登录或注册。
|
||||
type LoginThirdPartyRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
Provider string `protobuf:"bytes,2,opt,name=provider,proto3" json:"provider,omitempty"`
|
||||
Credential string `protobuf:"bytes,3,opt,name=credential,proto3" json:"credential,omitempty"`
|
||||
Username string `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"`
|
||||
Gender string `protobuf:"bytes,5,opt,name=gender,proto3" json:"gender,omitempty"`
|
||||
Country string `protobuf:"bytes,6,opt,name=country,proto3" json:"country,omitempty"`
|
||||
InviteCode string `protobuf:"bytes,7,opt,name=invite_code,json=inviteCode,proto3" json:"invite_code,omitempty"`
|
||||
DeviceId string `protobuf:"bytes,8,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"`
|
||||
Device string `protobuf:"bytes,9,opt,name=device,proto3" json:"device,omitempty"`
|
||||
Avatar string `protobuf:"bytes,10,opt,name=avatar,proto3" json:"avatar,omitempty"`
|
||||
Birth string `protobuf:"bytes,11,opt,name=birth,proto3" json:"birth,omitempty"`
|
||||
AppVersion string `protobuf:"bytes,12,opt,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"`
|
||||
Source string `protobuf:"bytes,13,opt,name=source,proto3" json:"source,omitempty"`
|
||||
Platform string `protobuf:"bytes,14,opt,name=platform,proto3" json:"platform,omitempty"`
|
||||
Language string `protobuf:"bytes,15,opt,name=language,proto3" json:"language,omitempty"`
|
||||
OsVersion string `protobuf:"bytes,16,opt,name=os_version,json=osVersion,proto3" json:"os_version,omitempty"`
|
||||
BuildNumber string `protobuf:"bytes,17,opt,name=build_number,json=buildNumber,proto3" json:"build_number,omitempty"`
|
||||
Timezone string `protobuf:"bytes,18,opt,name=timezone,proto3" json:"timezone,omitempty"`
|
||||
InstallChannel string `protobuf:"bytes,19,opt,name=install_channel,json=installChannel,proto3" json:"install_channel,omitempty"`
|
||||
Campaign string `protobuf:"bytes,20,opt,name=campaign,proto3" json:"campaign,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
Provider string `protobuf:"bytes,2,opt,name=provider,proto3" json:"provider,omitempty"`
|
||||
Credential string `protobuf:"bytes,3,opt,name=credential,proto3" json:"credential,omitempty"`
|
||||
Username string `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"`
|
||||
Gender string `protobuf:"bytes,5,opt,name=gender,proto3" json:"gender,omitempty"`
|
||||
Country string `protobuf:"bytes,6,opt,name=country,proto3" json:"country,omitempty"`
|
||||
InviteCode string `protobuf:"bytes,7,opt,name=invite_code,json=inviteCode,proto3" json:"invite_code,omitempty"`
|
||||
DeviceId string `protobuf:"bytes,8,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"`
|
||||
Device string `protobuf:"bytes,9,opt,name=device,proto3" json:"device,omitempty"`
|
||||
Avatar string `protobuf:"bytes,10,opt,name=avatar,proto3" json:"avatar,omitempty"`
|
||||
Birth string `protobuf:"bytes,11,opt,name=birth,proto3" json:"birth,omitempty"`
|
||||
AppVersion string `protobuf:"bytes,12,opt,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"`
|
||||
Source string `protobuf:"bytes,13,opt,name=source,proto3" json:"source,omitempty"`
|
||||
Platform string `protobuf:"bytes,14,opt,name=platform,proto3" json:"platform,omitempty"`
|
||||
Language string `protobuf:"bytes,15,opt,name=language,proto3" json:"language,omitempty"`
|
||||
OsVersion string `protobuf:"bytes,16,opt,name=os_version,json=osVersion,proto3" json:"os_version,omitempty"`
|
||||
BuildNumber string `protobuf:"bytes,17,opt,name=build_number,json=buildNumber,proto3" json:"build_number,omitempty"`
|
||||
Timezone string `protobuf:"bytes,18,opt,name=timezone,proto3" json:"timezone,omitempty"`
|
||||
InstallChannel string `protobuf:"bytes,19,opt,name=install_channel,json=installChannel,proto3" json:"install_channel,omitempty"`
|
||||
Campaign string `protobuf:"bytes,20,opt,name=campaign,proto3" json:"campaign,omitempty"`
|
||||
}
|
||||
|
||||
func (x *LoginThirdPartyRequest) Reset() {
|
||||
@ -281,13 +282,14 @@ func (x *LoginThirdPartyRequest) GetCampaign() string {
|
||||
|
||||
// AuthResponse 返回标准认证令牌。
|
||||
type AuthResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Token *AuthToken `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
|
||||
IsNewUser bool `protobuf:"varint,2,opt,name=is_new_user,json=isNewUser,proto3" json:"is_new_user,omitempty"`
|
||||
ProfileCompleted bool `protobuf:"varint,3,opt,name=profile_completed,json=profileCompleted,proto3" json:"profile_completed,omitempty"`
|
||||
OnboardingStatus string `protobuf:"bytes,4,opt,name=onboarding_status,json=onboardingStatus,proto3" json:"onboarding_status,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Token *AuthToken `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
|
||||
IsNewUser bool `protobuf:"varint,2,opt,name=is_new_user,json=isNewUser,proto3" json:"is_new_user,omitempty"`
|
||||
ProfileCompleted bool `protobuf:"varint,3,opt,name=profile_completed,json=profileCompleted,proto3" json:"profile_completed,omitempty"`
|
||||
OnboardingStatus string `protobuf:"bytes,4,opt,name=onboarding_status,json=onboardingStatus,proto3" json:"onboarding_status,omitempty"`
|
||||
}
|
||||
|
||||
func (x *AuthResponse) Reset() {
|
||||
@ -350,12 +352,13 @@ func (x *AuthResponse) GetOnboardingStatus() string {
|
||||
|
||||
// SetPasswordRequest 为已经三方登录的用户首次设置密码。
|
||||
type SetPasswordRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SetPasswordRequest) Reset() {
|
||||
@ -411,10 +414,11 @@ func (x *SetPasswordRequest) GetPassword() string {
|
||||
|
||||
// SetPasswordResponse 返回密码是否已经成功设置。
|
||||
type SetPasswordResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
PasswordSet bool `protobuf:"varint,1,opt,name=password_set,json=passwordSet,proto3" json:"password_set,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
PasswordSet bool `protobuf:"varint,1,opt,name=password_set,json=passwordSet,proto3" json:"password_set,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SetPasswordResponse) Reset() {
|
||||
@ -456,28 +460,29 @@ func (x *SetPasswordResponse) GetPasswordSet() bool {
|
||||
|
||||
// QuickCreateAccountRequest 为后台快速创建完整资料账号;source=game_robot 时账号不可登录。
|
||||
type QuickCreateAccountRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
|
||||
Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"`
|
||||
Avatar string `protobuf:"bytes,4,opt,name=avatar,proto3" json:"avatar,omitempty"`
|
||||
Gender string `protobuf:"bytes,5,opt,name=gender,proto3" json:"gender,omitempty"`
|
||||
Country string `protobuf:"bytes,6,opt,name=country,proto3" json:"country,omitempty"`
|
||||
InviteCode string `protobuf:"bytes,7,opt,name=invite_code,json=inviteCode,proto3" json:"invite_code,omitempty"`
|
||||
DeviceId string `protobuf:"bytes,8,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"`
|
||||
Device string `protobuf:"bytes,9,opt,name=device,proto3" json:"device,omitempty"`
|
||||
OsVersion string `protobuf:"bytes,10,opt,name=os_version,json=osVersion,proto3" json:"os_version,omitempty"`
|
||||
Birth string `protobuf:"bytes,11,opt,name=birth,proto3" json:"birth,omitempty"`
|
||||
AppVersion string `protobuf:"bytes,12,opt,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"`
|
||||
BuildNumber string `protobuf:"bytes,13,opt,name=build_number,json=buildNumber,proto3" json:"build_number,omitempty"`
|
||||
Source string `protobuf:"bytes,14,opt,name=source,proto3" json:"source,omitempty"`
|
||||
InstallChannel string `protobuf:"bytes,15,opt,name=install_channel,json=installChannel,proto3" json:"install_channel,omitempty"`
|
||||
Campaign string `protobuf:"bytes,16,opt,name=campaign,proto3" json:"campaign,omitempty"`
|
||||
Platform string `protobuf:"bytes,17,opt,name=platform,proto3" json:"platform,omitempty"`
|
||||
Language string `protobuf:"bytes,18,opt,name=language,proto3" json:"language,omitempty"`
|
||||
Timezone string `protobuf:"bytes,19,opt,name=timezone,proto3" json:"timezone,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
|
||||
Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"`
|
||||
Avatar string `protobuf:"bytes,4,opt,name=avatar,proto3" json:"avatar,omitempty"`
|
||||
Gender string `protobuf:"bytes,5,opt,name=gender,proto3" json:"gender,omitempty"`
|
||||
Country string `protobuf:"bytes,6,opt,name=country,proto3" json:"country,omitempty"`
|
||||
InviteCode string `protobuf:"bytes,7,opt,name=invite_code,json=inviteCode,proto3" json:"invite_code,omitempty"`
|
||||
DeviceId string `protobuf:"bytes,8,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"`
|
||||
Device string `protobuf:"bytes,9,opt,name=device,proto3" json:"device,omitempty"`
|
||||
OsVersion string `protobuf:"bytes,10,opt,name=os_version,json=osVersion,proto3" json:"os_version,omitempty"`
|
||||
Birth string `protobuf:"bytes,11,opt,name=birth,proto3" json:"birth,omitempty"`
|
||||
AppVersion string `protobuf:"bytes,12,opt,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"`
|
||||
BuildNumber string `protobuf:"bytes,13,opt,name=build_number,json=buildNumber,proto3" json:"build_number,omitempty"`
|
||||
Source string `protobuf:"bytes,14,opt,name=source,proto3" json:"source,omitempty"`
|
||||
InstallChannel string `protobuf:"bytes,15,opt,name=install_channel,json=installChannel,proto3" json:"install_channel,omitempty"`
|
||||
Campaign string `protobuf:"bytes,16,opt,name=campaign,proto3" json:"campaign,omitempty"`
|
||||
Platform string `protobuf:"bytes,17,opt,name=platform,proto3" json:"platform,omitempty"`
|
||||
Language string `protobuf:"bytes,18,opt,name=language,proto3" json:"language,omitempty"`
|
||||
Timezone string `protobuf:"bytes,19,opt,name=timezone,proto3" json:"timezone,omitempty"`
|
||||
}
|
||||
|
||||
func (x *QuickCreateAccountRequest) Reset() {
|
||||
@ -645,11 +650,12 @@ func (x *QuickCreateAccountRequest) GetTimezone() string {
|
||||
|
||||
// QuickCreateAccountResponse 返回新账号身份;普通账号含登录态,source=game_robot 时 token 只含 user_id/display_user_id。
|
||||
type QuickCreateAccountResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Token *AuthToken `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
|
||||
PasswordSet bool `protobuf:"varint,2,opt,name=password_set,json=passwordSet,proto3" json:"password_set,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Token *AuthToken `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
|
||||
PasswordSet bool `protobuf:"varint,2,opt,name=password_set,json=passwordSet,proto3" json:"password_set,omitempty"`
|
||||
}
|
||||
|
||||
func (x *QuickCreateAccountResponse) Reset() {
|
||||
@ -698,11 +704,12 @@ func (x *QuickCreateAccountResponse) GetPasswordSet() bool {
|
||||
|
||||
// RefreshTokenRequest 使用 refresh token 换取新 token。
|
||||
type RefreshTokenRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
RefreshToken string `protobuf:"bytes,2,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
RefreshToken string `protobuf:"bytes,2,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RefreshTokenRequest) Reset() {
|
||||
@ -751,10 +758,11 @@ func (x *RefreshTokenRequest) GetRefreshToken() string {
|
||||
|
||||
// RefreshTokenResponse 返回轮换后的令牌。
|
||||
type RefreshTokenResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Token *AuthToken `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Token *AuthToken `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RefreshTokenResponse) Reset() {
|
||||
@ -796,12 +804,13 @@ func (x *RefreshTokenResponse) GetToken() *AuthToken {
|
||||
|
||||
// LogoutRequest 失效指定会话或 refresh token。
|
||||
type LogoutRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"`
|
||||
RefreshToken string `protobuf:"bytes,3,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"`
|
||||
RefreshToken string `protobuf:"bytes,3,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
|
||||
}
|
||||
|
||||
func (x *LogoutRequest) Reset() {
|
||||
@ -857,10 +866,11 @@ func (x *LogoutRequest) GetRefreshToken() string {
|
||||
|
||||
// LogoutResponse 返回会话是否被失效。
|
||||
type LogoutResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Revoked bool `protobuf:"varint,1,opt,name=revoked,proto3" json:"revoked,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Revoked bool `protobuf:"varint,1,opt,name=revoked,proto3" json:"revoked,omitempty"`
|
||||
}
|
||||
|
||||
func (x *LogoutResponse) Reset() {
|
||||
@ -902,15 +912,16 @@ func (x *LogoutResponse) GetRevoked() bool {
|
||||
|
||||
// RecordLoginBlockedRequest 记录 gateway 入口快拦拒绝的登录审计。
|
||||
type RecordLoginBlockedRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
Channel string `protobuf:"bytes,2,opt,name=channel,proto3" json:"channel,omitempty"`
|
||||
Platform string `protobuf:"bytes,3,opt,name=platform,proto3" json:"platform,omitempty"`
|
||||
Language string `protobuf:"bytes,4,opt,name=language,proto3" json:"language,omitempty"`
|
||||
Timezone string `protobuf:"bytes,5,opt,name=timezone,proto3" json:"timezone,omitempty"`
|
||||
BlockReason string `protobuf:"bytes,6,opt,name=block_reason,json=blockReason,proto3" json:"block_reason,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
Channel string `protobuf:"bytes,2,opt,name=channel,proto3" json:"channel,omitempty"`
|
||||
Platform string `protobuf:"bytes,3,opt,name=platform,proto3" json:"platform,omitempty"`
|
||||
Language string `protobuf:"bytes,4,opt,name=language,proto3" json:"language,omitempty"`
|
||||
Timezone string `protobuf:"bytes,5,opt,name=timezone,proto3" json:"timezone,omitempty"`
|
||||
BlockReason string `protobuf:"bytes,6,opt,name=block_reason,json=blockReason,proto3" json:"block_reason,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RecordLoginBlockedRequest) Reset() {
|
||||
@ -987,10 +998,11 @@ func (x *RecordLoginBlockedRequest) GetBlockReason() string {
|
||||
|
||||
// RecordLoginBlockedResponse 返回审计写入是否成功。
|
||||
type RecordLoginBlockedResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Recorded bool `protobuf:"varint,1,opt,name=recorded,proto3" json:"recorded,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Recorded bool `protobuf:"varint,1,opt,name=recorded,proto3" json:"recorded,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RecordLoginBlockedResponse) Reset() {
|
||||
@ -1032,12 +1044,13 @@ func (x *RecordLoginBlockedResponse) GetRecorded() bool {
|
||||
|
||||
// AppHeartbeatRequest 刷新当前登录会话的 App 在线心跳。
|
||||
type AppHeartbeatRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"`
|
||||
UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"`
|
||||
}
|
||||
|
||||
func (x *AppHeartbeatRequest) Reset() {
|
||||
@ -1093,13 +1106,14 @@ func (x *AppHeartbeatRequest) GetSessionId() string {
|
||||
|
||||
// AppHeartbeatResponse 返回本次会话心跳写入时间,并在当前会话仍有效时顺手重签 access token。
|
||||
type AppHeartbeatResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Accepted bool `protobuf:"varint,1,opt,name=accepted,proto3" json:"accepted,omitempty"`
|
||||
HeartbeatAtMs int64 `protobuf:"varint,2,opt,name=heartbeat_at_ms,json=heartbeatAtMs,proto3" json:"heartbeat_at_ms,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
Token *AuthToken `protobuf:"bytes,4,opt,name=token,proto3" json:"token,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Accepted bool `protobuf:"varint,1,opt,name=accepted,proto3" json:"accepted,omitempty"`
|
||||
HeartbeatAtMs int64 `protobuf:"varint,2,opt,name=heartbeat_at_ms,json=heartbeatAtMs,proto3" json:"heartbeat_at_ms,omitempty"`
|
||||
ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"`
|
||||
Token *AuthToken `protobuf:"bytes,4,opt,name=token,proto3" json:"token,omitempty"`
|
||||
}
|
||||
|
||||
func (x *AppHeartbeatResponse) Reset() {
|
||||
@ -1162,127 +1176,244 @@ func (x *AppHeartbeatResponse) GetToken() *AuthToken {
|
||||
|
||||
var File_proto_user_v1_auth_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_proto_user_v1_auth_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x18proto/user/v1/auth.proto\x12\rhyapp.user.v1\x1a\x18proto/user/v1/user.proto\"\x8a\x01\n" +
|
||||
"\x14LoginPasswordRequest\x12.\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12&\n" +
|
||||
"\x0fdisplay_user_id\x18\x02 \x01(\tR\rdisplayUserId\x12\x1a\n" +
|
||||
"\bpassword\x18\x03 \x01(\tR\bpassword\"\xea\x04\n" +
|
||||
"\x16LoginThirdPartyRequest\x12.\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1a\n" +
|
||||
"\bprovider\x18\x02 \x01(\tR\bprovider\x12\x1e\n" +
|
||||
"\n" +
|
||||
"credential\x18\x03 \x01(\tR\n" +
|
||||
"credential\x12\x1a\n" +
|
||||
"\busername\x18\x04 \x01(\tR\busername\x12\x16\n" +
|
||||
"\x06gender\x18\x05 \x01(\tR\x06gender\x12\x18\n" +
|
||||
"\acountry\x18\x06 \x01(\tR\acountry\x12\x1f\n" +
|
||||
"\vinvite_code\x18\a \x01(\tR\n" +
|
||||
"inviteCode\x12\x1b\n" +
|
||||
"\tdevice_id\x18\b \x01(\tR\bdeviceId\x12\x16\n" +
|
||||
"\x06device\x18\t \x01(\tR\x06device\x12\x16\n" +
|
||||
"\x06avatar\x18\n" +
|
||||
" \x01(\tR\x06avatar\x12\x14\n" +
|
||||
"\x05birth\x18\v \x01(\tR\x05birth\x12\x1f\n" +
|
||||
"\vapp_version\x18\f \x01(\tR\n" +
|
||||
"appVersion\x12\x16\n" +
|
||||
"\x06source\x18\r \x01(\tR\x06source\x12\x1a\n" +
|
||||
"\bplatform\x18\x0e \x01(\tR\bplatform\x12\x1a\n" +
|
||||
"\blanguage\x18\x0f \x01(\tR\blanguage\x12\x1d\n" +
|
||||
"\n" +
|
||||
"os_version\x18\x10 \x01(\tR\tosVersion\x12!\n" +
|
||||
"\fbuild_number\x18\x11 \x01(\tR\vbuildNumber\x12\x1a\n" +
|
||||
"\btimezone\x18\x12 \x01(\tR\btimezone\x12'\n" +
|
||||
"\x0finstall_channel\x18\x13 \x01(\tR\x0einstallChannel\x12\x1a\n" +
|
||||
"\bcampaign\x18\x14 \x01(\tR\bcampaign\"\xb8\x01\n" +
|
||||
"\fAuthResponse\x12.\n" +
|
||||
"\x05token\x18\x01 \x01(\v2\x18.hyapp.user.v1.AuthTokenR\x05token\x12\x1e\n" +
|
||||
"\vis_new_user\x18\x02 \x01(\bR\tisNewUser\x12+\n" +
|
||||
"\x11profile_completed\x18\x03 \x01(\bR\x10profileCompleted\x12+\n" +
|
||||
"\x11onboarding_status\x18\x04 \x01(\tR\x10onboardingStatus\"y\n" +
|
||||
"\x12SetPasswordRequest\x12.\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" +
|
||||
"\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1a\n" +
|
||||
"\bpassword\x18\x03 \x01(\tR\bpassword\"8\n" +
|
||||
"\x13SetPasswordResponse\x12!\n" +
|
||||
"\fpassword_set\x18\x01 \x01(\bR\vpasswordSet\"\xcd\x04\n" +
|
||||
"\x19QuickCreateAccountRequest\x12.\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1a\n" +
|
||||
"\bpassword\x18\x02 \x01(\tR\bpassword\x12\x1a\n" +
|
||||
"\busername\x18\x03 \x01(\tR\busername\x12\x16\n" +
|
||||
"\x06avatar\x18\x04 \x01(\tR\x06avatar\x12\x16\n" +
|
||||
"\x06gender\x18\x05 \x01(\tR\x06gender\x12\x18\n" +
|
||||
"\acountry\x18\x06 \x01(\tR\acountry\x12\x1f\n" +
|
||||
"\vinvite_code\x18\a \x01(\tR\n" +
|
||||
"inviteCode\x12\x1b\n" +
|
||||
"\tdevice_id\x18\b \x01(\tR\bdeviceId\x12\x16\n" +
|
||||
"\x06device\x18\t \x01(\tR\x06device\x12\x1d\n" +
|
||||
"\n" +
|
||||
"os_version\x18\n" +
|
||||
" \x01(\tR\tosVersion\x12\x14\n" +
|
||||
"\x05birth\x18\v \x01(\tR\x05birth\x12\x1f\n" +
|
||||
"\vapp_version\x18\f \x01(\tR\n" +
|
||||
"appVersion\x12!\n" +
|
||||
"\fbuild_number\x18\r \x01(\tR\vbuildNumber\x12\x16\n" +
|
||||
"\x06source\x18\x0e \x01(\tR\x06source\x12'\n" +
|
||||
"\x0finstall_channel\x18\x0f \x01(\tR\x0einstallChannel\x12\x1a\n" +
|
||||
"\bcampaign\x18\x10 \x01(\tR\bcampaign\x12\x1a\n" +
|
||||
"\bplatform\x18\x11 \x01(\tR\bplatform\x12\x1a\n" +
|
||||
"\blanguage\x18\x12 \x01(\tR\blanguage\x12\x1a\n" +
|
||||
"\btimezone\x18\x13 \x01(\tR\btimezone\"o\n" +
|
||||
"\x1aQuickCreateAccountResponse\x12.\n" +
|
||||
"\x05token\x18\x01 \x01(\v2\x18.hyapp.user.v1.AuthTokenR\x05token\x12!\n" +
|
||||
"\fpassword_set\x18\x02 \x01(\bR\vpasswordSet\"j\n" +
|
||||
"\x13RefreshTokenRequest\x12.\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12#\n" +
|
||||
"\rrefresh_token\x18\x02 \x01(\tR\frefreshToken\"F\n" +
|
||||
"\x14RefreshTokenResponse\x12.\n" +
|
||||
"\x05token\x18\x01 \x01(\v2\x18.hyapp.user.v1.AuthTokenR\x05token\"\x83\x01\n" +
|
||||
"\rLogoutRequest\x12.\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1d\n" +
|
||||
"\n" +
|
||||
"session_id\x18\x02 \x01(\tR\tsessionId\x12#\n" +
|
||||
"\rrefresh_token\x18\x03 \x01(\tR\frefreshToken\"*\n" +
|
||||
"\x0eLogoutResponse\x12\x18\n" +
|
||||
"\arevoked\x18\x01 \x01(\bR\arevoked\"\xdc\x01\n" +
|
||||
"\x19RecordLoginBlockedRequest\x12.\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x18\n" +
|
||||
"\achannel\x18\x02 \x01(\tR\achannel\x12\x1a\n" +
|
||||
"\bplatform\x18\x03 \x01(\tR\bplatform\x12\x1a\n" +
|
||||
"\blanguage\x18\x04 \x01(\tR\blanguage\x12\x1a\n" +
|
||||
"\btimezone\x18\x05 \x01(\tR\btimezone\x12!\n" +
|
||||
"\fblock_reason\x18\x06 \x01(\tR\vblockReason\"8\n" +
|
||||
"\x1aRecordLoginBlockedResponse\x12\x1a\n" +
|
||||
"\brecorded\x18\x01 \x01(\bR\brecorded\"}\n" +
|
||||
"\x13AppHeartbeatRequest\x12.\n" +
|
||||
"\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" +
|
||||
"\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1d\n" +
|
||||
"\n" +
|
||||
"session_id\x18\x03 \x01(\tR\tsessionId\"\xb0\x01\n" +
|
||||
"\x14AppHeartbeatResponse\x12\x1a\n" +
|
||||
"\baccepted\x18\x01 \x01(\bR\baccepted\x12&\n" +
|
||||
"\x0fheartbeat_at_ms\x18\x02 \x01(\x03R\rheartbeatAtMs\x12$\n" +
|
||||
"\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\x12.\n" +
|
||||
"\x05token\x18\x04 \x01(\v2\x18.hyapp.user.v1.AuthTokenR\x05token2\xdc\x05\n" +
|
||||
"\vAuthService\x12Q\n" +
|
||||
"\rLoginPassword\x12#.hyapp.user.v1.LoginPasswordRequest\x1a\x1b.hyapp.user.v1.AuthResponse\x12U\n" +
|
||||
"\x0fLoginThirdParty\x12%.hyapp.user.v1.LoginThirdPartyRequest\x1a\x1b.hyapp.user.v1.AuthResponse\x12T\n" +
|
||||
"\vSetPassword\x12!.hyapp.user.v1.SetPasswordRequest\x1a\".hyapp.user.v1.SetPasswordResponse\x12i\n" +
|
||||
"\x12QuickCreateAccount\x12(.hyapp.user.v1.QuickCreateAccountRequest\x1a).hyapp.user.v1.QuickCreateAccountResponse\x12W\n" +
|
||||
"\fRefreshToken\x12\".hyapp.user.v1.RefreshTokenRequest\x1a#.hyapp.user.v1.RefreshTokenResponse\x12E\n" +
|
||||
"\x06Logout\x12\x1c.hyapp.user.v1.LogoutRequest\x1a\x1d.hyapp.user.v1.LogoutResponse\x12i\n" +
|
||||
"\x12RecordLoginBlocked\x12(.hyapp.user.v1.RecordLoginBlockedRequest\x1a).hyapp.user.v1.RecordLoginBlockedResponse\x12W\n" +
|
||||
"\fAppHeartbeat\x12\".hyapp.user.v1.AppHeartbeatRequest\x1a#.hyapp.user.v1.AppHeartbeatResponseB&Z$hyapp.local/api/proto/user/v1;userv1b\x06proto3"
|
||||
var file_proto_user_v1_auth_proto_rawDesc = []byte{
|
||||
0x0a, 0x18, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f,
|
||||
0x61, 0x75, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x68, 0x79, 0x61, 0x70,
|
||||
0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x1a, 0x18, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x22, 0x8a, 0x01, 0x0a, 0x14, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 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, 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, 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, 0xea, 0x04, 0x0a, 0x16, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50,
|
||||
0x61, 0x72, 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, 0x1a, 0x0a, 0x08, 0x70,
|
||||
0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70,
|
||||
0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x72, 0x65,
|
||||
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x72, 0x79, 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, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65,
|
||||
0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63,
|
||||
0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x09, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61,
|
||||
0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61,
|
||||
0x74, 0x61, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x69, 0x72, 0x74, 0x68, 0x18, 0x0b, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x05, 0x62, 0x69, 0x72, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x70, 0x70,
|
||||
0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
|
||||
0x61, 0x70, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72,
|
||||
0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x0e,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1a,
|
||||
0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x73,
|
||||
0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
|
||||
0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x75, 0x69,
|
||||
0x6c, 0x64, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08,
|
||||
0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
|
||||
0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x74,
|
||||
0x61, 0x6c, 0x6c, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x13, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65,
|
||||
0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x6d, 0x70, 0x61, 0x69, 0x67, 0x6e, 0x18, 0x14, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x6d, 0x70, 0x61, 0x69, 0x67, 0x6e, 0x22, 0xb8, 0x01,
|
||||
0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e,
|
||||
0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 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, 0x1e,
|
||||
0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x4e, 0x65, 0x77, 0x55, 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, 0x03, 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, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69,
|
||||
0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x79, 0x0a, 0x12, 0x53, 0x65, 0x74, 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, 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, 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, 0x38, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||
0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61,
|
||||
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x0b, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x53, 0x65, 0x74, 0x22, 0xcd, 0x04,
|
||||
0x0a, 0x19, 0x51, 0x75, 0x69, 0x63, 0x6b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63,
|
||||
0x6f, 0x75, 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, 0x1a, 0x0a, 0x08, 0x70,
|
||||
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70,
|
||||
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 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, 0x16, 0x0a, 0x06, 0x67,
|
||||
0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x65, 0x6e,
|
||||
0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x06,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 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, 0x12, 0x1b,
|
||||
0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x64,
|
||||
0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x76,
|
||||
0x69, 0x63, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x69, 0x72, 0x74, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x05, 0x62, 0x69, 0x72, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x5f,
|
||||
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61,
|
||||
0x70, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x75, 0x69,
|
||||
0x6c, 0x64, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 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, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x5f,
|
||||
0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69,
|
||||
0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1a, 0x0a,
|
||||
0x08, 0x63, 0x61, 0x6d, 0x70, 0x61, 0x69, 0x67, 0x6e, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x08, 0x63, 0x61, 0x6d, 0x70, 0x61, 0x69, 0x67, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61,
|
||||
0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61,
|
||||
0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67,
|
||||
0x65, 0x18, 0x12, 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, 0x13, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x22, 0x6f, 0x0a,
|
||||
0x1a, 0x51, 0x75, 0x69, 0x63, 0x6b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x74,
|
||||
0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 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, 0x21, 0x0a, 0x0c, 0x70,
|
||||
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x08, 0x52, 0x0b, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x53, 0x65, 0x74, 0x22, 0x6a,
|
||||
0x0a, 0x13, 0x52, 0x65, 0x66, 0x72, 0x65, 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, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68,
|
||||
0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65,
|
||||
0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x46, 0x0a, 0x14, 0x52, 0x65,
|
||||
0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 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, 0x22, 0x83, 0x01, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 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, 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, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74,
|
||||
0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x66, 0x72,
|
||||
0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x2a, 0x0a, 0x0e, 0x4c, 0x6f, 0x67, 0x6f,
|
||||
0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65,
|
||||
0x76, 0x6f, 0x6b, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x76,
|
||||
0x6f, 0x6b, 0x65, 0x64, 0x22, 0xdc, 0x01, 0x0a, 0x19, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4c,
|
||||
0x6f, 0x67, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 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, 0x18, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1a, 0x0a, 0x08,
|
||||
0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
|
||||
0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67,
|
||||
0x75, 0x61, 0x67, 0x65, 0x18, 0x04, 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, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65,
|
||||
0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e,
|
||||
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x61,
|
||||
0x73, 0x6f, 0x6e, 0x22, 0x38, 0x0a, 0x1a, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4c, 0x6f, 0x67,
|
||||
0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 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, 0x22, 0x7d, 0x0a,
|
||||
0x13, 0x41, 0x70, 0x70, 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, 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, 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, 0x22, 0xb0, 0x01, 0x0a,
|
||||
0x14, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 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, 0x26, 0x0a, 0x0f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x5f, 0x61,
|
||||
0x74, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x68, 0x65, 0x61, 0x72,
|
||||
0x74, 0x62, 0x65, 0x61, 0x74, 0x41, 0x74, 0x4d, 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, 0x12,
|
||||
0x2e, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 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, 0x32,
|
||||
0xdc, 0x05, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
|
||||
0x51, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
|
||||
0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73,
|
||||
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x12, 0x55, 0x0a, 0x0f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x54, 0x68, 0x69, 0x72, 0x64,
|
||||
0x50, 0x61, 0x72, 0x74, 0x79, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73,
|
||||
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x54, 0x68, 0x69, 0x72, 0x64,
|
||||
0x50, 0x61, 0x72, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x68,
|
||||
0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74,
|
||||
0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0b, 0x53, 0x65, 0x74,
|
||||
0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70,
|
||||
0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73,
|
||||
0x77, 0x6f, 0x72, 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, 0x53, 0x65, 0x74, 0x50,
|
||||
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x69, 0x0a, 0x12, 0x51, 0x75, 0x69, 0x63, 0x6b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73,
|
||||
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x69, 0x63, 0x6b, 0x43, 0x72, 0x65, 0x61, 0x74,
|
||||
0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 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,
|
||||
0x51, 0x75, 0x69, 0x63, 0x6b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x52, 0x65,
|
||||
0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61,
|
||||
0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65,
|
||||
0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23,
|
||||
0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52,
|
||||
0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x06, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x12, 0x1c, 0x2e,
|
||||
0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f,
|
||||
0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x68, 0x79,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x6f,
|
||||
0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x52, 0x65,
|
||||
0x63, 0x6f, 0x72, 0x64, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64,
|
||||
0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x65, 0x64, 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, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x72,
|
||||
0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x75, 0x73,
|
||||
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 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, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61,
|
||||
0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 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 (
|
||||
file_proto_user_v1_auth_proto_rawDescOnce sync.Once
|
||||
file_proto_user_v1_auth_proto_rawDescData []byte
|
||||
file_proto_user_v1_auth_proto_rawDescData = file_proto_user_v1_auth_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_proto_user_v1_auth_proto_rawDescGZIP() []byte {
|
||||
file_proto_user_v1_auth_proto_rawDescOnce.Do(func() {
|
||||
file_proto_user_v1_auth_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_user_v1_auth_proto_rawDesc), len(file_proto_user_v1_auth_proto_rawDesc)))
|
||||
file_proto_user_v1_auth_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_user_v1_auth_proto_rawDescData)
|
||||
})
|
||||
return file_proto_user_v1_auth_proto_rawDescData
|
||||
}
|
||||
@ -1353,7 +1484,7 @@ func file_proto_user_v1_auth_proto_init() {
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_user_v1_auth_proto_rawDesc), len(file_proto_user_v1_auth_proto_rawDesc)),
|
||||
RawDescriptor: file_proto_user_v1_auth_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 15,
|
||||
NumExtensions: 0,
|
||||
@ -1364,6 +1495,7 @@ func file_proto_user_v1_auth_proto_init() {
|
||||
MessageInfos: file_proto_user_v1_auth_proto_msgTypes,
|
||||
}.Build()
|
||||
File_proto_user_v1_auth_proto = out.File
|
||||
file_proto_user_v1_auth_proto_rawDesc = nil
|
||||
file_proto_user_v1_auth_proto_goTypes = nil
|
||||
file_proto_user_v1_auth_proto_depIdxs = nil
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.6.2
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v7.35.0
|
||||
// source: proto/user/v1/auth.proto
|
||||
|
||||
@ -158,28 +158,28 @@ type AuthServiceServer interface {
|
||||
type UnimplementedAuthServiceServer struct{}
|
||||
|
||||
func (UnimplementedAuthServiceServer) LoginPassword(context.Context, *LoginPasswordRequest) (*AuthResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method LoginPassword not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method LoginPassword not implemented")
|
||||
}
|
||||
func (UnimplementedAuthServiceServer) LoginThirdParty(context.Context, *LoginThirdPartyRequest) (*AuthResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method LoginThirdParty not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method LoginThirdParty not implemented")
|
||||
}
|
||||
func (UnimplementedAuthServiceServer) SetPassword(context.Context, *SetPasswordRequest) (*SetPasswordResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetPassword not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetPassword not implemented")
|
||||
}
|
||||
func (UnimplementedAuthServiceServer) QuickCreateAccount(context.Context, *QuickCreateAccountRequest) (*QuickCreateAccountResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method QuickCreateAccount not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method QuickCreateAccount not implemented")
|
||||
}
|
||||
func (UnimplementedAuthServiceServer) RefreshToken(context.Context, *RefreshTokenRequest) (*RefreshTokenResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RefreshToken not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RefreshToken not implemented")
|
||||
}
|
||||
func (UnimplementedAuthServiceServer) Logout(context.Context, *LogoutRequest) (*LogoutResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method Logout not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Logout not implemented")
|
||||
}
|
||||
func (UnimplementedAuthServiceServer) RecordLoginBlocked(context.Context, *RecordLoginBlockedRequest) (*RecordLoginBlockedResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RecordLoginBlocked not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RecordLoginBlocked not implemented")
|
||||
}
|
||||
func (UnimplementedAuthServiceServer) AppHeartbeat(context.Context, *AppHeartbeatRequest) (*AppHeartbeatResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AppHeartbeat not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AppHeartbeat not implemented")
|
||||
}
|
||||
func (UnimplementedAuthServiceServer) mustEmbedUnimplementedAuthServiceServer() {}
|
||||
func (UnimplementedAuthServiceServer) testEmbeddedByValue() {}
|
||||
@ -192,7 +192,7 @@ type UnsafeAuthServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAuthServiceServer(s grpc.ServiceRegistrar, srv AuthServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAuthServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAuthServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.6.2
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v7.35.0
|
||||
// source: proto/user/v1/host.proto
|
||||
|
||||
@ -327,67 +327,67 @@ type UserHostServiceServer interface {
|
||||
type UnimplementedUserHostServiceServer struct{}
|
||||
|
||||
func (UnimplementedUserHostServiceServer) SearchAgencies(context.Context, *SearchAgenciesRequest) (*SearchAgenciesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SearchAgencies not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SearchAgencies not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) ApplyToAgency(context.Context, *ApplyToAgencyRequest) (*ApplyToAgencyResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ApplyToAgency not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ApplyToAgency not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) ReviewAgencyApplication(context.Context, *ReviewAgencyApplicationRequest) (*ReviewAgencyApplicationResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ReviewAgencyApplication not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ReviewAgencyApplication not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) KickAgencyHost(context.Context, *KickAgencyHostRequest) (*KickAgencyHostResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method KickAgencyHost not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method KickAgencyHost not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) InviteAgency(context.Context, *InviteAgencyRequest) (*InviteAgencyResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method InviteAgency not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method InviteAgency not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) InviteBD(context.Context, *InviteBDRequest) (*InviteBDResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method InviteBD not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method InviteBD not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) InviteHost(context.Context, *InviteHostRequest) (*InviteHostResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method InviteHost not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method InviteHost not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) ListBDLeaderBDs(context.Context, *ListBDLeaderBDsRequest) (*ListBDLeaderBDsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListBDLeaderBDs not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListBDLeaderBDs not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) ListBDLeaderAgencies(context.Context, *ListBDLeaderAgenciesRequest) (*ListBDLeaderAgenciesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListBDLeaderAgencies not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListBDLeaderAgencies not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) ListBDAgencies(context.Context, *ListBDAgenciesRequest) (*ListBDAgenciesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListBDAgencies not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListBDAgencies not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) ListRoleInvitations(context.Context, *ListRoleInvitationsRequest) (*ListRoleInvitationsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRoleInvitations not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRoleInvitations not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) ProcessRoleInvitation(context.Context, *ProcessRoleInvitationRequest) (*ProcessRoleInvitationResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessRoleInvitation not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessRoleInvitation not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) GetHostProfile(context.Context, *GetHostProfileRequest) (*GetHostProfileResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetHostProfile not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetHostProfile not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) GetBDProfile(context.Context, *GetBDProfileRequest) (*GetBDProfileResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetBDProfile not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetBDProfile not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) GetCoinSellerProfile(context.Context, *GetCoinSellerProfileRequest) (*GetCoinSellerProfileResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetCoinSellerProfile not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetCoinSellerProfile not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) ListActiveCoinSellersInMyRegion(context.Context, *ListActiveCoinSellersInMyRegionRequest) (*ListActiveCoinSellersInMyRegionResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListActiveCoinSellersInMyRegion not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListActiveCoinSellersInMyRegion not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) GetUserRoleSummary(context.Context, *GetUserRoleSummaryRequest) (*GetUserRoleSummaryResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetUserRoleSummary not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetUserRoleSummary not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) GetAgency(context.Context, *GetAgencyRequest) (*GetAgencyResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetAgency not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetAgency not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) CheckBusinessCapability(context.Context, *CheckBusinessCapabilityRequest) (*CheckBusinessCapabilityResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CheckBusinessCapability not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CheckBusinessCapability not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) GetAgencyMembers(context.Context, *GetAgencyMembersRequest) (*GetAgencyMembersResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetAgencyMembers not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetAgencyMembers not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) GetAgencyApplications(context.Context, *GetAgencyApplicationsRequest) (*GetAgencyApplicationsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetAgencyApplications not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetAgencyApplications not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostServiceServer) mustEmbedUnimplementedUserHostServiceServer() {}
|
||||
func (UnimplementedUserHostServiceServer) testEmbeddedByValue() {}
|
||||
@ -400,7 +400,7 @@ type UnsafeUserHostServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterUserHostServiceServer(s grpc.ServiceRegistrar, srv UserHostServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedUserHostServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedUserHostServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -1037,31 +1037,31 @@ type UserHostAdminServiceServer interface {
|
||||
type UnimplementedUserHostAdminServiceServer struct{}
|
||||
|
||||
func (UnimplementedUserHostAdminServiceServer) CreateBDLeader(context.Context, *CreateBDLeaderRequest) (*CreateBDLeaderResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateBDLeader not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateBDLeader not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostAdminServiceServer) CreateBD(context.Context, *CreateBDRequest) (*CreateBDResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateBD not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateBD not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostAdminServiceServer) SetBDStatus(context.Context, *SetBDStatusRequest) (*SetBDStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetBDStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetBDStatus not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostAdminServiceServer) CreateCoinSeller(context.Context, *CreateCoinSellerRequest) (*CreateCoinSellerResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateCoinSeller not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateCoinSeller not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostAdminServiceServer) SetCoinSellerStatus(context.Context, *SetCoinSellerStatusRequest) (*SetCoinSellerStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetCoinSellerStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetCoinSellerStatus not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostAdminServiceServer) CreateAgency(context.Context, *CreateAgencyRequest) (*CreateAgencyResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateAgency not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateAgency not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostAdminServiceServer) CloseAgency(context.Context, *CloseAgencyRequest) (*CloseAgencyResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CloseAgency not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CloseAgency not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostAdminServiceServer) DeleteAgency(context.Context, *DeleteAgencyRequest) (*DeleteAgencyResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method DeleteAgency not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeleteAgency not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostAdminServiceServer) SetAgencyJoinEnabled(context.Context, *SetAgencyJoinEnabledRequest) (*SetAgencyJoinEnabledResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetAgencyJoinEnabled not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetAgencyJoinEnabled not implemented")
|
||||
}
|
||||
func (UnimplementedUserHostAdminServiceServer) mustEmbedUnimplementedUserHostAdminServiceServer() {}
|
||||
func (UnimplementedUserHostAdminServiceServer) testEmbeddedByValue() {}
|
||||
@ -1074,7 +1074,7 @@ type UnsafeUserHostAdminServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterUserHostAdminServiceServer(s grpc.ServiceRegistrar, srv UserHostAdminServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedUserHostAdminServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedUserHostAdminServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.6.2
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v7.35.0
|
||||
// source: proto/user/v1/user.proto
|
||||
|
||||
@ -262,52 +262,52 @@ type UserServiceServer interface {
|
||||
type UnimplementedUserServiceServer struct{}
|
||||
|
||||
func (UnimplementedUserServiceServer) GetUser(context.Context, *GetUserRequest) (*GetUserResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetUser not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetUser not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) GetInviteAttribution(context.Context, *GetInviteAttributionRequest) (*GetInviteAttributionResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetInviteAttribution not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetInviteAttribution not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) BusinessUserLookup(context.Context, *BusinessUserLookupRequest) (*BusinessUserLookupResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method BusinessUserLookup not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method BusinessUserLookup not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) GetMyProfileStats(context.Context, *GetMyProfileStatsRequest) (*GetMyProfileStatsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetMyProfileStats not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetMyProfileStats not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) BatchGetUsers(context.Context, *BatchGetUsersRequest) (*BatchGetUsersResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method BatchGetUsers not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method BatchGetUsers not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) ListUserIDs(context.Context, *ListUserIDsRequest) (*ListUserIDsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListUserIDs not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListUserIDs not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) GetUserMicLifetimeStats(context.Context, *GetUserMicLifetimeStatsRequest) (*GetUserMicLifetimeStatsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetUserMicLifetimeStats not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetUserMicLifetimeStats not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) UpdateUserProfile(context.Context, *UpdateUserProfileRequest) (*UpdateUserProfileResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateUserProfile not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateUserProfile not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) UpdateUserProfileBackground(context.Context, *UpdateUserProfileBackgroundRequest) (*UpdateUserProfileBackgroundResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateUserProfileBackground not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateUserProfileBackground not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) ChangeUserCountry(context.Context, *ChangeUserCountryRequest) (*ChangeUserCountryResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ChangeUserCountry not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ChangeUserCountry not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) AdminChangeUserCountry(context.Context, *AdminChangeUserCountryRequest) (*ChangeUserCountryResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminChangeUserCountry not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminChangeUserCountry not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) SetUserStatus(context.Context, *SetUserStatusRequest) (*SetUserStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetUserStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetUserStatus not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) CreateManagerUserBlock(context.Context, *CreateManagerUserBlockRequest) (*CreateManagerUserBlockResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateManagerUserBlock not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateManagerUserBlock not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) ListManagerUserBlocks(context.Context, *ListManagerUserBlocksRequest) (*ListManagerUserBlocksResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListManagerUserBlocks not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListManagerUserBlocks not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) UnblockManagerUser(context.Context, *UnblockManagerUserRequest) (*UnblockManagerUserResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UnblockManagerUser not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UnblockManagerUser not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) CompleteOnboarding(context.Context, *CompleteOnboardingRequest) (*CompleteOnboardingResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CompleteOnboarding not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CompleteOnboarding not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) mustEmbedUnimplementedUserServiceServer() {}
|
||||
func (UnimplementedUserServiceServer) testEmbeddedByValue() {}
|
||||
@ -320,7 +320,7 @@ type UnsafeUserServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterUserServiceServer(s grpc.ServiceRegistrar, srv UserServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedUserServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedUserServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -873,37 +873,37 @@ type UserSocialServiceServer interface {
|
||||
type UnimplementedUserSocialServiceServer struct{}
|
||||
|
||||
func (UnimplementedUserSocialServiceServer) RecordProfileVisit(context.Context, *RecordProfileVisitRequest) (*RecordProfileVisitResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RecordProfileVisit not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RecordProfileVisit not implemented")
|
||||
}
|
||||
func (UnimplementedUserSocialServiceServer) ListProfileVisitors(context.Context, *ListProfileVisitorsRequest) (*ListProfileVisitorsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListProfileVisitors not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListProfileVisitors not implemented")
|
||||
}
|
||||
func (UnimplementedUserSocialServiceServer) FollowUser(context.Context, *FollowUserRequest) (*FollowUserResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method FollowUser not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method FollowUser not implemented")
|
||||
}
|
||||
func (UnimplementedUserSocialServiceServer) UnfollowUser(context.Context, *UnfollowUserRequest) (*UnfollowUserResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UnfollowUser not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UnfollowUser not implemented")
|
||||
}
|
||||
func (UnimplementedUserSocialServiceServer) ListFollowing(context.Context, *ListFollowingRequest) (*ListFollowingResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListFollowing not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListFollowing not implemented")
|
||||
}
|
||||
func (UnimplementedUserSocialServiceServer) ApplyFriend(context.Context, *ApplyFriendRequest) (*ApplyFriendResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ApplyFriend not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ApplyFriend not implemented")
|
||||
}
|
||||
func (UnimplementedUserSocialServiceServer) AcceptFriendApplication(context.Context, *AcceptFriendApplicationRequest) (*AcceptFriendApplicationResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AcceptFriendApplication not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AcceptFriendApplication not implemented")
|
||||
}
|
||||
func (UnimplementedUserSocialServiceServer) DeleteFriend(context.Context, *DeleteFriendRequest) (*DeleteFriendResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method DeleteFriend not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeleteFriend not implemented")
|
||||
}
|
||||
func (UnimplementedUserSocialServiceServer) ListFriends(context.Context, *ListFriendsRequest) (*ListFriendsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListFriends not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListFriends not implemented")
|
||||
}
|
||||
func (UnimplementedUserSocialServiceServer) ListFriendApplications(context.Context, *ListFriendApplicationsRequest) (*ListFriendApplicationsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListFriendApplications not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListFriendApplications not implemented")
|
||||
}
|
||||
func (UnimplementedUserSocialServiceServer) SubmitReport(context.Context, *SubmitReportRequest) (*SubmitReportResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SubmitReport not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SubmitReport not implemented")
|
||||
}
|
||||
func (UnimplementedUserSocialServiceServer) mustEmbedUnimplementedUserSocialServiceServer() {}
|
||||
func (UnimplementedUserSocialServiceServer) testEmbeddedByValue() {}
|
||||
@ -916,7 +916,7 @@ type UnsafeUserSocialServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterUserSocialServiceServer(s grpc.ServiceRegistrar, srv UserSocialServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedUserSocialServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedUserSocialServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -1320,28 +1320,28 @@ type UserCPServiceServer interface {
|
||||
type UnimplementedUserCPServiceServer struct{}
|
||||
|
||||
func (UnimplementedUserCPServiceServer) ListCPApplications(context.Context, *ListCPApplicationsRequest) (*ListCPApplicationsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListCPApplications not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListCPApplications not implemented")
|
||||
}
|
||||
func (UnimplementedUserCPServiceServer) AcceptCPApplication(context.Context, *AcceptCPApplicationRequest) (*AcceptCPApplicationResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AcceptCPApplication not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AcceptCPApplication not implemented")
|
||||
}
|
||||
func (UnimplementedUserCPServiceServer) RejectCPApplication(context.Context, *RejectCPApplicationRequest) (*RejectCPApplicationResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RejectCPApplication not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RejectCPApplication not implemented")
|
||||
}
|
||||
func (UnimplementedUserCPServiceServer) ListCPRelationships(context.Context, *ListCPRelationshipsRequest) (*ListCPRelationshipsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListCPRelationships not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListCPRelationships not implemented")
|
||||
}
|
||||
func (UnimplementedUserCPServiceServer) ListCPIntimacyLeaderboard(context.Context, *ListCPIntimacyLeaderboardRequest) (*ListCPIntimacyLeaderboardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListCPIntimacyLeaderboard not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListCPIntimacyLeaderboard not implemented")
|
||||
}
|
||||
func (UnimplementedUserCPServiceServer) PrepareBreakCPRelationship(context.Context, *PrepareBreakCPRelationshipRequest) (*PrepareBreakCPRelationshipResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method PrepareBreakCPRelationship not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PrepareBreakCPRelationship not implemented")
|
||||
}
|
||||
func (UnimplementedUserCPServiceServer) ConfirmBreakCPRelationship(context.Context, *ConfirmBreakCPRelationshipRequest) (*ConfirmBreakCPRelationshipResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ConfirmBreakCPRelationship not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ConfirmBreakCPRelationship not implemented")
|
||||
}
|
||||
func (UnimplementedUserCPServiceServer) CancelBreakCPRelationship(context.Context, *CancelBreakCPRelationshipRequest) (*CancelBreakCPRelationshipResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CancelBreakCPRelationship not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CancelBreakCPRelationship not implemented")
|
||||
}
|
||||
func (UnimplementedUserCPServiceServer) mustEmbedUnimplementedUserCPServiceServer() {}
|
||||
func (UnimplementedUserCPServiceServer) testEmbeddedByValue() {}
|
||||
@ -1354,7 +1354,7 @@ type UnsafeUserCPServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterUserCPServiceServer(s grpc.ServiceRegistrar, srv UserCPServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedUserCPServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedUserCPServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -1614,10 +1614,10 @@ type UserCPInternalServiceServer interface {
|
||||
type UnimplementedUserCPInternalServiceServer struct{}
|
||||
|
||||
func (UnimplementedUserCPInternalServiceServer) ConsumeRoomGiftCPEvent(context.Context, *ConsumeRoomGiftCPEventRequest) (*ConsumeRoomGiftCPEventResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ConsumeRoomGiftCPEvent not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ConsumeRoomGiftCPEvent not implemented")
|
||||
}
|
||||
func (UnimplementedUserCPInternalServiceServer) ListCPWeeklyRankEntries(context.Context, *ListCPWeeklyRankEntriesRequest) (*ListCPWeeklyRankEntriesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListCPWeeklyRankEntries not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListCPWeeklyRankEntries not implemented")
|
||||
}
|
||||
func (UnimplementedUserCPInternalServiceServer) mustEmbedUnimplementedUserCPInternalServiceServer() {}
|
||||
func (UnimplementedUserCPInternalServiceServer) testEmbeddedByValue() {}
|
||||
@ -1630,7 +1630,7 @@ type UnsafeUserCPInternalServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterUserCPInternalServiceServer(s grpc.ServiceRegistrar, srv UserCPInternalServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedUserCPInternalServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedUserCPInternalServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -1797,19 +1797,19 @@ type UserCronServiceServer interface {
|
||||
type UnimplementedUserCronServiceServer struct{}
|
||||
|
||||
func (UnimplementedUserCronServiceServer) ProcessLoginIPRiskBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessLoginIPRiskBatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessLoginIPRiskBatch not implemented")
|
||||
}
|
||||
func (UnimplementedUserCronServiceServer) ProcessRegionRebuildBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessRegionRebuildBatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessRegionRebuildBatch not implemented")
|
||||
}
|
||||
func (UnimplementedUserCronServiceServer) CompensateMicOpenSessions(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CompensateMicOpenSessions not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CompensateMicOpenSessions not implemented")
|
||||
}
|
||||
func (UnimplementedUserCronServiceServer) ExpireManagerUserBlocks(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ExpireManagerUserBlocks not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ExpireManagerUserBlocks not implemented")
|
||||
}
|
||||
func (UnimplementedUserCronServiceServer) RefreshCPIntimacyLeaderboard(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RefreshCPIntimacyLeaderboard not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RefreshCPIntimacyLeaderboard not implemented")
|
||||
}
|
||||
func (UnimplementedUserCronServiceServer) mustEmbedUnimplementedUserCronServiceServer() {}
|
||||
func (UnimplementedUserCronServiceServer) testEmbeddedByValue() {}
|
||||
@ -1822,7 +1822,7 @@ type UnsafeUserCronServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterUserCronServiceServer(s grpc.ServiceRegistrar, srv UserCronServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedUserCronServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedUserCronServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -2016,10 +2016,10 @@ type UserDeviceServiceServer interface {
|
||||
type UnimplementedUserDeviceServiceServer struct{}
|
||||
|
||||
func (UnimplementedUserDeviceServiceServer) BindPushToken(context.Context, *BindPushTokenRequest) (*BindPushTokenResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method BindPushToken not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method BindPushToken not implemented")
|
||||
}
|
||||
func (UnimplementedUserDeviceServiceServer) DeletePushToken(context.Context, *DeletePushTokenRequest) (*DeletePushTokenResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method DeletePushToken not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeletePushToken not implemented")
|
||||
}
|
||||
func (UnimplementedUserDeviceServiceServer) mustEmbedUnimplementedUserDeviceServiceServer() {}
|
||||
func (UnimplementedUserDeviceServiceServer) testEmbeddedByValue() {}
|
||||
@ -2032,7 +2032,7 @@ type UnsafeUserDeviceServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterUserDeviceServiceServer(s grpc.ServiceRegistrar, srv UserDeviceServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedUserDeviceServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedUserDeviceServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -2147,7 +2147,7 @@ type AppRegistryServiceServer interface {
|
||||
type UnimplementedAppRegistryServiceServer struct{}
|
||||
|
||||
func (UnimplementedAppRegistryServiceServer) ResolveApp(context.Context, *ResolveAppRequest) (*ResolveAppResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ResolveApp not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ResolveApp not implemented")
|
||||
}
|
||||
func (UnimplementedAppRegistryServiceServer) mustEmbedUnimplementedAppRegistryServiceServer() {}
|
||||
func (UnimplementedAppRegistryServiceServer) testEmbeddedByValue() {}
|
||||
@ -2160,7 +2160,7 @@ type UnsafeAppRegistryServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterAppRegistryServiceServer(s grpc.ServiceRegistrar, srv AppRegistryServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedAppRegistryServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedAppRegistryServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -2268,10 +2268,10 @@ type CountryAdminServiceServer interface {
|
||||
type UnimplementedCountryAdminServiceServer struct{}
|
||||
|
||||
func (UnimplementedCountryAdminServiceServer) ListCountries(context.Context, *ListCountriesRequest) (*ListCountriesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListCountries not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListCountries not implemented")
|
||||
}
|
||||
func (UnimplementedCountryAdminServiceServer) UpdateCountry(context.Context, *UpdateCountryRequest) (*CountryResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateCountry not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateCountry not implemented")
|
||||
}
|
||||
func (UnimplementedCountryAdminServiceServer) mustEmbedUnimplementedCountryAdminServiceServer() {}
|
||||
func (UnimplementedCountryAdminServiceServer) testEmbeddedByValue() {}
|
||||
@ -2284,7 +2284,7 @@ type UnsafeCountryAdminServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterCountryAdminServiceServer(s grpc.ServiceRegistrar, srv CountryAdminServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedCountryAdminServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedCountryAdminServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -2412,10 +2412,10 @@ type CountryQueryServiceServer interface {
|
||||
type UnimplementedCountryQueryServiceServer struct{}
|
||||
|
||||
func (UnimplementedCountryQueryServiceServer) ListRegistrationCountries(context.Context, *ListRegistrationCountriesRequest) (*ListRegistrationCountriesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRegistrationCountries not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRegistrationCountries not implemented")
|
||||
}
|
||||
func (UnimplementedCountryQueryServiceServer) ListLoginRiskBlockedCountries(context.Context, *ListLoginRiskBlockedCountriesRequest) (*ListLoginRiskBlockedCountriesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListLoginRiskBlockedCountries not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListLoginRiskBlockedCountries not implemented")
|
||||
}
|
||||
func (UnimplementedCountryQueryServiceServer) mustEmbedUnimplementedCountryQueryServiceServer() {}
|
||||
func (UnimplementedCountryQueryServiceServer) testEmbeddedByValue() {}
|
||||
@ -2428,7 +2428,7 @@ type UnsafeCountryQueryServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterCountryQueryServiceServer(s grpc.ServiceRegistrar, srv CountryQueryServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedCountryQueryServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedCountryQueryServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -2584,16 +2584,16 @@ type RegionAdminServiceServer interface {
|
||||
type UnimplementedRegionAdminServiceServer struct{}
|
||||
|
||||
func (UnimplementedRegionAdminServiceServer) ListRegions(context.Context, *ListRegionsRequest) (*ListRegionsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRegions not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRegions not implemented")
|
||||
}
|
||||
func (UnimplementedRegionAdminServiceServer) GetRegion(context.Context, *GetRegionRequest) (*RegionResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetRegion not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRegion not implemented")
|
||||
}
|
||||
func (UnimplementedRegionAdminServiceServer) UpdateRegion(context.Context, *UpdateRegionRequest) (*RegionResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateRegion not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateRegion not implemented")
|
||||
}
|
||||
func (UnimplementedRegionAdminServiceServer) ReplaceRegionCountries(context.Context, *ReplaceRegionCountriesRequest) (*RegionResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ReplaceRegionCountries not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ReplaceRegionCountries not implemented")
|
||||
}
|
||||
func (UnimplementedRegionAdminServiceServer) mustEmbedUnimplementedRegionAdminServiceServer() {}
|
||||
func (UnimplementedRegionAdminServiceServer) testEmbeddedByValue() {}
|
||||
@ -2606,7 +2606,7 @@ type UnsafeRegionAdminServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterRegionAdminServiceServer(s grpc.ServiceRegistrar, srv RegionAdminServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedRegionAdminServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedRegionAdminServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -2843,25 +2843,25 @@ type UserIdentityServiceServer interface {
|
||||
type UnimplementedUserIdentityServiceServer struct{}
|
||||
|
||||
func (UnimplementedUserIdentityServiceServer) GetUserIdentity(context.Context, *GetUserIdentityRequest) (*GetUserIdentityResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetUserIdentity not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetUserIdentity not implemented")
|
||||
}
|
||||
func (UnimplementedUserIdentityServiceServer) ResolveDisplayUserID(context.Context, *ResolveDisplayUserIDRequest) (*ResolveDisplayUserIDResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ResolveDisplayUserID not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ResolveDisplayUserID not implemented")
|
||||
}
|
||||
func (UnimplementedUserIdentityServiceServer) ChangeDisplayUserID(context.Context, *ChangeDisplayUserIDRequest) (*ChangeDisplayUserIDResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ChangeDisplayUserID not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ChangeDisplayUserID not implemented")
|
||||
}
|
||||
func (UnimplementedUserIdentityServiceServer) ApplyPrettyDisplayUserID(context.Context, *ApplyPrettyDisplayUserIDRequest) (*ApplyPrettyDisplayUserIDResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ApplyPrettyDisplayUserID not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ApplyPrettyDisplayUserID not implemented")
|
||||
}
|
||||
func (UnimplementedUserIdentityServiceServer) ListAvailablePrettyDisplayIDs(context.Context, *ListAvailablePrettyDisplayIDsRequest) (*ListAvailablePrettyDisplayIDsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListAvailablePrettyDisplayIDs not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListAvailablePrettyDisplayIDs not implemented")
|
||||
}
|
||||
func (UnimplementedUserIdentityServiceServer) ApplyPrettyDisplayIDFromPool(context.Context, *ApplyPrettyDisplayIDFromPoolRequest) (*ApplyPrettyDisplayIDFromPoolResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ApplyPrettyDisplayIDFromPool not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ApplyPrettyDisplayIDFromPool not implemented")
|
||||
}
|
||||
func (UnimplementedUserIdentityServiceServer) ExpirePrettyDisplayUserID(context.Context, *ExpirePrettyDisplayUserIDRequest) (*ExpirePrettyDisplayUserIDResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ExpirePrettyDisplayUserID not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ExpirePrettyDisplayUserID not implemented")
|
||||
}
|
||||
func (UnimplementedUserIdentityServiceServer) mustEmbedUnimplementedUserIdentityServiceServer() {}
|
||||
func (UnimplementedUserIdentityServiceServer) testEmbeddedByValue() {}
|
||||
@ -2874,7 +2874,7 @@ type UnsafeUserIdentityServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterUserIdentityServiceServer(s grpc.ServiceRegistrar, srv UserIdentityServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedUserIdentityServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedUserIdentityServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -3177,25 +3177,25 @@ type UserPrettyDisplayIDAdminServiceServer interface {
|
||||
type UnimplementedUserPrettyDisplayIDAdminServiceServer struct{}
|
||||
|
||||
func (UnimplementedUserPrettyDisplayIDAdminServiceServer) ListPrettyDisplayIDPools(context.Context, *ListPrettyDisplayIDPoolsRequest) (*ListPrettyDisplayIDPoolsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListPrettyDisplayIDPools not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListPrettyDisplayIDPools not implemented")
|
||||
}
|
||||
func (UnimplementedUserPrettyDisplayIDAdminServiceServer) CreatePrettyDisplayIDPool(context.Context, *CreatePrettyDisplayIDPoolRequest) (*PrettyDisplayIDPoolResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreatePrettyDisplayIDPool not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreatePrettyDisplayIDPool not implemented")
|
||||
}
|
||||
func (UnimplementedUserPrettyDisplayIDAdminServiceServer) UpdatePrettyDisplayIDPool(context.Context, *UpdatePrettyDisplayIDPoolRequest) (*PrettyDisplayIDPoolResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdatePrettyDisplayIDPool not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdatePrettyDisplayIDPool not implemented")
|
||||
}
|
||||
func (UnimplementedUserPrettyDisplayIDAdminServiceServer) GeneratePrettyDisplayIDs(context.Context, *GeneratePrettyDisplayIDsRequest) (*GeneratePrettyDisplayIDsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GeneratePrettyDisplayIDs not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GeneratePrettyDisplayIDs not implemented")
|
||||
}
|
||||
func (UnimplementedUserPrettyDisplayIDAdminServiceServer) ListPrettyDisplayIDs(context.Context, *ListPrettyDisplayIDsRequest) (*ListPrettyDisplayIDsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListPrettyDisplayIDs not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListPrettyDisplayIDs not implemented")
|
||||
}
|
||||
func (UnimplementedUserPrettyDisplayIDAdminServiceServer) SetPrettyDisplayIDStatus(context.Context, *SetPrettyDisplayIDStatusRequest) (*PrettyDisplayIDResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetPrettyDisplayIDStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetPrettyDisplayIDStatus not implemented")
|
||||
}
|
||||
func (UnimplementedUserPrettyDisplayIDAdminServiceServer) AdminGrantPrettyDisplayID(context.Context, *AdminGrantPrettyDisplayIDRequest) (*AdminGrantPrettyDisplayIDResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminGrantPrettyDisplayID not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminGrantPrettyDisplayID not implemented")
|
||||
}
|
||||
func (UnimplementedUserPrettyDisplayIDAdminServiceServer) mustEmbedUnimplementedUserPrettyDisplayIDAdminServiceServer() {
|
||||
}
|
||||
@ -3209,7 +3209,7 @@ type UnsafeUserPrettyDisplayIDAdminServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterUserPrettyDisplayIDAdminServiceServer(s grpc.ServiceRegistrar, srv UserPrettyDisplayIDAdminServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedUserPrettyDisplayIDAdminServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedUserPrettyDisplayIDAdminServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.6.2
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v7.35.0
|
||||
// source: proto/wallet/v1/wallet.proto
|
||||
|
||||
@ -93,13 +93,13 @@ type WalletCronServiceServer interface {
|
||||
type UnimplementedWalletCronServiceServer struct{}
|
||||
|
||||
func (UnimplementedWalletCronServiceServer) ProcessHostSalaryDailySettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessHostSalaryDailySettlementBatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessHostSalaryDailySettlementBatch not implemented")
|
||||
}
|
||||
func (UnimplementedWalletCronServiceServer) ProcessHostSalaryHalfMonthSettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessHostSalaryHalfMonthSettlementBatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessHostSalaryHalfMonthSettlementBatch not implemented")
|
||||
}
|
||||
func (UnimplementedWalletCronServiceServer) ProcessHostSalaryMonthEndBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ProcessHostSalaryMonthEndBatch not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ProcessHostSalaryMonthEndBatch not implemented")
|
||||
}
|
||||
func (UnimplementedWalletCronServiceServer) mustEmbedUnimplementedWalletCronServiceServer() {}
|
||||
func (UnimplementedWalletCronServiceServer) testEmbeddedByValue() {}
|
||||
@ -112,7 +112,7 @@ type UnsafeWalletCronServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterWalletCronServiceServer(s grpc.ServiceRegistrar, srv WalletCronServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedWalletCronServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedWalletCronServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
@ -1289,247 +1289,247 @@ type WalletServiceServer interface {
|
||||
type UnimplementedWalletServiceServer struct{}
|
||||
|
||||
func (UnimplementedWalletServiceServer) DebitGift(context.Context, *DebitGiftRequest) (*DebitGiftResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method DebitGift not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DebitGift not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) BatchDebitGift(context.Context, *BatchDebitGiftRequest) (*BatchDebitGiftResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method BatchDebitGift not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method BatchDebitGift not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) DebitRobotGift(context.Context, *DebitRobotGiftRequest) (*DebitGiftResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method DebitRobotGift not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DebitRobotGift not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GetBalances(context.Context, *GetBalancesRequest) (*GetBalancesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetBalances not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetBalances not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GetActiveHostSalaryPolicy(context.Context, *GetActiveHostSalaryPolicyRequest) (*GetActiveHostSalaryPolicyResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetActiveHostSalaryPolicy not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetActiveHostSalaryPolicy not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GetHostSalaryProgress(context.Context, *GetHostSalaryProgressRequest) (*GetHostSalaryProgressResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetHostSalaryProgress not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetHostSalaryProgress not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) AdminCreditAsset(context.Context, *AdminCreditAssetRequest) (*AdminCreditAssetResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminCreditAsset not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminCreditAsset not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) AdminCreditCoinSellerStock(context.Context, *AdminCreditCoinSellerStockRequest) (*AdminCreditCoinSellerStockResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AdminCreditCoinSellerStock not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdminCreditCoinSellerStock not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) TransferCoinFromSeller(context.Context, *TransferCoinFromSellerRequest) (*TransferCoinFromSellerResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method TransferCoinFromSeller not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method TransferCoinFromSeller not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListCoinSellerSalaryExchangeRateTiers(context.Context, *ListCoinSellerSalaryExchangeRateTiersRequest) (*ListCoinSellerSalaryExchangeRateTiersResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListCoinSellerSalaryExchangeRateTiers not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListCoinSellerSalaryExchangeRateTiers not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ExchangeSalaryToCoin(context.Context, *ExchangeSalaryToCoinRequest) (*ExchangeSalaryToCoinResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ExchangeSalaryToCoin not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ExchangeSalaryToCoin not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) TransferSalaryToCoinSeller(context.Context, *TransferSalaryToCoinSellerRequest) (*TransferSalaryToCoinSellerResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method TransferSalaryToCoinSeller not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method TransferSalaryToCoinSeller not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListResources(context.Context, *ListResourcesRequest) (*ListResourcesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListResources not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListResources not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GetResource(context.Context, *GetResourceRequest) (*GetResourceResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetResource not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetResource not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) CreateResource(context.Context, *CreateResourceRequest) (*ResourceResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateResource not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateResource not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) UpdateResource(context.Context, *UpdateResourceRequest) (*ResourceResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateResource not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateResource not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) SetResourceStatus(context.Context, *SetResourceStatusRequest) (*ResourceResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetResourceStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetResourceStatus not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListResourceGroups(context.Context, *ListResourceGroupsRequest) (*ListResourceGroupsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListResourceGroups not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListResourceGroups not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GetResourceGroup(context.Context, *GetResourceGroupRequest) (*GetResourceGroupResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetResourceGroup not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetResourceGroup not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) CreateResourceGroup(context.Context, *CreateResourceGroupRequest) (*ResourceGroupResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateResourceGroup not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateResourceGroup not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) UpdateResourceGroup(context.Context, *UpdateResourceGroupRequest) (*ResourceGroupResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateResourceGroup not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateResourceGroup not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) SetResourceGroupStatus(context.Context, *SetResourceGroupStatusRequest) (*ResourceGroupResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetResourceGroupStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetResourceGroupStatus not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListGiftConfigs(context.Context, *ListGiftConfigsRequest) (*ListGiftConfigsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListGiftConfigs not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListGiftConfigs not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListGiftTypeConfigs(context.Context, *ListGiftTypeConfigsRequest) (*ListGiftTypeConfigsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListGiftTypeConfigs not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListGiftTypeConfigs not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) CreateGiftConfig(context.Context, *CreateGiftConfigRequest) (*GiftConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateGiftConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateGiftConfig not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) UpdateGiftConfig(context.Context, *UpdateGiftConfigRequest) (*GiftConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateGiftConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateGiftConfig not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) SetGiftConfigStatus(context.Context, *SetGiftConfigStatusRequest) (*GiftConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetGiftConfigStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetGiftConfigStatus not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) DeleteGiftConfig(context.Context, *DeleteGiftConfigRequest) (*GiftConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method DeleteGiftConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeleteGiftConfig not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) UpsertGiftTypeConfig(context.Context, *UpsertGiftTypeConfigRequest) (*GiftTypeConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpsertGiftTypeConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpsertGiftTypeConfig not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GrantResource(context.Context, *GrantResourceRequest) (*ResourceGrantResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GrantResource not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GrantResource not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GrantResourceGroup(context.Context, *GrantResourceGroupRequest) (*ResourceGrantResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GrantResourceGroup not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GrantResourceGroup not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListUserResources(context.Context, *ListUserResourcesRequest) (*ListUserResourcesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListUserResources not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListUserResources not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) EquipUserResource(context.Context, *EquipUserResourceRequest) (*EquipUserResourceResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method EquipUserResource not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method EquipUserResource not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) UnequipUserResource(context.Context, *UnequipUserResourceRequest) (*UnequipUserResourceResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UnequipUserResource not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UnequipUserResource not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) BatchGetUserEquippedResources(context.Context, *BatchGetUserEquippedResourcesRequest) (*BatchGetUserEquippedResourcesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method BatchGetUserEquippedResources not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method BatchGetUserEquippedResources not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListResourceGrants(context.Context, *ListResourceGrantsRequest) (*ListResourceGrantsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListResourceGrants not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListResourceGrants not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListResourceShopItems(context.Context, *ListResourceShopItemsRequest) (*ListResourceShopItemsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListResourceShopItems not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListResourceShopItems not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) UpsertResourceShopItems(context.Context, *UpsertResourceShopItemsRequest) (*UpsertResourceShopItemsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpsertResourceShopItems not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpsertResourceShopItems not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) SetResourceShopItemStatus(context.Context, *SetResourceShopItemStatusRequest) (*ResourceShopItemResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetResourceShopItemStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetResourceShopItemStatus not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) PurchaseResourceShopItem(context.Context, *PurchaseResourceShopItemRequest) (*PurchaseResourceShopItemResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method PurchaseResourceShopItem not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PurchaseResourceShopItem not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListRechargeBills(context.Context, *ListRechargeBillsRequest) (*ListRechargeBillsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRechargeBills not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRechargeBills not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GetWalletOverview(context.Context, *GetWalletOverviewRequest) (*GetWalletOverviewResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetWalletOverview not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetWalletOverview not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GetWalletValueSummary(context.Context, *GetWalletValueSummaryRequest) (*GetWalletValueSummaryResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetWalletValueSummary not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetWalletValueSummary not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GetUserGiftWall(context.Context, *GetUserGiftWallRequest) (*GetUserGiftWallResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetUserGiftWall not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetUserGiftWall not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListRechargeProducts(context.Context, *ListRechargeProductsRequest) (*ListRechargeProductsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRechargeProducts not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRechargeProducts not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ConfirmGooglePayment(context.Context, *ConfirmGooglePaymentRequest) (*ConfirmGooglePaymentResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ConfirmGooglePayment not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ConfirmGooglePayment not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListAdminRechargeProducts(context.Context, *ListAdminRechargeProductsRequest) (*ListAdminRechargeProductsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListAdminRechargeProducts not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListAdminRechargeProducts not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) CreateRechargeProduct(context.Context, *CreateRechargeProductRequest) (*RechargeProductResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateRechargeProduct not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateRechargeProduct not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) UpdateRechargeProduct(context.Context, *UpdateRechargeProductRequest) (*RechargeProductResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateRechargeProduct not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateRechargeProduct not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) DeleteRechargeProduct(context.Context, *DeleteRechargeProductRequest) (*DeleteRechargeProductResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method DeleteRechargeProduct not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeleteRechargeProduct not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListThirdPartyPaymentChannels(context.Context, *ListThirdPartyPaymentChannelsRequest) (*ListThirdPartyPaymentChannelsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListThirdPartyPaymentChannels not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListThirdPartyPaymentChannels not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) SetThirdPartyPaymentMethodStatus(context.Context, *SetThirdPartyPaymentMethodStatusRequest) (*ThirdPartyPaymentMethodResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SetThirdPartyPaymentMethodStatus not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetThirdPartyPaymentMethodStatus not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) UpdateThirdPartyPaymentRate(context.Context, *UpdateThirdPartyPaymentRateRequest) (*ThirdPartyPaymentMethodResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateThirdPartyPaymentRate not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateThirdPartyPaymentRate not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListH5RechargeOptions(context.Context, *H5RechargeOptionsRequest) (*H5RechargeOptionsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListH5RechargeOptions not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListH5RechargeOptions not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) CreateH5RechargeOrder(context.Context, *CreateH5RechargeOrderRequest) (*H5RechargeOrderResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateH5RechargeOrder not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateH5RechargeOrder not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) SubmitH5RechargeTx(context.Context, *SubmitH5RechargeTxRequest) (*H5RechargeOrderResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method SubmitH5RechargeTx not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SubmitH5RechargeTx not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GetH5RechargeOrder(context.Context, *GetH5RechargeOrderRequest) (*H5RechargeOrderResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetH5RechargeOrder not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetH5RechargeOrder not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) HandleMifapayNotify(context.Context, *HandleMifapayNotifyRequest) (*HandleMifapayNotifyResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method HandleMifapayNotify not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method HandleMifapayNotify not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GetDiamondExchangeConfig(context.Context, *GetDiamondExchangeConfigRequest) (*GetDiamondExchangeConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetDiamondExchangeConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetDiamondExchangeConfig not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListWalletTransactions(context.Context, *ListWalletTransactionsRequest) (*ListWalletTransactionsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListWalletTransactions not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListWalletTransactions not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListVipPackages(context.Context, *ListVipPackagesRequest) (*ListVipPackagesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListVipPackages not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListVipPackages not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GetMyVip(context.Context, *GetMyVipRequest) (*GetMyVipResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetMyVip not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetMyVip not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) PurchaseVip(context.Context, *PurchaseVipRequest) (*PurchaseVipResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method PurchaseVip not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PurchaseVip not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) DebitCPBreakupFee(context.Context, *DebitCPBreakupFeeRequest) (*DebitCPBreakupFeeResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method DebitCPBreakupFee not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DebitCPBreakupFee not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GrantVip(context.Context, *GrantVipRequest) (*GrantVipResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GrantVip not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GrantVip not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListAdminVipLevels(context.Context, *ListAdminVipLevelsRequest) (*ListAdminVipLevelsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListAdminVipLevels not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListAdminVipLevels not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) UpdateAdminVipLevels(context.Context, *UpdateAdminVipLevelsRequest) (*UpdateAdminVipLevelsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateAdminVipLevels not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateAdminVipLevels not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) CreditTaskReward(context.Context, *CreditTaskRewardRequest) (*CreditTaskRewardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreditTaskReward not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreditTaskReward not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) CreditLuckyGiftReward(context.Context, *CreditLuckyGiftRewardRequest) (*CreditLuckyGiftRewardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreditLuckyGiftReward not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreditLuckyGiftReward not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) CreditRoomTurnoverReward(context.Context, *CreditRoomTurnoverRewardRequest) (*CreditRoomTurnoverRewardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreditRoomTurnoverReward not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreditRoomTurnoverReward not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) CreditInviteActivityReward(context.Context, *CreditInviteActivityRewardRequest) (*CreditInviteActivityRewardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreditInviteActivityReward not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreditInviteActivityReward not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) CreditAgencyOpeningReward(context.Context, *CreditAgencyOpeningRewardRequest) (*CreditAgencyOpeningRewardResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreditAgencyOpeningReward not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreditAgencyOpeningReward not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ApplyGameCoinChange(context.Context, *ApplyGameCoinChangeRequest) (*ApplyGameCoinChangeResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ApplyGameCoinChange not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ApplyGameCoinChange not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GetRedPacketConfig(context.Context, *GetRedPacketConfigRequest) (*GetRedPacketConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetRedPacketConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRedPacketConfig not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) UpdateRedPacketConfig(context.Context, *UpdateRedPacketConfigRequest) (*UpdateRedPacketConfigResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method UpdateRedPacketConfig not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateRedPacketConfig not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) CreateRedPacket(context.Context, *CreateRedPacketRequest) (*CreateRedPacketResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method CreateRedPacket not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateRedPacket not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ClaimRedPacket(context.Context, *ClaimRedPacketRequest) (*ClaimRedPacketResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ClaimRedPacket not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ClaimRedPacket not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ListRedPackets(context.Context, *ListRedPacketsRequest) (*ListRedPacketsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListRedPackets not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRedPackets not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) GetRedPacket(context.Context, *GetRedPacketRequest) (*GetRedPacketResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetRedPacket not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRedPacket not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) ExpireRedPackets(context.Context, *ExpireRedPacketsRequest) (*ExpireRedPacketsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ExpireRedPackets not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ExpireRedPackets not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) RetryRedPacketRefund(context.Context, *RetryRedPacketRefundRequest) (*RetryRedPacketRefundResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RetryRedPacketRefund not implemented")
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RetryRedPacketRefund not implemented")
|
||||
}
|
||||
func (UnimplementedWalletServiceServer) mustEmbedUnimplementedWalletServiceServer() {}
|
||||
func (UnimplementedWalletServiceServer) testEmbeddedByValue() {}
|
||||
@ -1542,7 +1542,7 @@ type UnsafeWalletServiceServer interface {
|
||||
}
|
||||
|
||||
func RegisterWalletServiceServer(s grpc.ServiceRegistrar, srv WalletServiceServer) {
|
||||
// If the following call panics, it indicates UnimplementedWalletServiceServer was
|
||||
// If the following call pancis, it indicates UnimplementedWalletServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
|
||||
@ -24,6 +24,7 @@ services:
|
||||
command: ["sh", "mqbroker", "-n", "rocketmq-namesrv:9876", "-c", "/home/rocketmq/broker.conf"]
|
||||
ports:
|
||||
- "19009:10909"
|
||||
- "10911:10911"
|
||||
- "19011:10911"
|
||||
volumes:
|
||||
- ${DEPLOY_PLATFORM_ROOT:-../deploy-platform}/deploy/rocketmq/broker.conf:/home/rocketmq/broker.conf:ro
|
||||
|
||||
@ -111,6 +111,29 @@ type RoomEvent struct {
|
||||
Attributes map[string]string `json:"attributes,omitempty"`
|
||||
}
|
||||
|
||||
func (event RoomEvent) MarshalJSON() ([]byte, error) {
|
||||
type roomEventAlias RoomEvent
|
||||
payload, err := json.Marshal(roomEventAlias(event))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var merged map[string]any
|
||||
if err := json.Unmarshal(payload, &merged); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for key, value := range event.Attributes {
|
||||
if strings.TrimSpace(key) == "" {
|
||||
continue
|
||||
}
|
||||
if _, exists := merged[key]; exists {
|
||||
// 顶层协议字段由 RoomEvent 结构体负责,attributes 只能补充展示字段,不能覆盖事件身份。
|
||||
continue
|
||||
}
|
||||
merged[key] = value
|
||||
}
|
||||
return json.Marshal(merged)
|
||||
}
|
||||
|
||||
// RoomEntryVehicleSnapshot 是房间系统消息里可直接渲染的座驾素材快照。
|
||||
// 它故意不包含 wallet 内部状态,只保留客户端展示和过期兜底需要的字段。
|
||||
type RoomEntryVehicleSnapshot struct {
|
||||
|
||||
@ -48,6 +48,24 @@ func TestRealTencentIMCreateSendAndDestroyGroup(t *testing.T) {
|
||||
if err := realImportAccount(ctx, client, memberUserID); err != nil {
|
||||
t.Fatalf("real Tencent IM account import failed: %v", err)
|
||||
}
|
||||
c2cEventID := fmt.Sprintf("codex_real_im_c2c_%d", nowMS)
|
||||
c2cPayload, err := json.Marshal(map[string]any{
|
||||
"event_id": c2cEventID,
|
||||
"event_type": "codex_real_im_c2c_probe",
|
||||
"sent_at_ms": nowMS,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("marshal c2c smoke payload failed: %v", err)
|
||||
}
|
||||
if err := client.PublishUserCustomMessage(ctx, CustomUserMessage{
|
||||
ToAccount: strconv.FormatInt(memberUserID, 10),
|
||||
EventID: c2cEventID,
|
||||
Desc: "codex_real_im_c2c_probe",
|
||||
Ext: "im_c2c_smoke",
|
||||
PayloadJSON: c2cPayload,
|
||||
}); err != nil {
|
||||
t.Fatalf("real Tencent IM send C2C custom message failed: %v", err)
|
||||
}
|
||||
if err := realAddGroupMember(ctx, client, groupID, memberUserID); err != nil {
|
||||
t.Fatalf("real Tencent IM add group member failed: %v", err)
|
||||
}
|
||||
@ -82,7 +100,7 @@ func TestRealTencentIMCreateSendAndDestroyGroup(t *testing.T) {
|
||||
t.Fatalf("real Tencent IM delete group member failed: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("real Tencent IM smoke passed: sdk_app_id=%d group_id=%s event_id=%s removed_user_id=%d", cfg.SDKAppID, groupID, eventID, memberUserID)
|
||||
t.Logf("real Tencent IM smoke passed: sdk_app_id=%d group_id=%s group_event_id=%s c2c_event_id=%s removed_user_id=%d", cfg.SDKAppID, groupID, eventID, c2cEventID, memberUserID)
|
||||
}
|
||||
|
||||
func realImportAccount(ctx context.Context, client *RESTClient, userID int64) error {
|
||||
|
||||
@ -97,6 +97,60 @@ func TestRESTClientPublishRoomEventBuildsCustomMessage(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRESTClientPublishRoomEventFlattensAttributesForClientPayload(t *testing.T) {
|
||||
var capturedBody map[string]any
|
||||
client := newTestRESTClient(t, func(request *http.Request) (*http.Response, error) {
|
||||
if err := json.NewDecoder(request.Body).Decode(&capturedBody); err != nil {
|
||||
t.Fatalf("decode request body failed: %v", err)
|
||||
}
|
||||
return okRESTResponse(), nil
|
||||
})
|
||||
|
||||
err := client.PublishRoomEvent(context.Background(), RoomEvent{
|
||||
GroupID: "room_1001",
|
||||
EventID: "evt-robot-lucky-1",
|
||||
RoomID: "room-1001",
|
||||
EventType: "lucky_gift_drawn",
|
||||
ActorUserID: 10001,
|
||||
TargetUserID: 10002,
|
||||
GiftValue: 500,
|
||||
Attributes: map[string]string{
|
||||
"event_type": "should_not_override",
|
||||
"draw_id": "robot_lucky_draw_1",
|
||||
"gift_id": "gift_lucky_1",
|
||||
"gift_count": "1",
|
||||
"pool_id": "robot_lucky_display",
|
||||
"multiplier_ppm": "5000000",
|
||||
"effective_reward_coins": "500",
|
||||
"reward_status": "granted",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("PublishRoomEvent failed: %v", err)
|
||||
}
|
||||
|
||||
body, ok := capturedBody["MsgBody"].([]any)
|
||||
if !ok || len(body) != 1 {
|
||||
t.Fatalf("unexpected msg body: %+v", capturedBody["MsgBody"])
|
||||
}
|
||||
element := body[0].(map[string]any)
|
||||
content := element["MsgContent"].(map[string]any)
|
||||
var payload map[string]any
|
||||
if err := json.Unmarshal([]byte(content["Data"].(string)), &payload); err != nil {
|
||||
t.Fatalf("decode custom data failed: %v", err)
|
||||
}
|
||||
if payload["event_type"] != "lucky_gift_drawn" {
|
||||
t.Fatalf("attributes must not override top-level event_type: %+v", payload)
|
||||
}
|
||||
if payload["draw_id"] != "robot_lucky_draw_1" || payload["effective_reward_coins"] != "500" || payload["reward_status"] != "granted" {
|
||||
t.Fatalf("lucky gift attributes must be flattened for existing clients: %+v", payload)
|
||||
}
|
||||
attributes, ok := payload["attributes"].(map[string]any)
|
||||
if !ok || attributes["effective_reward_coins"] != "500" {
|
||||
t.Fatalf("attributes must still be kept for diagnostics and fallback clients: %+v", payload["attributes"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestRESTClientPublishGroupCustomMessageBuildsBroadcastPayload(t *testing.T) {
|
||||
var capturedBody map[string]any
|
||||
client := newTestRESTClient(t, func(request *http.Request) (*http.Response, error) {
|
||||
|
||||
@ -272,6 +272,7 @@ func main() {
|
||||
userclient.NewGRPC(userConn),
|
||||
auditHandler,
|
||||
gamemanagementmodule.WithRobotProfileSource(robotProfileSource),
|
||||
gamemanagementmodule.WithRobotAppearanceServices(walletclient.NewGRPC(walletConn), activityclient.NewGRPC(activityConn)),
|
||||
),
|
||||
GiftDiamond: giftdiamondmodule.New(walletDB, auditHandler),
|
||||
Health: healthmodule.New(store, redisClient, jobStatus),
|
||||
@ -291,7 +292,7 @@ func main() {
|
||||
RegistrationReward: registrationrewardmodule.New(activityclient.NewGRPC(activityConn), userDB, auditHandler),
|
||||
RegionBlock: regionblockmodule.New(userDB, auditHandler),
|
||||
Resource: resourcemodule.New(walletclient.NewGRPC(walletConn), store, userDB, cfg.WalletService.RequestTimeout, auditHandler),
|
||||
RoomAdmin: roomadminmodule.New(userDB, roomClient, robotClient, auditHandler),
|
||||
RoomAdmin: roomadminmodule.New(userDB, store, roomClient, robotClient, auditHandler),
|
||||
RoomRocket: roomrocketmodule.New(roomClient, auditHandler),
|
||||
RoomTurnoverReward: roomturnoverrewardmodule.New(activityclient.NewGRPC(activityConn), userDB, auditHandler),
|
||||
Search: searchmodule.New(store),
|
||||
|
||||
@ -61,6 +61,7 @@ type Client interface {
|
||||
UpsertLevelTrack(ctx context.Context, req *activityv1.UpsertLevelTrackRequest) (*activityv1.UpsertLevelTrackResponse, error)
|
||||
UpsertLevelRule(ctx context.Context, req *activityv1.UpsertLevelRuleRequest) (*activityv1.UpsertLevelRuleResponse, error)
|
||||
UpsertLevelTier(ctx context.Context, req *activityv1.UpsertLevelTierRequest) (*activityv1.UpsertLevelTierResponse, error)
|
||||
SetUserLevel(ctx context.Context, req *activityv1.SetUserLevelRequest) (*activityv1.SetUserLevelResponse, error)
|
||||
CreateInboxMessage(ctx context.Context, req *activityv1.CreateInboxMessageRequest) (*activityv1.CreateInboxMessageResponse, error)
|
||||
CreateFanoutJob(ctx context.Context, req *activityv1.CreateFanoutJobRequest) (*activityv1.CreateFanoutJobResponse, error)
|
||||
}
|
||||
@ -79,6 +80,7 @@ type GRPCClient struct {
|
||||
cpWeeklyRankClient activityv1.AdminCPWeeklyRankServiceClient
|
||||
luckyGiftClient activityv1.AdminLuckyGiftServiceClient
|
||||
broadcastClient activityv1.BroadcastServiceClient
|
||||
levelClient activityv1.GrowthLevelServiceClient
|
||||
growthClient activityv1.AdminGrowthLevelServiceClient
|
||||
messageClient activityv1.MessageInboxServiceClient
|
||||
}
|
||||
@ -98,6 +100,7 @@ func NewGRPC(conn grpc.ClientConnInterface) *GRPCClient {
|
||||
cpWeeklyRankClient: activityv1.NewAdminCPWeeklyRankServiceClient(conn),
|
||||
luckyGiftClient: activityv1.NewAdminLuckyGiftServiceClient(conn),
|
||||
broadcastClient: activityv1.NewBroadcastServiceClient(conn),
|
||||
levelClient: activityv1.NewGrowthLevelServiceClient(conn),
|
||||
growthClient: activityv1.NewAdminGrowthLevelServiceClient(conn),
|
||||
messageClient: activityv1.NewMessageInboxServiceClient(conn),
|
||||
}
|
||||
@ -307,6 +310,10 @@ func (c *GRPCClient) UpsertLevelTier(ctx context.Context, req *activityv1.Upsert
|
||||
return c.growthClient.UpsertLevelTier(ctx, req)
|
||||
}
|
||||
|
||||
func (c *GRPCClient) SetUserLevel(ctx context.Context, req *activityv1.SetUserLevelRequest) (*activityv1.SetUserLevelResponse, error) {
|
||||
return c.levelClient.SetUserLevel(ctx, req)
|
||||
}
|
||||
|
||||
func (c *GRPCClient) CreateInboxMessage(ctx context.Context, req *activityv1.CreateInboxMessageRequest) (*activityv1.CreateInboxMessageResponse, error) {
|
||||
return c.messageClient.CreateInboxMessage(ctx, req)
|
||||
}
|
||||
|
||||
@ -21,6 +21,8 @@ type Client interface {
|
||||
UpdateRoomRocketConfig(ctx context.Context, req UpdateRoomRocketConfigRequest) (RoomRocketConfig, error)
|
||||
GetRoomSeatConfig(ctx context.Context) (RoomSeatConfig, error)
|
||||
UpdateRoomSeatConfig(ctx context.Context, req UpdateRoomSeatConfigRequest) (RoomSeatConfig, error)
|
||||
GetHumanRoomRobotConfig(ctx context.Context) (HumanRoomRobotConfig, error)
|
||||
UpdateHumanRoomRobotConfig(ctx context.Context, req UpdateHumanRoomRobotConfigRequest) (HumanRoomRobotConfig, error)
|
||||
ListRoomPins(ctx context.Context, req ListRoomPinsRequest) (ListRoomPinsResult, error)
|
||||
CreateRoomPin(ctx context.Context, req CreateRoomPinRequest) (RoomPin, error)
|
||||
CancelRoomPin(ctx context.Context, req CancelRoomPinRequest) (RoomPin, error)
|
||||
@ -162,6 +164,38 @@ type UpdateRoomSeatConfigRequest struct {
|
||||
DefaultSeatCount int32
|
||||
}
|
||||
|
||||
type HumanRoomRobotConfig struct {
|
||||
AppCode string
|
||||
Enabled bool
|
||||
CandidateRoomMaxOnline int32
|
||||
RoomFullStopOnline int32
|
||||
RoomTargetMinOnline int32
|
||||
RoomTargetMaxOnline int32
|
||||
RobotStayMinMS int64
|
||||
RobotStayMaxMS int64
|
||||
RobotReplaceMinMS int64
|
||||
RobotReplaceMaxMS int64
|
||||
NormalGiftIntervalMS int64
|
||||
NormalGiftIntervalMinMS int64
|
||||
NormalGiftIntervalMaxMS int64
|
||||
GiftIDs []string
|
||||
LuckyGiftIDs []string
|
||||
SuperLuckyGiftIDs []string
|
||||
LuckyComboMin int64
|
||||
LuckyComboMax int64
|
||||
LuckyPauseMinMS int64
|
||||
LuckyPauseMaxMS int64
|
||||
MaxGiftSenders int64
|
||||
UpdatedByAdminID uint64
|
||||
CreatedAtMS int64
|
||||
UpdatedAtMS int64
|
||||
}
|
||||
|
||||
type UpdateHumanRoomRobotConfigRequest struct {
|
||||
Config HumanRoomRobotConfig
|
||||
AdminID uint64
|
||||
}
|
||||
|
||||
type RoomPinRoom struct {
|
||||
RoomID string
|
||||
RoomShortID string
|
||||
@ -226,6 +260,11 @@ type RobotRoomGiftRule struct {
|
||||
LuckyComboMax int64
|
||||
LuckyPauseMinMS int64
|
||||
LuckyPauseMaxMS int64
|
||||
RobotStayMinMS int64
|
||||
RobotStayMaxMS int64
|
||||
RobotReplaceMinMS int64
|
||||
RobotReplaceMaxMS int64
|
||||
MaxGiftSenders int64
|
||||
}
|
||||
|
||||
type RobotRoom struct {
|
||||
@ -238,6 +277,8 @@ type RobotRoom struct {
|
||||
Status string
|
||||
OwnerRobotUserID int64
|
||||
RobotUserIDs []int64
|
||||
ActiveRobotCount int32
|
||||
SeatCount int32
|
||||
GiftRule RobotRoomGiftRule
|
||||
CreatedByAdminID uint64
|
||||
CreatedAtMS int64
|
||||
@ -263,6 +304,8 @@ type CreateRobotRoomRequest struct {
|
||||
RoomName string
|
||||
RoomAvatar string
|
||||
VisibleRegionID int64
|
||||
OwnerCountryCode string
|
||||
SeatCount int32
|
||||
GiftRule RobotRoomGiftRule
|
||||
AdminID uint64
|
||||
}
|
||||
@ -415,6 +458,26 @@ func (c *GRPCClient) UpdateRoomSeatConfig(ctx context.Context, req UpdateRoomSea
|
||||
return roomSeatConfigFromProto(resp.GetConfig()), nil
|
||||
}
|
||||
|
||||
func (c *GRPCClient) GetHumanRoomRobotConfig(ctx context.Context) (HumanRoomRobotConfig, error) {
|
||||
resp, err := c.queryClient.AdminGetHumanRoomRobotConfig(ctx, &roomv1.AdminGetHumanRoomRobotConfigRequest{Meta: requestMeta(ctx, "", 0, "admin-get-human-room-robot-config")})
|
||||
if err != nil {
|
||||
return HumanRoomRobotConfig{}, err
|
||||
}
|
||||
return humanRoomRobotConfigFromProto(resp.GetConfig()), nil
|
||||
}
|
||||
|
||||
func (c *GRPCClient) UpdateHumanRoomRobotConfig(ctx context.Context, req UpdateHumanRoomRobotConfigRequest) (HumanRoomRobotConfig, error) {
|
||||
resp, err := c.client.AdminUpdateHumanRoomRobotConfig(ctx, &roomv1.AdminUpdateHumanRoomRobotConfigRequest{
|
||||
Meta: requestMeta(ctx, "", int64(req.AdminID), "admin-update-human-room-robot-config"),
|
||||
Config: humanRoomRobotConfigToProto(req.Config),
|
||||
AdminId: req.AdminID,
|
||||
})
|
||||
if err != nil {
|
||||
return HumanRoomRobotConfig{}, err
|
||||
}
|
||||
return humanRoomRobotConfigFromProto(resp.GetConfig()), nil
|
||||
}
|
||||
|
||||
func (c *GRPCClient) ListRoomPins(ctx context.Context, req ListRoomPinsRequest) (ListRoomPinsResult, error) {
|
||||
resp, err := c.queryClient.AdminListRoomPins(ctx, &roomv1.AdminListRoomPinsRequest{
|
||||
Meta: requestMeta(ctx, "", 0, "admin-list-room-pins"),
|
||||
@ -491,6 +554,8 @@ func (c *GRPCClient) CreateRobotRoom(ctx context.Context, req CreateRobotRoomReq
|
||||
RoomName: strings.TrimSpace(req.RoomName),
|
||||
RoomAvatar: strings.TrimSpace(req.RoomAvatar),
|
||||
VisibleRegionId: req.VisibleRegionID,
|
||||
OwnerCountryCode: strings.ToUpper(strings.TrimSpace(req.OwnerCountryCode)),
|
||||
SeatCount: req.SeatCount,
|
||||
GiftRule: robotRoomGiftRuleToProto(req.GiftRule),
|
||||
AdminId: req.AdminID,
|
||||
})
|
||||
@ -655,6 +720,69 @@ func roomSeatConfigFromProto(input *roomv1.AdminRoomSeatConfig) RoomSeatConfig {
|
||||
}
|
||||
}
|
||||
|
||||
func humanRoomRobotConfigFromProto(input *roomv1.AdminHumanRoomRobotConfig) HumanRoomRobotConfig {
|
||||
if input == nil {
|
||||
return HumanRoomRobotConfig{}
|
||||
}
|
||||
config := HumanRoomRobotConfig{
|
||||
AppCode: input.GetAppCode(),
|
||||
Enabled: input.GetEnabled(),
|
||||
CandidateRoomMaxOnline: input.GetCandidateRoomMaxOnline(),
|
||||
RoomFullStopOnline: input.GetRoomFullStopOnline(),
|
||||
RoomTargetMinOnline: input.GetRoomTargetMinOnline(),
|
||||
RoomTargetMaxOnline: input.GetRoomTargetMaxOnline(),
|
||||
RobotStayMinMS: input.GetRobotStayMinMs(),
|
||||
RobotStayMaxMS: input.GetRobotStayMaxMs(),
|
||||
RobotReplaceMinMS: input.GetRobotReplaceMinMs(),
|
||||
RobotReplaceMaxMS: input.GetRobotReplaceMaxMs(),
|
||||
NormalGiftIntervalMS: input.GetNormalGiftIntervalMs(),
|
||||
NormalGiftIntervalMinMS: input.GetNormalGiftIntervalMinMs(),
|
||||
NormalGiftIntervalMaxMS: input.GetNormalGiftIntervalMaxMs(),
|
||||
GiftIDs: append([]string(nil), input.GetGiftIds()...),
|
||||
LuckyGiftIDs: append([]string(nil), input.GetLuckyGiftIds()...),
|
||||
SuperLuckyGiftIDs: append([]string(nil), input.GetSuperLuckyGiftIds()...),
|
||||
LuckyComboMin: input.GetLuckyComboMin(),
|
||||
LuckyComboMax: input.GetLuckyComboMax(),
|
||||
LuckyPauseMinMS: input.GetLuckyPauseMinMs(),
|
||||
LuckyPauseMaxMS: input.GetLuckyPauseMaxMs(),
|
||||
MaxGiftSenders: input.GetMaxGiftSenders(),
|
||||
UpdatedByAdminID: input.GetUpdatedByAdminId(),
|
||||
CreatedAtMS: input.GetCreatedAtMs(),
|
||||
UpdatedAtMS: input.GetUpdatedAtMs(),
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
func humanRoomRobotConfigToProto(input HumanRoomRobotConfig) *roomv1.AdminHumanRoomRobotConfig {
|
||||
out := &roomv1.AdminHumanRoomRobotConfig{
|
||||
AppCode: input.AppCode,
|
||||
Enabled: input.Enabled,
|
||||
CandidateRoomMaxOnline: input.CandidateRoomMaxOnline,
|
||||
RoomFullStopOnline: input.RoomFullStopOnline,
|
||||
RoomTargetMinOnline: input.RoomTargetMinOnline,
|
||||
RoomTargetMaxOnline: input.RoomTargetMaxOnline,
|
||||
RobotStayMinMs: input.RobotStayMinMS,
|
||||
RobotStayMaxMs: input.RobotStayMaxMS,
|
||||
RobotReplaceMinMs: input.RobotReplaceMinMS,
|
||||
RobotReplaceMaxMs: input.RobotReplaceMaxMS,
|
||||
NormalGiftIntervalMs: input.NormalGiftIntervalMS,
|
||||
NormalGiftIntervalMinMs: input.NormalGiftIntervalMinMS,
|
||||
NormalGiftIntervalMaxMs: input.NormalGiftIntervalMaxMS,
|
||||
GiftIds: append([]string(nil), input.GiftIDs...),
|
||||
LuckyGiftIds: append([]string(nil), input.LuckyGiftIDs...),
|
||||
SuperLuckyGiftIds: append([]string(nil), input.SuperLuckyGiftIDs...),
|
||||
LuckyComboMin: input.LuckyComboMin,
|
||||
LuckyComboMax: input.LuckyComboMax,
|
||||
LuckyPauseMinMs: input.LuckyPauseMinMS,
|
||||
LuckyPauseMaxMs: input.LuckyPauseMaxMS,
|
||||
MaxGiftSenders: input.MaxGiftSenders,
|
||||
UpdatedByAdminId: input.UpdatedByAdminID,
|
||||
CreatedAtMs: input.CreatedAtMS,
|
||||
UpdatedAtMs: input.UpdatedAtMS,
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func roomPinFromProto(input *roomv1.AdminRoomPin) RoomPin {
|
||||
if input == nil {
|
||||
return RoomPin{}
|
||||
@ -700,6 +828,8 @@ func robotRoomFromProto(input *roomv1.AdminRobotRoom) RobotRoom {
|
||||
Status: input.GetStatus(),
|
||||
OwnerRobotUserID: input.GetOwnerRobotUserId(),
|
||||
RobotUserIDs: append([]int64(nil), input.GetRobotUserIds()...),
|
||||
ActiveRobotCount: input.GetActiveRobotCount(),
|
||||
SeatCount: input.GetSeatCount(),
|
||||
GiftRule: robotRoomGiftRuleFromProto(input.GetGiftRule()),
|
||||
CreatedByAdminID: input.GetCreatedByAdminId(),
|
||||
CreatedAtMS: input.GetCreatedAtMs(),
|
||||
@ -719,6 +849,11 @@ func robotRoomGiftRuleFromProto(input *roomv1.AdminRobotRoomGiftRule) RobotRoomG
|
||||
LuckyComboMax: input.GetLuckyComboMax(),
|
||||
LuckyPauseMinMS: input.GetLuckyPauseMinMs(),
|
||||
LuckyPauseMaxMS: input.GetLuckyPauseMaxMs(),
|
||||
RobotStayMinMS: input.GetRobotStayMinMs(),
|
||||
RobotStayMaxMS: input.GetRobotStayMaxMs(),
|
||||
RobotReplaceMinMS: input.GetRobotReplaceMinMs(),
|
||||
RobotReplaceMaxMS: input.GetRobotReplaceMaxMs(),
|
||||
MaxGiftSenders: input.GetMaxGiftSenders(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -731,6 +866,11 @@ func robotRoomGiftRuleToProto(input RobotRoomGiftRule) *roomv1.AdminRobotRoomGif
|
||||
LuckyComboMax: input.LuckyComboMax,
|
||||
LuckyPauseMinMs: input.LuckyPauseMinMS,
|
||||
LuckyPauseMaxMs: input.LuckyPauseMaxMS,
|
||||
RobotStayMinMs: input.RobotStayMinMS,
|
||||
RobotStayMaxMs: input.RobotStayMaxMS,
|
||||
RobotReplaceMinMs: input.RobotReplaceMinMS,
|
||||
RobotReplaceMaxMs: input.RobotReplaceMaxMS,
|
||||
MaxGiftSenders: input.MaxGiftSenders,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@ type Client interface {
|
||||
UpsertGiftTypeConfig(ctx context.Context, req *walletv1.UpsertGiftTypeConfigRequest) (*walletv1.GiftTypeConfigResponse, error)
|
||||
GrantResource(ctx context.Context, req *walletv1.GrantResourceRequest) (*walletv1.ResourceGrantResponse, error)
|
||||
GrantResourceGroup(ctx context.Context, req *walletv1.GrantResourceGroupRequest) (*walletv1.ResourceGrantResponse, error)
|
||||
EquipUserResource(ctx context.Context, req *walletv1.EquipUserResourceRequest) (*walletv1.EquipUserResourceResponse, error)
|
||||
ListResourceGrants(ctx context.Context, req *walletv1.ListResourceGrantsRequest) (*walletv1.ListResourceGrantsResponse, error)
|
||||
ListResourceShopItems(ctx context.Context, req *walletv1.ListResourceShopItemsRequest) (*walletv1.ListResourceShopItemsResponse, error)
|
||||
UpsertResourceShopItems(ctx context.Context, req *walletv1.UpsertResourceShopItemsRequest) (*walletv1.UpsertResourceShopItemsResponse, error)
|
||||
@ -137,6 +138,10 @@ func (c *GRPCClient) GrantResourceGroup(ctx context.Context, req *walletv1.Grant
|
||||
return c.client.GrantResourceGroup(ctx, req)
|
||||
}
|
||||
|
||||
func (c *GRPCClient) EquipUserResource(ctx context.Context, req *walletv1.EquipUserResourceRequest) (*walletv1.EquipUserResourceResponse, error) {
|
||||
return c.client.EquipUserResource(ctx, req)
|
||||
}
|
||||
|
||||
func (c *GRPCClient) ListResourceGrants(ctx context.Context, req *walletv1.ListResourceGrantsRequest) (*walletv1.ListResourceGrantsResponse, error) {
|
||||
return c.client.ListResourceGrants(ctx, req)
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ type AppBanner struct {
|
||||
CoverURL string `gorm:"size:1024;not null" json:"coverUrl"`
|
||||
RoomSmallImageURL string `gorm:"column:room_small_image_url;size:1024;not null;default:'';comment:房间内小屏图 URL" json:"roomSmallImageUrl"`
|
||||
BannerType string `gorm:"size:16;not null" json:"bannerType"`
|
||||
DisplayScope string `gorm:"size:128;index:idx_admin_app_banners_display,not null;default:home;comment:显示范围,多选逗号分隔:首页、房间内或充值页" json:"displayScope"`
|
||||
DisplayScope string `gorm:"size:128;index:idx_admin_app_banners_display,not null;default:home;comment:显示范围,多选逗号分隔:首页、房间内、充值页或我的页" json:"displayScope"`
|
||||
Param string `gorm:"size:2048" json:"param"`
|
||||
Status string `gorm:"size:24;index:idx_admin_app_banners_app_sort,not null;default:active" json:"status"`
|
||||
Platform string `gorm:"size:24;index:idx_admin_app_banners_scope,not null" json:"platform"`
|
||||
|
||||
@ -19,6 +19,7 @@ const (
|
||||
bannerDisplayScopeHome = "home"
|
||||
bannerDisplayScopeRoom = "room"
|
||||
bannerDisplayScopeRecharge = "recharge"
|
||||
bannerDisplayScopeMe = "me"
|
||||
|
||||
bannerStatusActive = "active"
|
||||
bannerStatusDisabled = "disabled"
|
||||
@ -27,7 +28,7 @@ const (
|
||||
splashDefaultDisplayDurationMS = 3000
|
||||
)
|
||||
|
||||
var bannerDisplayScopeOrder = []string{bannerDisplayScopeHome, bannerDisplayScopeRoom, bannerDisplayScopeRecharge}
|
||||
var bannerDisplayScopeOrder = []string{bannerDisplayScopeHome, bannerDisplayScopeRoom, bannerDisplayScopeRecharge, bannerDisplayScopeMe}
|
||||
|
||||
type AppConfigService struct {
|
||||
store *repository.Store
|
||||
@ -963,6 +964,8 @@ func normalizeBannerDisplayScope(value string) string {
|
||||
return bannerDisplayScopeRoom
|
||||
case bannerDisplayScopeRecharge, "充值页":
|
||||
return bannerDisplayScopeRecharge
|
||||
case bannerDisplayScopeMe, "我的页", "我的":
|
||||
return bannerDisplayScopeMe
|
||||
default:
|
||||
return value
|
||||
}
|
||||
@ -1017,7 +1020,7 @@ func validBannerDisplayScopes(scopes []string) bool {
|
||||
return false
|
||||
}
|
||||
for _, scope := range scopes {
|
||||
if scope != bannerDisplayScopeHome && scope != bannerDisplayScopeRoom && scope != bannerDisplayScopeRecharge {
|
||||
if scope != bannerDisplayScopeHome && scope != bannerDisplayScopeRoom && scope != bannerDisplayScopeRecharge && scope != bannerDisplayScopeMe {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,12 +94,12 @@ func TestBannerModelFromRequestExpiresEndedActiveBanner(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAppBannerFromModelReturnsDisplayScopes(t *testing.T) {
|
||||
item := appBannerFromModel(bannerModel("home,room,recharge"))
|
||||
item := appBannerFromModel(bannerModel("home,room,recharge,me"))
|
||||
|
||||
if item.DisplayScope != "home,room,recharge" {
|
||||
if item.DisplayScope != "home,room,recharge,me" {
|
||||
t.Fatalf("display scope should keep stored value: %+v", item)
|
||||
}
|
||||
if len(item.DisplayScopes) != 3 || item.DisplayScopes[0] != bannerDisplayScopeHome || item.DisplayScopes[1] != bannerDisplayScopeRoom || item.DisplayScopes[2] != bannerDisplayScopeRecharge {
|
||||
if len(item.DisplayScopes) != 4 || item.DisplayScopes[0] != bannerDisplayScopeHome || item.DisplayScopes[1] != bannerDisplayScopeRoom || item.DisplayScopes[2] != bannerDisplayScopeRecharge || item.DisplayScopes[3] != bannerDisplayScopeMe {
|
||||
t.Fatalf("display scopes mismatch: %+v", item.DisplayScopes)
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,8 +4,10 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"hyapp-admin-server/internal/integration/activityclient"
|
||||
"hyapp-admin-server/internal/integration/gameclient"
|
||||
"hyapp-admin-server/internal/integration/userclient"
|
||||
"hyapp-admin-server/internal/integration/walletclient"
|
||||
"hyapp-admin-server/internal/modules/shared"
|
||||
"hyapp-admin-server/internal/response"
|
||||
gamev1 "hyapp.local/api/proto/game/v1"
|
||||
@ -16,6 +18,8 @@ import (
|
||||
type Handler struct {
|
||||
game gameclient.Client
|
||||
user userclient.Client
|
||||
wallet walletclient.Client
|
||||
activity activityclient.Client
|
||||
audit shared.OperationLogger
|
||||
robotProfiles RobotProfileSource
|
||||
}
|
||||
|
||||
189
server/admin/internal/modules/gamemanagement/robot_appearance.go
Normal file
189
server/admin/internal/modules/gamemanagement/robot_appearance.go
Normal file
@ -0,0 +1,189 @@
|
||||
package gamemanagement
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
activityv1 "hyapp.local/api/proto/activity/v1"
|
||||
walletv1 "hyapp.local/api/proto/wallet/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
robotResourceDurationDays = 9999
|
||||
robotResourceDurationMS = int64(robotResourceDurationDays) * int64(24*time.Hour/time.Millisecond)
|
||||
robotMinDisplayLevel = 5
|
||||
robotMaxDisplayLevel = 30
|
||||
)
|
||||
|
||||
type robotAppearanceCatalog struct {
|
||||
avatarFrames []*walletv1.Resource
|
||||
vehicles []*walletv1.Resource
|
||||
longBadges []*walletv1.Resource
|
||||
shortBadges []*walletv1.Resource
|
||||
}
|
||||
|
||||
func (h *Handler) initializeGeneratedRobotAppearance(ctx context.Context, requestID string, appCode string, actorUserID int64, userID int64) error {
|
||||
if h.wallet == nil || h.activity == nil {
|
||||
return fmt.Errorf("机器人装扮初始化依赖未配置")
|
||||
}
|
||||
catalog, err := h.loadRobotAppearanceCatalog(ctx, requestID, appCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
avatarFrame := randomRobotResource(catalog.avatarFrames)
|
||||
vehicle := randomRobotResource(catalog.vehicles)
|
||||
longBadge := randomRobotResource(catalog.longBadges)
|
||||
shortBadge := randomRobotResource(catalog.shortBadges)
|
||||
if avatarFrame == nil || vehicle == nil || longBadge == nil || shortBadge == nil {
|
||||
return fmt.Errorf("机器人装扮资源库不完整: 头像框=%d 座驾=%d 长徽章=%d 短徽章=%d", len(catalog.avatarFrames), len(catalog.vehicles), len(catalog.longBadges), len(catalog.shortBadges))
|
||||
}
|
||||
if err := h.grantAndEquipRobotResource(ctx, requestID, appCode, actorUserID, userID, "avatar_frame", avatarFrame.GetResourceId(), true); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.grantAndEquipRobotResource(ctx, requestID, appCode, actorUserID, userID, "vehicle", vehicle.GetResourceId(), true); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.grantAndEquipRobotResource(ctx, requestID, appCode, actorUserID, userID, "long_badge", longBadge.GetResourceId(), false); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.grantAndEquipRobotResource(ctx, requestID, appCode, actorUserID, userID, "short_badge", shortBadge.GetResourceId(), false); err != nil {
|
||||
return err
|
||||
}
|
||||
// 财富和魅力等级由 activity-service 按等级规则写入账户、展示投影和等级奖励 job;
|
||||
// admin-server 只给出目标等级,避免绕过成长系统直接伪造资料卡字段。
|
||||
if err := h.setRobotDisplayLevel(ctx, requestID, appCode, actorUserID, userID, "wealth", int32(robotMinDisplayLevel+randomRobotInt(robotMaxDisplayLevel-robotMinDisplayLevel+1))); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.setRobotDisplayLevel(ctx, requestID, appCode, actorUserID, userID, "charm", int32(robotMinDisplayLevel+randomRobotInt(robotMaxDisplayLevel-robotMinDisplayLevel+1))); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) loadRobotAppearanceCatalog(ctx context.Context, requestID string, appCode string) (robotAppearanceCatalog, error) {
|
||||
avatarFrames, err := h.listRobotResources(ctx, requestID, appCode, "avatar_frame")
|
||||
if err != nil {
|
||||
return robotAppearanceCatalog{}, err
|
||||
}
|
||||
vehicles, err := h.listRobotResources(ctx, requestID, appCode, "vehicle")
|
||||
if err != nil {
|
||||
return robotAppearanceCatalog{}, err
|
||||
}
|
||||
badges, err := h.listRobotResources(ctx, requestID, appCode, "badge")
|
||||
if err != nil {
|
||||
return robotAppearanceCatalog{}, err
|
||||
}
|
||||
catalog := robotAppearanceCatalog{avatarFrames: avatarFrames, vehicles: vehicles}
|
||||
for _, badge := range badges {
|
||||
switch robotBadgeForm(badge.GetMetadataJson()) {
|
||||
case "strip", "long":
|
||||
catalog.longBadges = append(catalog.longBadges, badge)
|
||||
case "tile", "short":
|
||||
catalog.shortBadges = append(catalog.shortBadges, badge)
|
||||
}
|
||||
}
|
||||
return catalog, nil
|
||||
}
|
||||
|
||||
func (h *Handler) listRobotResources(ctx context.Context, requestID string, appCode string, resourceType string) ([]*walletv1.Resource, error) {
|
||||
resp, err := h.wallet.ListResources(ctx, &walletv1.ListResourcesRequest{
|
||||
RequestId: requestID,
|
||||
AppCode: appCode,
|
||||
ResourceType: resourceType,
|
||||
Page: 1,
|
||||
PageSize: 500,
|
||||
ActiveOnly: true,
|
||||
ManagerGrantOnly: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("读取机器人%s资源失败: %w", resourceType, err)
|
||||
}
|
||||
resources := make([]*walletv1.Resource, 0, len(resp.GetResources()))
|
||||
for _, item := range resp.GetResources() {
|
||||
if item != nil && item.GetResourceId() > 0 && item.GetStatus() == "active" && item.GetManagerGrantEnabled() {
|
||||
resources = append(resources, item)
|
||||
}
|
||||
}
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
func (h *Handler) grantAndEquipRobotResource(ctx context.Context, requestID string, appCode string, actorUserID int64, userID int64, slot string, resourceID int64, equip bool) error {
|
||||
grant, err := h.wallet.GrantResource(ctx, &walletv1.GrantResourceRequest{
|
||||
CommandId: fmt.Sprintf("game_robot_init:%s:%d:%s:%d", requestID, userID, slot, resourceID),
|
||||
AppCode: appCode,
|
||||
TargetUserId: userID,
|
||||
ResourceId: resourceID,
|
||||
Quantity: 1,
|
||||
DurationMs: robotResourceDurationMS,
|
||||
Reason: "game_robot_init",
|
||||
OperatorUserId: actorUserID,
|
||||
GrantSource: "game_robot_init",
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("发放机器人%s失败: %w", slot, err)
|
||||
}
|
||||
if !equip {
|
||||
return nil
|
||||
}
|
||||
entitlementID := ""
|
||||
for _, item := range grant.GetGrant().GetItems() {
|
||||
if item.GetResourceId() == resourceID {
|
||||
entitlementID = item.GetEntitlementId()
|
||||
break
|
||||
}
|
||||
}
|
||||
if _, err := h.wallet.EquipUserResource(ctx, &walletv1.EquipUserResourceRequest{
|
||||
RequestId: fmt.Sprintf("%s:%s:equip", requestID, slot),
|
||||
AppCode: appCode,
|
||||
UserId: userID,
|
||||
ResourceId: resourceID,
|
||||
EntitlementId: entitlementID,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("装备机器人%s失败: %w", slot, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) setRobotDisplayLevel(ctx context.Context, requestID string, appCode string, actorUserID int64, userID int64, track string, level int32) error {
|
||||
_, err := h.activity.SetUserLevel(ctx, &activityv1.SetUserLevelRequest{
|
||||
Meta: activityRequestMeta(requestID, appCode),
|
||||
CommandId: fmt.Sprintf("game_robot_init:%s:%d:%s:%d", requestID, userID, track, level),
|
||||
UserId: userID,
|
||||
Track: track,
|
||||
Level: level,
|
||||
OperatorUserId: actorUserID,
|
||||
Reason: "game_robot_init",
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("设置机器人%s等级失败: %w", track, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func robotBadgeForm(metadataJSON string) string {
|
||||
var payload map[string]any
|
||||
if err := json.Unmarshal([]byte(strings.TrimSpace(metadataJSON)), &payload); err != nil {
|
||||
return ""
|
||||
}
|
||||
value, _ := payload["badge_form"].(string)
|
||||
return strings.ToLower(strings.TrimSpace(value))
|
||||
}
|
||||
|
||||
func randomRobotResource(items []*walletv1.Resource) *walletv1.Resource {
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
return items[randomRobotInt(int64(len(items)))]
|
||||
}
|
||||
|
||||
func activityRequestMeta(requestID string, appCode string) *activityv1.RequestMeta {
|
||||
return &activityv1.RequestMeta{
|
||||
RequestId: requestID,
|
||||
Caller: "admin-server",
|
||||
SentAtMs: time.Now().UnixMilli(),
|
||||
AppCode: appCode,
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,9 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"hyapp-admin-server/internal/integration/activityclient"
|
||||
"hyapp-admin-server/internal/integration/walletclient"
|
||||
)
|
||||
|
||||
type RobotProfile struct {
|
||||
@ -39,6 +42,15 @@ func WithRobotProfileSource(source RobotProfileSource) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithRobotAppearanceServices 注入机器人装扮和等级初始化依赖;robot-service 只登记机器人事实,
|
||||
// 因此创建账号后的资源发放和成长等级必须由 admin-server 编排到对应 owner service。
|
||||
func WithRobotAppearanceServices(wallet walletclient.Client, activity activityclient.Client) Option {
|
||||
return func(h *Handler) {
|
||||
h.wallet = wallet
|
||||
h.activity = activity
|
||||
}
|
||||
}
|
||||
|
||||
func (s *likeiRobotProfileSource) RandomRobotProfiles(ctx context.Context, count int) ([]RobotProfile, error) {
|
||||
if s == nil || s.db == nil {
|
||||
return nil, fmt.Errorf("likei robot profile source is not configured")
|
||||
|
||||
@ -8,10 +8,14 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"hyapp-admin-server/internal/integration/activityclient"
|
||||
"hyapp-admin-server/internal/integration/gameclient"
|
||||
"hyapp-admin-server/internal/integration/userclient"
|
||||
"hyapp-admin-server/internal/integration/walletclient"
|
||||
"hyapp-admin-server/internal/middleware"
|
||||
activityv1 "hyapp.local/api/proto/activity/v1"
|
||||
gamev1 "hyapp.local/api/proto/game/v1"
|
||||
walletv1 "hyapp.local/api/proto/wallet/v1"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@ -59,6 +63,51 @@ func (c *fakeRobotGameClient) RegisterDiceRobots(_ context.Context, req *gamev1.
|
||||
return &gamev1.RegisterDiceRobotsResponse{Robots: robots}, nil
|
||||
}
|
||||
|
||||
type fakeRobotWalletClient struct {
|
||||
walletclient.Client
|
||||
grants []string
|
||||
equips []int64
|
||||
}
|
||||
|
||||
func (c *fakeRobotWalletClient) ListResources(_ context.Context, req *walletv1.ListResourcesRequest) (*walletv1.ListResourcesResponse, error) {
|
||||
switch req.GetResourceType() {
|
||||
case "avatar_frame":
|
||||
return &walletv1.ListResourcesResponse{Resources: []*walletv1.Resource{{ResourceId: 101, ResourceType: "avatar_frame", Status: "active", ManagerGrantEnabled: true}}}, nil
|
||||
case "vehicle":
|
||||
return &walletv1.ListResourcesResponse{Resources: []*walletv1.Resource{{ResourceId: 201, ResourceType: "vehicle", Status: "active", ManagerGrantEnabled: true}}}, nil
|
||||
case "badge":
|
||||
return &walletv1.ListResourcesResponse{Resources: []*walletv1.Resource{
|
||||
{ResourceId: 301, ResourceType: "badge", Status: "active", ManagerGrantEnabled: true, MetadataJson: `{"badge_form":"strip"}`},
|
||||
{ResourceId: 302, ResourceType: "badge", Status: "active", ManagerGrantEnabled: true, MetadataJson: `{"badge_form":"tile"}`},
|
||||
}}, nil
|
||||
default:
|
||||
return &walletv1.ListResourcesResponse{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *fakeRobotWalletClient) GrantResource(_ context.Context, req *walletv1.GrantResourceRequest) (*walletv1.ResourceGrantResponse, error) {
|
||||
c.grants = append(c.grants, req.GetCommandId())
|
||||
return &walletv1.ResourceGrantResponse{Grant: &walletv1.ResourceGrant{Items: []*walletv1.ResourceGrantItem{{
|
||||
ResourceId: req.GetResourceId(),
|
||||
EntitlementId: "entitlement",
|
||||
}}}}, nil
|
||||
}
|
||||
|
||||
func (c *fakeRobotWalletClient) EquipUserResource(_ context.Context, req *walletv1.EquipUserResourceRequest) (*walletv1.EquipUserResourceResponse, error) {
|
||||
c.equips = append(c.equips, req.GetResourceId())
|
||||
return &walletv1.EquipUserResourceResponse{}, nil
|
||||
}
|
||||
|
||||
type fakeRobotActivityClient struct {
|
||||
activityclient.Client
|
||||
levels []*activityv1.SetUserLevelRequest
|
||||
}
|
||||
|
||||
func (c *fakeRobotActivityClient) SetUserLevel(_ context.Context, req *activityv1.SetUserLevelRequest) (*activityv1.SetUserLevelResponse, error) {
|
||||
c.levels = append(c.levels, req)
|
||||
return &activityv1.SetUserLevelResponse{Status: "consumed", Track: req.GetTrack(), NewLevel: req.GetLevel()}, nil
|
||||
}
|
||||
|
||||
func TestGenerateDiceRobotsUsesLikeiProfiles(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
profiles := &fakeRobotProfileSource{profiles: []RobotProfile{
|
||||
@ -67,7 +116,9 @@ func TestGenerateDiceRobotsUsesLikeiProfiles(t *testing.T) {
|
||||
}}
|
||||
users := &fakeRobotUserClient{}
|
||||
games := &fakeRobotGameClient{}
|
||||
handler := New(games, users, nil, WithRobotProfileSource(profiles))
|
||||
wallets := &fakeRobotWalletClient{}
|
||||
activities := &fakeRobotActivityClient{}
|
||||
handler := New(games, users, nil, WithRobotProfileSource(profiles), WithRobotAppearanceServices(wallets, activities))
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
@ -104,13 +155,21 @@ func TestGenerateDiceRobotsUsesLikeiProfiles(t *testing.T) {
|
||||
if len(games.registered) != 2 || games.registered[0] != 9001 || games.registered[1] != 9002 {
|
||||
t.Fatalf("registered user ids = %#v", games.registered)
|
||||
}
|
||||
if len(wallets.grants) != 8 || len(wallets.equips) != 4 || len(activities.levels) != 4 {
|
||||
t.Fatalf("robot appearance init mismatch: grants=%d equips=%d levels=%d", len(wallets.grants), len(wallets.equips), len(activities.levels))
|
||||
}
|
||||
for _, level := range activities.levels {
|
||||
if level.GetLevel() < robotMinDisplayLevel || level.GetLevel() > robotMaxDisplayLevel {
|
||||
t.Fatalf("robot level out of range: %+v", level)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateDiceRobotsFallsBackToRandomProfilesWhenLikeiMissing(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
users := &fakeRobotUserClient{}
|
||||
games := &fakeRobotGameClient{}
|
||||
handler := New(games, users, nil)
|
||||
handler := New(games, users, nil, WithRobotAppearanceServices(&fakeRobotWalletClient{}, &fakeRobotActivityClient{}))
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
|
||||
@ -232,6 +232,13 @@ func (h *Handler) GenerateDiceRobots(c *gin.Context) {
|
||||
}
|
||||
userIDs := make([]int64, 0, req.Count)
|
||||
requestID := middleware.CurrentRequestID(c)
|
||||
meta := requestMeta(c)
|
||||
appCode := meta.GetAppCode()
|
||||
if appCode == "" {
|
||||
appCode = "lalu"
|
||||
meta.AppCode = appCode
|
||||
}
|
||||
actorUserID := int64(middleware.CurrentUserID(c))
|
||||
accountLanguage := robotAccountLanguage(req.NicknameLanguage)
|
||||
for index := int32(0); index < req.Count; index++ {
|
||||
profile := profiles[index]
|
||||
@ -262,10 +269,14 @@ func (h *Handler) GenerateDiceRobots(c *gin.Context) {
|
||||
response.BadRequest(c, "创建机器人用户失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
if err := h.initializeGeneratedRobotAppearance(c.Request.Context(), requestID, appCode, actorUserID, created.UserID); err != nil {
|
||||
response.BadRequest(c, "初始化机器人装扮失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
userIDs = append(userIDs, created.UserID)
|
||||
}
|
||||
resp, err := h.game.RegisterDiceRobots(c.Request.Context(), &gamev1.RegisterDiceRobotsRequest{
|
||||
Meta: requestMeta(c),
|
||||
Meta: meta,
|
||||
GameId: strings.TrimSpace(firstQuery(c, "gameId", "game_id")),
|
||||
UserIds: userIDs,
|
||||
})
|
||||
|
||||
@ -3,6 +3,7 @@ package roomadmin
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@ -10,6 +11,7 @@ import (
|
||||
"hyapp-admin-server/internal/integration/roomclient"
|
||||
"hyapp-admin-server/internal/middleware"
|
||||
"hyapp-admin-server/internal/modules/shared"
|
||||
"hyapp-admin-server/internal/repository"
|
||||
"hyapp-admin-server/internal/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -20,8 +22,8 @@ type Handler struct {
|
||||
audit shared.OperationLogger
|
||||
}
|
||||
|
||||
func New(userDB *sql.DB, roomClient roomclient.Client, robotClient robotclient.Client, audit shared.OperationLogger) *Handler {
|
||||
return &Handler{service: NewService(userDB, roomClient, robotClient), audit: audit}
|
||||
func New(userDB *sql.DB, store *repository.Store, roomClient roomclient.Client, robotClient robotclient.Client, audit shared.OperationLogger) *Handler {
|
||||
return &Handler{service: NewService(userDB, store, roomClient, robotClient), audit: audit}
|
||||
}
|
||||
|
||||
func (h *Handler) ListRooms(c *gin.Context) {
|
||||
@ -83,6 +85,10 @@ func (h *Handler) ListRobotRooms(c *gin.Context) {
|
||||
query := parseRobotRoomListQuery(c)
|
||||
items, total, err := h.service.ListRobotRooms(c.Request.Context(), query)
|
||||
if err != nil {
|
||||
slog.Error("roomadmin_list_robot_rooms_failed",
|
||||
"request_id", middleware.CurrentRequestID(c),
|
||||
"error", err.Error(),
|
||||
)
|
||||
response.ServerError(c, "获取机器人房间列表失败")
|
||||
return
|
||||
}
|
||||
@ -121,6 +127,30 @@ func (h *Handler) StopRobotRoom(c *gin.Context) {
|
||||
h.setRobotRoomStatus(c, "stopped", "stop-robot-room", "停止机器人房间失败")
|
||||
}
|
||||
|
||||
func (h *Handler) GetHumanRoomRobotConfig(c *gin.Context) {
|
||||
config, err := h.service.GetHumanRoomRobotConfig(c.Request.Context())
|
||||
if err != nil {
|
||||
response.ServerError(c, "获取真人房间机器人配置失败")
|
||||
return
|
||||
}
|
||||
response.OK(c, config)
|
||||
}
|
||||
|
||||
func (h *Handler) UpdateHumanRoomRobotConfig(c *gin.Context) {
|
||||
var req updateHumanRoomRobotConfigRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "真人房间机器人配置参数不正确")
|
||||
return
|
||||
}
|
||||
config, err := h.service.UpdateHumanRoomRobotConfig(c.Request.Context(), req, shared.ActorFromContext(c))
|
||||
if err != nil {
|
||||
writeMutationError(c, err, "更新真人房间机器人配置失败")
|
||||
return
|
||||
}
|
||||
writeRoomAuditLog(c, h.audit, "update-human-room-robot-config", "room_human_robot_configs", "human-room-robot", "success", "update human room robot config")
|
||||
response.OK(c, config)
|
||||
}
|
||||
|
||||
func (h *Handler) GetRoomConfig(c *gin.Context) {
|
||||
config, err := h.service.GetRoomConfig(c.Request.Context())
|
||||
if err != nil {
|
||||
@ -130,6 +160,30 @@ func (h *Handler) GetRoomConfig(c *gin.Context) {
|
||||
response.OK(c, config)
|
||||
}
|
||||
|
||||
func (h *Handler) GetRoomWhitelistConfig(c *gin.Context) {
|
||||
config, err := h.service.GetRoomWhitelistConfig(c.Request.Context())
|
||||
if err != nil {
|
||||
response.ServerError(c, "获取房间白名单失败")
|
||||
return
|
||||
}
|
||||
response.OK(c, config)
|
||||
}
|
||||
|
||||
func (h *Handler) UpdateRoomWhitelistConfig(c *gin.Context) {
|
||||
var req updateRoomWhitelistRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "房间白名单参数不正确")
|
||||
return
|
||||
}
|
||||
config, err := h.service.UpdateRoomWhitelistConfig(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
writeMutationError(c, err, "更新房间白名单失败")
|
||||
return
|
||||
}
|
||||
writeRoomAuditLog(c, h.audit, "update-room-whitelist", "admin_app_configs", "room-region-whitelist", "success", "update room whitelist")
|
||||
response.OK(c, config)
|
||||
}
|
||||
|
||||
func (h *Handler) UpdateRoomConfig(c *gin.Context) {
|
||||
var req updateRoomConfigRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@ -40,6 +40,8 @@ type createRobotRoomRequest struct {
|
||||
RoomName string `json:"roomName"`
|
||||
RoomAvatar string `json:"roomAvatar"`
|
||||
VisibleRegionID int64 `json:"visibleRegionId"`
|
||||
OwnerCountryCode string `json:"-"`
|
||||
SeatCount int32 `json:"seatCount"`
|
||||
GiftIDs []string `json:"giftIds"`
|
||||
LuckyGiftIDs []string `json:"luckyGiftIds"`
|
||||
NormalGiftIntervalMS int64 `json:"normalGiftIntervalMs"`
|
||||
@ -47,6 +49,11 @@ type createRobotRoomRequest struct {
|
||||
LuckyComboMax int64 `json:"luckyComboMax"`
|
||||
LuckyPauseMinMS int64 `json:"luckyPauseMinMs"`
|
||||
LuckyPauseMaxMS int64 `json:"luckyPauseMaxMs"`
|
||||
RobotStayMinMS int64 `json:"robotStayMinMs"`
|
||||
RobotStayMaxMS int64 `json:"robotStayMaxMs"`
|
||||
RobotReplaceMinMS int64 `json:"robotReplaceMinMs"`
|
||||
RobotReplaceMaxMS int64 `json:"robotReplaceMaxMs"`
|
||||
MaxGiftSenders int64 `json:"maxGiftSenders"`
|
||||
}
|
||||
|
||||
type flexibleJSONInt64 int64
|
||||
@ -126,3 +133,52 @@ type updateRoomConfigRequest struct {
|
||||
AllowedSeatCounts []int32 `json:"allowedSeatCounts"`
|
||||
DefaultSeatCount int32 `json:"defaultSeatCount"`
|
||||
}
|
||||
|
||||
type updateRoomWhitelistRequest struct {
|
||||
UserIDs flexibleJSONInt64StringSlice `json:"userIds"`
|
||||
}
|
||||
|
||||
type updateHumanRoomRobotConfigRequest struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
CandidateRoomMaxOnline int32 `json:"candidateRoomMaxOnline"`
|
||||
RoomFullStopOnline int32 `json:"roomFullStopOnline"`
|
||||
RoomTargetMinOnline int32 `json:"roomTargetMinOnline"`
|
||||
RoomTargetMaxOnline int32 `json:"roomTargetMaxOnline"`
|
||||
RobotStayMinMS int64 `json:"robotStayMinMs"`
|
||||
RobotStayMaxMS int64 `json:"robotStayMaxMs"`
|
||||
RobotReplaceMinMS int64 `json:"robotReplaceMinMs"`
|
||||
RobotReplaceMaxMS int64 `json:"robotReplaceMaxMs"`
|
||||
NormalGiftIntervalMS int64 `json:"normalGiftIntervalMs"`
|
||||
NormalGiftIntervalMinMS int64 `json:"normalGiftIntervalMinMs"`
|
||||
NormalGiftIntervalMaxMS int64 `json:"normalGiftIntervalMaxMs"`
|
||||
GiftIDs []string `json:"giftIds"`
|
||||
LuckyGiftIDs []string `json:"luckyGiftIds"`
|
||||
SuperLuckyGiftIDs []string `json:"superLuckyGiftIds"`
|
||||
LuckyComboMin int64 `json:"luckyComboMin"`
|
||||
LuckyComboMax int64 `json:"luckyComboMax"`
|
||||
LuckyPauseMinMS int64 `json:"luckyPauseMinMs"`
|
||||
LuckyPauseMaxMS int64 `json:"luckyPauseMaxMs"`
|
||||
MaxGiftSenders int64 `json:"maxGiftSenders"`
|
||||
}
|
||||
|
||||
type flexibleJSONInt64StringSlice []string
|
||||
|
||||
func (values *flexibleJSONInt64StringSlice) UnmarshalJSON(data []byte) error {
|
||||
// 房间白名单 user_id 是 int64 标识,API 合约统一按字符串输出;这里兼容旧脚本传数字但拒绝小数。
|
||||
var raw []json.RawMessage
|
||||
if err := json.Unmarshal(data, &raw); err != nil {
|
||||
return err
|
||||
}
|
||||
out := make([]string, 0, len(raw))
|
||||
for _, item := range raw {
|
||||
value, err := parseFlexibleJSONInt64(item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if value > 0 {
|
||||
out = append(out, strconv.FormatInt(value, 10))
|
||||
}
|
||||
}
|
||||
*values = out
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -24,6 +24,8 @@ type RobotRoom struct {
|
||||
Owner RoomOwner `json:"owner"`
|
||||
RobotUserIDs []string `json:"robotUserIds"`
|
||||
Robots []RoomOwner `json:"robots"`
|
||||
ActiveRobotCount int32 `json:"activeRobotCount"`
|
||||
SeatCount int32 `json:"seatCount"`
|
||||
GiftRule RobotGiftRule `json:"giftRule"`
|
||||
CreatedByAdminID uint64 `json:"createdByAdminId"`
|
||||
CreatedAtMS int64 `json:"createdAtMs"`
|
||||
@ -38,6 +40,11 @@ type RobotGiftRule struct {
|
||||
LuckyComboMax int64 `json:"luckyComboMax"`
|
||||
LuckyPauseMinMS int64 `json:"luckyPauseMinMs"`
|
||||
LuckyPauseMaxMS int64 `json:"luckyPauseMaxMs"`
|
||||
RobotStayMinMS int64 `json:"robotStayMinMs"`
|
||||
RobotStayMaxMS int64 `json:"robotStayMaxMs"`
|
||||
RobotReplaceMinMS int64 `json:"robotReplaceMinMs"`
|
||||
RobotReplaceMaxMS int64 `json:"robotReplaceMaxMs"`
|
||||
MaxGiftSenders int64 `json:"maxGiftSenders"`
|
||||
}
|
||||
|
||||
type AvailableRoomRobot struct {
|
||||
@ -49,6 +56,33 @@ type AvailableRoomRobot struct {
|
||||
User RoomOwner `json:"user"`
|
||||
}
|
||||
|
||||
type HumanRoomRobotConfig struct {
|
||||
AppCode string `json:"appCode"`
|
||||
Enabled bool `json:"enabled"`
|
||||
CandidateRoomMaxOnline int32 `json:"candidateRoomMaxOnline"`
|
||||
RoomFullStopOnline int32 `json:"roomFullStopOnline"`
|
||||
RoomTargetMinOnline int32 `json:"roomTargetMinOnline"`
|
||||
RoomTargetMaxOnline int32 `json:"roomTargetMaxOnline"`
|
||||
RobotStayMinMS int64 `json:"robotStayMinMs"`
|
||||
RobotStayMaxMS int64 `json:"robotStayMaxMs"`
|
||||
RobotReplaceMinMS int64 `json:"robotReplaceMinMs"`
|
||||
RobotReplaceMaxMS int64 `json:"robotReplaceMaxMs"`
|
||||
NormalGiftIntervalMS int64 `json:"normalGiftIntervalMs"`
|
||||
NormalGiftIntervalMinMS int64 `json:"normalGiftIntervalMinMs"`
|
||||
NormalGiftIntervalMaxMS int64 `json:"normalGiftIntervalMaxMs"`
|
||||
GiftIDs []string `json:"giftIds"`
|
||||
LuckyGiftIDs []string `json:"luckyGiftIds"`
|
||||
SuperLuckyGiftIDs []string `json:"superLuckyGiftIds"`
|
||||
LuckyComboMin int64 `json:"luckyComboMin"`
|
||||
LuckyComboMax int64 `json:"luckyComboMax"`
|
||||
LuckyPauseMinMS int64 `json:"luckyPauseMinMs"`
|
||||
LuckyPauseMaxMS int64 `json:"luckyPauseMaxMs"`
|
||||
MaxGiftSenders int64 `json:"maxGiftSenders"`
|
||||
UpdatedByAdminID uint64 `json:"updatedByAdminId"`
|
||||
CreatedAtMS int64 `json:"createdAtMs"`
|
||||
UpdatedAtMS int64 `json:"updatedAtMs"`
|
||||
}
|
||||
|
||||
func (s *Service) ListRobotRooms(ctx context.Context, query robotRoomListQuery) ([]RobotRoom, int64, error) {
|
||||
if s.roomClient == nil {
|
||||
return nil, 0, fmt.Errorf("room service client is not configured")
|
||||
@ -113,6 +147,53 @@ func (s *Service) ListAvailableRoomRobots(ctx context.Context) ([]AvailableRoomR
|
||||
return availableRoomRobotsFromGamePool(result.Robots, available.AvailableUserIDs, owners), nil
|
||||
}
|
||||
|
||||
func (s *Service) GetHumanRoomRobotConfig(ctx context.Context) (HumanRoomRobotConfig, error) {
|
||||
if s.roomClient == nil {
|
||||
return HumanRoomRobotConfig{}, fmt.Errorf("room service client is not configured")
|
||||
}
|
||||
config, err := s.roomClient.GetHumanRoomRobotConfig(ctx)
|
||||
if err != nil {
|
||||
return HumanRoomRobotConfig{}, err
|
||||
}
|
||||
return s.humanRoomRobotConfigFromClient(ctx, config)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateHumanRoomRobotConfig(ctx context.Context, req updateHumanRoomRobotConfigRequest, actor shared.Actor) (HumanRoomRobotConfig, error) {
|
||||
if s.roomClient == nil {
|
||||
return HumanRoomRobotConfig{}, fmt.Errorf("room service client is not configured")
|
||||
}
|
||||
config := roomclient.HumanRoomRobotConfig{
|
||||
Enabled: req.Enabled,
|
||||
CandidateRoomMaxOnline: req.CandidateRoomMaxOnline,
|
||||
RoomFullStopOnline: req.RoomFullStopOnline,
|
||||
RoomTargetMinOnline: req.RoomTargetMinOnline,
|
||||
RoomTargetMaxOnline: req.RoomTargetMaxOnline,
|
||||
RobotStayMinMS: req.RobotStayMinMS,
|
||||
RobotStayMaxMS: req.RobotStayMaxMS,
|
||||
RobotReplaceMinMS: req.RobotReplaceMinMS,
|
||||
RobotReplaceMaxMS: req.RobotReplaceMaxMS,
|
||||
NormalGiftIntervalMS: req.NormalGiftIntervalMS,
|
||||
NormalGiftIntervalMinMS: req.NormalGiftIntervalMinMS,
|
||||
NormalGiftIntervalMaxMS: req.NormalGiftIntervalMaxMS,
|
||||
GiftIDs: normalizeStringList(req.GiftIDs),
|
||||
LuckyGiftIDs: normalizeStringList(req.LuckyGiftIDs),
|
||||
SuperLuckyGiftIDs: normalizeStringList(req.SuperLuckyGiftIDs),
|
||||
LuckyComboMin: req.LuckyComboMin,
|
||||
LuckyComboMax: req.LuckyComboMax,
|
||||
LuckyPauseMinMS: req.LuckyPauseMinMS,
|
||||
LuckyPauseMaxMS: req.LuckyPauseMaxMS,
|
||||
MaxGiftSenders: req.MaxGiftSenders,
|
||||
}
|
||||
saved, err := s.roomClient.UpdateHumanRoomRobotConfig(ctx, roomclient.UpdateHumanRoomRobotConfigRequest{
|
||||
Config: config,
|
||||
AdminID: uint64(actor.UserID),
|
||||
})
|
||||
if err != nil {
|
||||
return HumanRoomRobotConfig{}, mapRoomClientError(err)
|
||||
}
|
||||
return s.humanRoomRobotConfigFromClient(ctx, saved)
|
||||
}
|
||||
|
||||
func availableRoomRobotsFromGamePool(robots []robotclient.Robot, availableUserIDs []int64, owners map[int64]RoomOwner) []AvailableRoomRobot {
|
||||
allowed := make(map[int64]bool, len(availableUserIDs))
|
||||
for _, userID := range availableUserIDs {
|
||||
@ -135,6 +216,50 @@ func availableRoomRobotsFromGamePool(robots []robotclient.Robot, availableUserID
|
||||
return items
|
||||
}
|
||||
|
||||
func normalizeStringList(values []string) []string {
|
||||
seen := make(map[string]bool, len(values))
|
||||
out := make([]string, 0, len(values))
|
||||
for _, value := range values {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" || seen[value] {
|
||||
continue
|
||||
}
|
||||
seen[value] = true
|
||||
out = append(out, value)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (s *Service) humanRoomRobotConfigFromClient(_ context.Context, config roomclient.HumanRoomRobotConfig) (HumanRoomRobotConfig, error) {
|
||||
out := HumanRoomRobotConfig{
|
||||
AppCode: config.AppCode,
|
||||
Enabled: config.Enabled,
|
||||
CandidateRoomMaxOnline: config.CandidateRoomMaxOnline,
|
||||
RoomFullStopOnline: config.RoomFullStopOnline,
|
||||
RoomTargetMinOnline: config.RoomTargetMinOnline,
|
||||
RoomTargetMaxOnline: config.RoomTargetMaxOnline,
|
||||
RobotStayMinMS: config.RobotStayMinMS,
|
||||
RobotStayMaxMS: config.RobotStayMaxMS,
|
||||
RobotReplaceMinMS: config.RobotReplaceMinMS,
|
||||
RobotReplaceMaxMS: config.RobotReplaceMaxMS,
|
||||
NormalGiftIntervalMS: config.NormalGiftIntervalMS,
|
||||
NormalGiftIntervalMinMS: config.NormalGiftIntervalMinMS,
|
||||
NormalGiftIntervalMaxMS: config.NormalGiftIntervalMaxMS,
|
||||
GiftIDs: append([]string(nil), config.GiftIDs...),
|
||||
LuckyGiftIDs: append([]string(nil), config.LuckyGiftIDs...),
|
||||
SuperLuckyGiftIDs: append([]string(nil), config.SuperLuckyGiftIDs...),
|
||||
LuckyComboMin: config.LuckyComboMin,
|
||||
LuckyComboMax: config.LuckyComboMax,
|
||||
LuckyPauseMinMS: config.LuckyPauseMinMS,
|
||||
LuckyPauseMaxMS: config.LuckyPauseMaxMS,
|
||||
MaxGiftSenders: config.MaxGiftSenders,
|
||||
UpdatedByAdminID: config.UpdatedByAdminID,
|
||||
CreatedAtMS: config.CreatedAtMS,
|
||||
UpdatedAtMS: config.UpdatedAtMS,
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *Service) CreateRobotRoom(ctx context.Context, req createRobotRoomRequest, actor shared.Actor) (RobotRoom, error) {
|
||||
if s.roomClient == nil {
|
||||
return RobotRoom{}, fmt.Errorf("room service client is not configured")
|
||||
@ -155,6 +280,8 @@ func (s *Service) CreateRobotRoom(ctx context.Context, req createRobotRoomReques
|
||||
RoomName: req.RoomName,
|
||||
RoomAvatar: req.RoomAvatar,
|
||||
VisibleRegionID: req.VisibleRegionID,
|
||||
OwnerCountryCode: req.OwnerCountryCode,
|
||||
SeatCount: req.SeatCount,
|
||||
GiftRule: roomclient.RobotRoomGiftRule{
|
||||
GiftIDs: req.GiftIDs,
|
||||
LuckyGiftIDs: req.LuckyGiftIDs,
|
||||
@ -163,6 +290,11 @@ func (s *Service) CreateRobotRoom(ctx context.Context, req createRobotRoomReques
|
||||
LuckyComboMax: req.LuckyComboMax,
|
||||
LuckyPauseMinMS: req.LuckyPauseMinMS,
|
||||
LuckyPauseMaxMS: req.LuckyPauseMaxMS,
|
||||
RobotStayMinMS: req.RobotStayMinMS,
|
||||
RobotStayMaxMS: req.RobotStayMaxMS,
|
||||
RobotReplaceMinMS: req.RobotReplaceMinMS,
|
||||
RobotReplaceMaxMS: req.RobotReplaceMaxMS,
|
||||
MaxGiftSenders: req.MaxGiftSenders,
|
||||
},
|
||||
AdminID: uint64(actor.UserID),
|
||||
})
|
||||
@ -189,13 +321,19 @@ func (s *Service) applyOwnerProfileToRobotRoomRequest(ctx context.Context, req *
|
||||
if !ok {
|
||||
return fmt.Errorf("%w: 房主机器人资料不存在", ErrInvalidArgument)
|
||||
}
|
||||
return applyOwnerProfileToRobotRoomRequest(req, owner)
|
||||
}
|
||||
|
||||
func applyOwnerProfileToRobotRoomRequest(req *createRobotRoomRequest, owner RoomOwner) error {
|
||||
roomName, roomAvatar, err := robotRoomProfileFromOwner(owner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 机器人房间对外展示必须跟随房主机器人资料,避免后台表单或脚本传入的自定义值让房间卡片和房主身份不一致。
|
||||
// 机器人房间对外展示和区域归属必须跟随房主机器人资料,避免后台表单或脚本传入的自定义值让房间卡片、区域桶和国家筛选不一致。
|
||||
req.RoomName = roomName
|
||||
req.RoomAvatar = roomAvatar
|
||||
req.VisibleRegionID = owner.VisibleRegionID
|
||||
req.OwnerCountryCode = strings.ToUpper(strings.TrimSpace(owner.CountryCode))
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -243,6 +381,12 @@ func normalizeCreateRobotRoomRequest(req createRobotRoomRequest) (createRobotRoo
|
||||
if req.MinRobotCount <= 0 || req.MaxRobotCount < req.MinRobotCount {
|
||||
return req, fmt.Errorf("%w: 机器人数量范围不正确", ErrInvalidArgument)
|
||||
}
|
||||
if req.SeatCount <= 0 {
|
||||
req.SeatCount = 10
|
||||
}
|
||||
if !validRobotRoomSeatCount(req.SeatCount) {
|
||||
return req, fmt.Errorf("%w: 麦位数不正确", ErrInvalidArgument)
|
||||
}
|
||||
candidateIDs := normalizeRobotRoomCandidateIDs([]int64(req.CandidateRobotUserIDs), ownerID)
|
||||
if len(candidateIDs) == 0 {
|
||||
return req, fmt.Errorf("%w: 请选择候选机器人", ErrInvalidArgument)
|
||||
@ -262,10 +406,28 @@ func normalizeCreateRobotRoomRequest(req createRobotRoomRequest) (createRobotRoo
|
||||
if req.LuckyPauseMinMS <= 0 || req.LuckyPauseMaxMS < req.LuckyPauseMinMS {
|
||||
return req, fmt.Errorf("%w: 幸运礼物间隔范围不正确", ErrInvalidArgument)
|
||||
}
|
||||
if req.RobotStayMinMS < 0 || req.RobotStayMaxMS < req.RobotStayMinMS {
|
||||
return req, fmt.Errorf("%w: 机器人停留时间范围不正确", ErrInvalidArgument)
|
||||
}
|
||||
if req.RobotReplaceMinMS < 0 || req.RobotReplaceMaxMS < req.RobotReplaceMinMS {
|
||||
return req, fmt.Errorf("%w: 机器人补位时间范围不正确", ErrInvalidArgument)
|
||||
}
|
||||
if req.MaxGiftSenders < 0 {
|
||||
return req, fmt.Errorf("%w: 同时送礼机器人数量不正确", ErrInvalidArgument)
|
||||
}
|
||||
req.CandidateRobotUserIDs = flexibleJSONInt64Slice(candidateIDs)
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func validRobotRoomSeatCount(seatCount int32) bool {
|
||||
switch seatCount {
|
||||
case 10, 15, 20:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeRobotRoomCandidateIDs(values []int64, ownerID int64) []int64 {
|
||||
seen := make(map[int64]bool, len(values))
|
||||
out := make([]int64, 0, len(values))
|
||||
@ -303,6 +465,8 @@ func robotRoomFromClient(item roomclient.RobotRoom) RobotRoom {
|
||||
Status: item.Status,
|
||||
OwnerRobotUserID: strconv.FormatInt(item.OwnerRobotUserID, 10),
|
||||
RobotUserIDs: robotUserIDs,
|
||||
ActiveRobotCount: item.ActiveRobotCount,
|
||||
SeatCount: item.SeatCount,
|
||||
GiftRule: RobotGiftRule{
|
||||
GiftIDs: item.GiftRule.GiftIDs,
|
||||
LuckyGiftIDs: item.GiftRule.LuckyGiftIDs,
|
||||
@ -311,6 +475,11 @@ func robotRoomFromClient(item roomclient.RobotRoom) RobotRoom {
|
||||
LuckyComboMax: item.GiftRule.LuckyComboMax,
|
||||
LuckyPauseMinMS: item.GiftRule.LuckyPauseMinMS,
|
||||
LuckyPauseMaxMS: item.GiftRule.LuckyPauseMaxMS,
|
||||
RobotStayMinMS: item.GiftRule.RobotStayMinMS,
|
||||
RobotStayMaxMS: item.GiftRule.RobotStayMaxMS,
|
||||
RobotReplaceMinMS: item.GiftRule.RobotReplaceMinMS,
|
||||
RobotReplaceMaxMS: item.GiftRule.RobotReplaceMaxMS,
|
||||
MaxGiftSenders: item.GiftRule.MaxGiftSenders,
|
||||
},
|
||||
CreatedByAdminID: item.CreatedByAdminID,
|
||||
CreatedAtMS: item.CreatedAtMS,
|
||||
|
||||
@ -17,11 +17,15 @@ func RegisterRoutes(protected *gin.RouterGroup, h *Handler) {
|
||||
protected.DELETE("/admin/rooms/pins/:pin_id", middleware.RequirePermission("room-pin:cancel"), h.CancelRoomPin)
|
||||
protected.GET("/admin/rooms/robot-rooms", middleware.RequirePermission("room-robot:view"), h.ListRobotRooms)
|
||||
protected.GET("/admin/rooms/robot-rooms/available-robots", middleware.RequirePermission("room-robot:view"), h.ListAvailableRoomRobots)
|
||||
protected.GET("/admin/rooms/robot-rooms/human-config", middleware.RequirePermission("room-robot:view"), h.GetHumanRoomRobotConfig)
|
||||
protected.PUT("/admin/rooms/robot-rooms/human-config", middleware.RequirePermission("room-robot:update"), h.UpdateHumanRoomRobotConfig)
|
||||
protected.POST("/admin/rooms/robot-rooms", middleware.RequirePermission("room-robot:create"), h.CreateRobotRoom)
|
||||
protected.POST("/admin/rooms/robot-rooms/:room_id/start", middleware.RequirePermission("room-robot:update"), h.StartRobotRoom)
|
||||
protected.POST("/admin/rooms/robot-rooms/:room_id/stop", middleware.RequirePermission("room-robot:update"), h.StopRobotRoom)
|
||||
protected.GET("/admin/rooms/config", middleware.RequirePermission("room-config:view"), h.GetRoomConfig)
|
||||
protected.PUT("/admin/rooms/config", middleware.RequirePermission("room-config:update"), h.UpdateRoomConfig)
|
||||
protected.GET("/admin/rooms/whitelist", middleware.RequirePermission("room-whitelist:view"), h.GetRoomWhitelistConfig)
|
||||
protected.PUT("/admin/rooms/whitelist", middleware.RequirePermission("room-whitelist:update"), h.UpdateRoomWhitelistConfig)
|
||||
protected.PATCH("/admin/rooms/:room_id", middleware.RequirePermission("room:update"), h.UpdateRoom)
|
||||
protected.DELETE("/admin/rooms/:room_id", middleware.RequirePermission("room:delete"), h.DeleteRoom)
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
"hyapp-admin-server/internal/integration/robotclient"
|
||||
"hyapp-admin-server/internal/integration/roomclient"
|
||||
"hyapp-admin-server/internal/modules/shared"
|
||||
"hyapp-admin-server/internal/repository"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -24,15 +25,18 @@ var (
|
||||
|
||||
type Service struct {
|
||||
userDB *sql.DB
|
||||
store *repository.Store
|
||||
roomClient roomclient.Client
|
||||
robotClient robotclient.Client
|
||||
}
|
||||
|
||||
type RoomOwner struct {
|
||||
Avatar string `json:"avatar"`
|
||||
DisplayUserID string `json:"displayUserId"`
|
||||
UserID string `json:"userId"`
|
||||
Username string `json:"username"`
|
||||
Avatar string `json:"avatar"`
|
||||
CountryCode string `json:"countryCode,omitempty"`
|
||||
DisplayUserID string `json:"displayUserId"`
|
||||
UserID string `json:"userId"`
|
||||
Username string `json:"username"`
|
||||
VisibleRegionID int64 `json:"visibleRegionId,omitempty"`
|
||||
}
|
||||
|
||||
type Room struct {
|
||||
@ -60,8 +64,8 @@ type Room struct {
|
||||
VisibleRegionID int64 `json:"visibleRegionId"`
|
||||
}
|
||||
|
||||
func NewService(userDB *sql.DB, roomClient roomclient.Client, robotClient robotclient.Client) *Service {
|
||||
return &Service{userDB: userDB, roomClient: roomClient, robotClient: robotClient}
|
||||
func NewService(userDB *sql.DB, store *repository.Store, roomClient roomclient.Client, robotClient robotclient.Client) *Service {
|
||||
return &Service{userDB: userDB, store: store, roomClient: roomClient, robotClient: robotClient}
|
||||
}
|
||||
|
||||
func (s *Service) ListRooms(ctx context.Context, query listQuery) ([]Room, int64, error) {
|
||||
@ -463,7 +467,9 @@ func (s *Service) queryRoomOwners(ctx context.Context, ownerIDs []int64) (map[in
|
||||
SELECT user_id,
|
||||
current_display_user_id,
|
||||
COALESCE(username, ''),
|
||||
COALESCE(avatar, '')
|
||||
COALESCE(avatar, ''),
|
||||
COALESCE(country, ''),
|
||||
COALESCE(region_id, 0)
|
||||
FROM users
|
||||
WHERE app_code = ? AND user_id IN (`+placeholders(len(ownerIDs))+`)
|
||||
`, args...)
|
||||
@ -475,7 +481,7 @@ func (s *Service) queryRoomOwners(ctx context.Context, ownerIDs []int64) (map[in
|
||||
for rows.Next() {
|
||||
var userID int64
|
||||
var owner RoomOwner
|
||||
if err := rows.Scan(&userID, &owner.DisplayUserID, &owner.Username, &owner.Avatar); err != nil {
|
||||
if err := rows.Scan(&userID, &owner.DisplayUserID, &owner.Username, &owner.Avatar, &owner.CountryCode, &owner.VisibleRegionID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
owner.UserID = strconv.FormatInt(userID, 10)
|
||||
|
||||
@ -3,8 +3,13 @@ package roomadmin
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"hyapp-admin-server/internal/integration/robotclient"
|
||||
)
|
||||
|
||||
@ -78,6 +83,30 @@ func TestRobotRoomProfileFromOwnerRequiresNameAndAvatar(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyOwnerProfileToRobotRoomRequestFollowsOwnerRegionAndCountry(t *testing.T) {
|
||||
req := createRobotRoomRequest{
|
||||
RoomName: "manual name",
|
||||
RoomAvatar: "https://cdn.example.com/manual.png",
|
||||
VisibleRegionID: 999,
|
||||
OwnerCountryCode: "XX",
|
||||
}
|
||||
err := applyOwnerProfileToRobotRoomRequest(&req, RoomOwner{
|
||||
Username: " Robot Owner ",
|
||||
Avatar: " https://cdn.example.com/owner.png ",
|
||||
CountryCode: " ae ",
|
||||
VisibleRegionID: 686,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("apply owner profile failed: %v", err)
|
||||
}
|
||||
if req.RoomName != "Robot Owner" || req.RoomAvatar != "https://cdn.example.com/owner.png" {
|
||||
t.Fatalf("owner display profile mismatch: name=%q avatar=%q", req.RoomName, req.RoomAvatar)
|
||||
}
|
||||
if req.VisibleRegionID != 686 || req.OwnerCountryCode != "AE" {
|
||||
t.Fatalf("owner region or country mismatch: region=%d country=%q", req.VisibleRegionID, req.OwnerCountryCode)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateRobotRoomRequestAcceptsStringInt64IDs(t *testing.T) {
|
||||
var req createRobotRoomRequest
|
||||
if err := json.Unmarshal([]byte(`{
|
||||
@ -108,6 +137,61 @@ func TestCreateRobotRoomRequestAcceptsStringInt64IDs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateRobotRoomRequestBindsStringInt64IDsFromHTTP(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
body := `{
|
||||
"ownerRobotUserId":"325379237278126080",
|
||||
"candidateRobotUserIds":["325455441691676672"],
|
||||
"minRobotCount":2,
|
||||
"maxRobotCount":8,
|
||||
"giftIds":["84"],
|
||||
"luckyGiftIds":["28"],
|
||||
"normalGiftIntervalMs":10000,
|
||||
"luckyComboMin":100,
|
||||
"luckyComboMax":10000,
|
||||
"luckyPauseMinMs":5000,
|
||||
"luckyPauseMaxMs":20000
|
||||
}`
|
||||
req := httptest.NewRequest(http.MethodPost, "/admin/rooms/robot-rooms", strings.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rec := httptest.NewRecorder()
|
||||
ctx, _ := gin.CreateTestContext(rec)
|
||||
ctx.Request = req
|
||||
|
||||
var payload createRobotRoomRequest
|
||||
if err := ctx.ShouldBindJSON(&payload); err != nil {
|
||||
t.Fatalf("gin binding should accept string int64 ids: %v", err)
|
||||
}
|
||||
if got := int64(payload.OwnerRobotUserID); got != 325379237278126080 {
|
||||
t.Fatalf("owner id mismatch: got %d", got)
|
||||
}
|
||||
if got := []int64(payload.CandidateRobotUserIDs); len(got) != 1 || got[0] != 325455441691676672 {
|
||||
t.Fatalf("candidate ids mismatch: %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeRoomWhitelistUserIDsKeepsStringInt64Order(t *testing.T) {
|
||||
got, err := normalizeRoomWhitelistUserIDs([]string{"325379237278126080", "1001", "1001"})
|
||||
if err != nil {
|
||||
t.Fatalf("normalize room whitelist failed: %v", err)
|
||||
}
|
||||
want := []string{"1001", "325379237278126080"}
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("whitelist length mismatch: got %+v want %+v", got, want)
|
||||
}
|
||||
for index := range want {
|
||||
if got[index] != want[index] {
|
||||
t.Fatalf("whitelist id %d mismatch: got %+v want %+v", index, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeRoomWhitelistUserIDsRejectsInvalidID(t *testing.T) {
|
||||
if _, err := normalizeRoomWhitelistUserIDs([]string{"1.2"}); !errors.Is(err, ErrInvalidArgument) {
|
||||
t.Fatalf("invalid id should return ErrInvalidArgument, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAvailableRoomRobotsFromGamePoolKeepsOnlyRoomAvailableUsers(t *testing.T) {
|
||||
robots := []robotclient.Robot{
|
||||
{UserID: 101, Status: "active", LastUsedAtMS: 1000, UsedCount: 2},
|
||||
|
||||
112
server/admin/internal/modules/roomadmin/whitelist.go
Normal file
112
server/admin/internal/modules/roomadmin/whitelist.go
Normal file
@ -0,0 +1,112 @@
|
||||
package roomadmin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"hyapp-admin-server/internal/appctx"
|
||||
"hyapp-admin-server/internal/model"
|
||||
)
|
||||
|
||||
const roomRegionWhitelistGroup = "room-region-whitelist"
|
||||
|
||||
type RoomWhitelistConfig struct {
|
||||
UserIDs []string `json:"userIds"`
|
||||
UpdatedAtMS int64 `json:"updatedAtMs"`
|
||||
}
|
||||
|
||||
type roomRegionWhitelistValue struct {
|
||||
UserIDs []string `json:"user_ids"`
|
||||
}
|
||||
|
||||
// GetRoomWhitelistConfig 读取当前 app 的房间区域白名单;缺行时返回空集合,表示所有用户仍受区域限制。
|
||||
func (s *Service) GetRoomWhitelistConfig(ctx context.Context) (RoomWhitelistConfig, error) {
|
||||
if s.store == nil {
|
||||
return RoomWhitelistConfig{}, fmt.Errorf("admin store is not configured")
|
||||
}
|
||||
item, err := s.store.GetAppConfig(roomRegionWhitelistGroup, appctx.FromContext(ctx))
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return RoomWhitelistConfig{UserIDs: []string{}}, nil
|
||||
}
|
||||
if err != nil {
|
||||
return RoomWhitelistConfig{}, err
|
||||
}
|
||||
userIDs, err := roomWhitelistIDsFromValue(item.Value)
|
||||
if err != nil {
|
||||
return RoomWhitelistConfig{}, err
|
||||
}
|
||||
return RoomWhitelistConfig{UserIDs: userIDs, UpdatedAtMS: item.UpdatedAtMS}, nil
|
||||
}
|
||||
|
||||
// UpdateRoomWhitelistConfig 覆盖当前 app 的房间区域白名单;gateway 会在最多五分钟内通过 Redis 缓存刷新结果。
|
||||
func (s *Service) UpdateRoomWhitelistConfig(ctx context.Context, req updateRoomWhitelistRequest) (RoomWhitelistConfig, error) {
|
||||
if s.store == nil {
|
||||
return RoomWhitelistConfig{}, fmt.Errorf("admin store is not configured")
|
||||
}
|
||||
userIDs, err := normalizeRoomWhitelistUserIDs(req.UserIDs)
|
||||
if err != nil {
|
||||
return RoomWhitelistConfig{}, err
|
||||
}
|
||||
payload, err := json.Marshal(roomRegionWhitelistValue{UserIDs: userIDs})
|
||||
if err != nil {
|
||||
return RoomWhitelistConfig{}, err
|
||||
}
|
||||
item := model.AppConfig{
|
||||
Group: roomRegionWhitelistGroup,
|
||||
Key: appctx.FromContext(ctx),
|
||||
Value: string(payload),
|
||||
Description: "房间区域白名单用户,命中后 App 房间列表不按用户 region_id 过滤",
|
||||
}
|
||||
if err := s.store.UpsertAppConfigs([]model.AppConfig{item}); err != nil {
|
||||
return RoomWhitelistConfig{}, err
|
||||
}
|
||||
return s.GetRoomWhitelistConfig(ctx)
|
||||
}
|
||||
|
||||
func roomWhitelistIDsFromValue(raw string) ([]string, error) {
|
||||
raw = strings.TrimSpace(raw)
|
||||
if raw == "" {
|
||||
return []string{}, nil
|
||||
}
|
||||
var payload roomRegionWhitelistValue
|
||||
if strings.HasPrefix(raw, "[") {
|
||||
if err := json.Unmarshal([]byte(raw), &payload.UserIDs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if err := json.Unmarshal([]byte(raw), &payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return normalizeRoomWhitelistUserIDs(payload.UserIDs)
|
||||
}
|
||||
|
||||
func normalizeRoomWhitelistUserIDs(values []string) ([]string, error) {
|
||||
seen := make(map[int64]struct{}, len(values))
|
||||
out := make([]int64, 0, len(values))
|
||||
for _, value := range values {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" {
|
||||
continue
|
||||
}
|
||||
id, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil || id <= 0 {
|
||||
return nil, fmt.Errorf("%w: 用户 ID 不正确", ErrInvalidArgument)
|
||||
}
|
||||
if _, ok := seen[id]; ok {
|
||||
continue
|
||||
}
|
||||
seen[id] = struct{}{}
|
||||
out = append(out, id)
|
||||
}
|
||||
slices.Sort(out)
|
||||
result := make([]string, 0, len(out))
|
||||
for _, id := range out {
|
||||
result = append(result, strconv.FormatInt(id, 10))
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
@ -36,6 +36,8 @@ var defaultPermissions = []model.Permission{
|
||||
{Name: "房间置顶取消", Code: "room-pin:cancel", Kind: "button"},
|
||||
{Name: "房间配置查看", Code: "room-config:view", Kind: "menu"},
|
||||
{Name: "房间配置更新", Code: "room-config:update", Kind: "button"},
|
||||
{Name: "房间白名单查看", Code: "room-whitelist:view", Kind: "menu"},
|
||||
{Name: "房间白名单更新", Code: "room-whitelist:update", Kind: "button"},
|
||||
{Name: "机器人房间查看", Code: "room-robot:view", Kind: "menu"},
|
||||
{Name: "机器人房间创建", Code: "room-robot:create", Kind: "button"},
|
||||
{Name: "机器人房间更新", Code: "room-robot:update", Kind: "button"},
|
||||
@ -263,7 +265,8 @@ func (s *Store) seedMenus() error {
|
||||
{ParentID: &roomsID, Title: "房间列表", Code: "room-list", Path: "/rooms", Icon: "room", PermissionCode: "room:view", Sort: 65, Visible: true},
|
||||
{ParentID: &roomsID, Title: "房间置顶", Code: "room-pins", Path: "/rooms/pins", Icon: "push_pin", PermissionCode: "room-pin:view", Sort: 66, Visible: true},
|
||||
{ParentID: &roomsID, Title: "房间配置", Code: "room-config", Path: "/rooms/config", Icon: "settings", PermissionCode: "room-config:view", Sort: 67, Visible: true},
|
||||
{ParentID: &roomsID, Title: "机器人房间", Code: "room-robots", Path: "/rooms/robots", Icon: "team", PermissionCode: "room-robot:view", Sort: 68, Visible: true},
|
||||
{ParentID: &roomsID, Title: "房间白名单", Code: "room-whitelist", Path: "/rooms/whitelist", Icon: "shield", PermissionCode: "room-whitelist:view", Sort: 68, Visible: true},
|
||||
{ParentID: &roomsID, Title: "机器人房间", Code: "room-robots", Path: "/rooms/robots", Icon: "team", PermissionCode: "room-robot:view", Sort: 69, Visible: true},
|
||||
{ParentID: &appConfigID, Title: "H5配置", Code: "app-config-h5", Path: "/app-config/h5", Icon: "settings", PermissionCode: "app-config:view", Sort: 66, Visible: true},
|
||||
{ParentID: &appConfigID, Title: "BANNER配置", Code: "app-config-banners", Path: "/app-config/banners", Icon: "image", PermissionCode: "app-config:view", Sort: 67, Visible: true},
|
||||
{ParentID: &appConfigID, Title: "开屏配置", Code: "app-config-splash-screens", Path: "/app-config/splash-screens", Icon: "image", PermissionCode: "app-config:view", Sort: 68, Visible: true},
|
||||
@ -522,7 +525,7 @@ func defaultRolePermissionCodes(code string) []string {
|
||||
"level-config:view", "level-config:update",
|
||||
"pretty-id:view", "pretty-id:update", "pretty-id:generate", "pretty-id:grant",
|
||||
"region-block:view", "region-block:update",
|
||||
"room:view", "room:update", "room:delete", "room-pin:view", "room-pin:create", "room-pin:cancel", "room-config:view", "room-config:update", "room-robot:view", "room-robot:create", "room-robot:update",
|
||||
"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",
|
||||
"resource:view", "resource:create", "resource:update",
|
||||
@ -554,7 +557,7 @@ func defaultRolePermissionCodes(code string) []string {
|
||||
"upload:create",
|
||||
}
|
||||
case "auditor":
|
||||
return []string{"overview:view", "log:view", "user:view", "app-user:view", "level-config:view", "pretty-id:view", "region-block:view", "room:view", "room-pin:view", "room-config:view", "room-robot:view", "app-config:view", "app-version:view", "resource:view", "resource-shop:view", "resource-group:view", "resource-grant:view", "gift:view", "emoji-pack:view", "host-agency-policy:view", "team-salary-policy:view", "host-salary-settlement:view", "coin-ledger:view", "coin-seller-ledger:view", "coin-adjustment:view", "report:view", "gift-diamond:view", "full-server-notice:view", "lucky-gift:view", "payment-bill:view", "payment-third-party:view", "payment-product:view", "game:view", "daily-task:view", "achievement:view", "seven-day-checkin:view", "room-rocket:view", "red-packet:view", "cp-config:view", "vip-config:view", "weekly-star:view", "agency-opening:view", "role:view", "permission:view", "job:view"}
|
||||
return []string{"overview:view", "log:view", "user:view", "app-user:view", "level-config:view", "pretty-id:view", "region-block:view", "room:view", "room-pin:view", "room-config:view", "room-whitelist:view", "room-robot:view", "app-config:view", "app-version:view", "resource:view", "resource-shop:view", "resource-group:view", "resource-grant:view", "gift:view", "emoji-pack:view", "host-agency-policy:view", "team-salary-policy:view", "host-salary-settlement:view", "coin-ledger:view", "coin-seller-ledger:view", "coin-adjustment:view", "report:view", "gift-diamond:view", "full-server-notice:view", "lucky-gift:view", "payment-bill:view", "payment-third-party:view", "payment-product:view", "game:view", "daily-task:view", "achievement:view", "seven-day-checkin:view", "room-rocket:view", "red-packet:view", "cp-config:view", "vip-config:view", "weekly-star:view", "agency-opening:view", "role:view", "permission:view", "job:view"}
|
||||
case "readonly":
|
||||
return []string{
|
||||
"overview:view",
|
||||
@ -566,6 +569,7 @@ func defaultRolePermissionCodes(code string) []string {
|
||||
"room:view",
|
||||
"room-pin:view",
|
||||
"room-config:view",
|
||||
"room-whitelist:view",
|
||||
"room-robot:view",
|
||||
"app-config:view",
|
||||
"app-version:view",
|
||||
@ -620,7 +624,7 @@ func defaultRolePermissionMigrationCodes(code string) []string {
|
||||
case "ops-admin":
|
||||
return []string{
|
||||
"app-user:update", "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-robot:view", "room-robot:create", "room-robot:update",
|
||||
"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",
|
||||
"level-config:view", "level-config:update",
|
||||
@ -651,7 +655,7 @@ func defaultRolePermissionMigrationCodes(code string) []string {
|
||||
"agency-opening:view", "agency-opening:create", "agency-opening:update",
|
||||
}
|
||||
case "auditor", "readonly":
|
||||
return []string{"level-config:view", "pretty-id:view", "region-block:view", "room:view", "room-pin:view", "room-config:view", "room-robot:view", "app-config:view", "app-version:view", "resource:view", "resource-shop:view", "resource-group:view", "resource-grant:view", "gift:view", "emoji-pack:view", "host-agency-policy:view", "team-salary-policy:view", "host-salary-settlement:view", "coin-seller:view", "coin-ledger:view", "coin-seller-ledger:view", "coin-adjustment:view", "report:view", "gift-diamond:view", "full-server-notice:view", "lucky-gift:view", "payment-bill:view", "payment-third-party:view", "payment-product:view", "game:view", "daily-task:view", "achievement:view", "seven-day-checkin:view", "room-rocket:view", "red-packet:view", "cp-config:view", "vip-config:view", "weekly-star:view", "agency-opening:view"}
|
||||
return []string{"level-config:view", "pretty-id:view", "region-block:view", "room:view", "room-pin:view", "room-config:view", "room-whitelist:view", "room-robot:view", "app-config:view", "app-version:view", "resource:view", "resource-shop:view", "resource-group:view", "resource-grant:view", "gift:view", "emoji-pack:view", "host-agency-policy:view", "team-salary-policy:view", "host-salary-settlement:view", "coin-seller:view", "coin-ledger:view", "coin-seller-ledger:view", "coin-adjustment:view", "report:view", "gift-diamond:view", "full-server-notice:view", "lucky-gift:view", "payment-bill:view", "payment-third-party:view", "payment-product:view", "game:view", "daily-task:view", "achievement:view", "seven-day-checkin:view", "room-rocket:view", "red-packet:view", "cp-config:view", "vip-config:view", "weekly-star:view", "agency-opening:view"}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
ALTER TABLE admin_app_banners
|
||||
ADD COLUMN room_small_image_url VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '房间内小屏图 URL' AFTER cover_url,
|
||||
ADD COLUMN display_scope VARCHAR(32) NOT NULL DEFAULT 'home' COMMENT '显示范围:首页、房间内或充值页' AFTER banner_type,
|
||||
ADD COLUMN display_scope VARCHAR(32) NOT NULL DEFAULT 'home' COMMENT '显示范围:首页、房间内、充值页或我的页' AFTER banner_type,
|
||||
ADD COLUMN starts_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '投放开始时间,UTC epoch ms' AFTER status,
|
||||
ADD COLUMN ends_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '投放结束时间,UTC epoch ms' AFTER starts_at_ms,
|
||||
ADD INDEX idx_admin_app_banners_display (app_code, display_scope, status, starts_at_ms, ends_at_ms, sort_order, id);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- Banner 显示范围支持多选,display_scope 以稳定逗号分隔值保存,例如 home,room,recharge。
|
||||
-- Banner 显示范围支持多选,display_scope 以稳定逗号分隔值保存,例如 home,room,recharge,me。
|
||||
|
||||
ALTER TABLE admin_app_banners
|
||||
MODIFY COLUMN display_scope VARCHAR(128) NOT NULL DEFAULT 'home' COMMENT '显示范围,多选逗号分隔:首页、房间内或充值页';
|
||||
MODIFY COLUMN display_scope VARCHAR(128) NOT NULL DEFAULT 'home' COMMENT '显示范围,多选逗号分隔:首页、房间内、充值页或我的页';
|
||||
|
||||
41
server/admin/migrations/055_room_whitelist_navigation.sql
Normal file
41
server/admin/migrations/055_room_whitelist_navigation.sql
Normal file
@ -0,0 +1,41 @@
|
||||
-- 房间白名单允许指定用户在 App 房间列表绕过 visible_region_id 过滤;本迁移只写后台菜单和权限事实。
|
||||
SET @now_ms := UNIX_TIMESTAMP(UTC_TIMESTAMP(3)) * 1000;
|
||||
|
||||
INSERT INTO admin_permissions (name, code, kind, description, created_at_ms, updated_at_ms) VALUES
|
||||
('房间白名单查看', 'room-whitelist:view', 'menu', '允许查看房间白名单配置', @now_ms, @now_ms),
|
||||
('房间白名单更新', 'room-whitelist:update', 'button', '允许更新房间白名单配置', @now_ms, @now_ms)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
name = VALUES(name),
|
||||
kind = VALUES(kind),
|
||||
description = VALUES(description),
|
||||
updated_at_ms = VALUES(updated_at_ms);
|
||||
|
||||
INSERT INTO admin_menus (parent_id, title, code, path, icon, permission_code, sort, visible, created_at_ms, updated_at_ms)
|
||||
SELECT parent.id, '房间白名单', 'room-whitelist', '/rooms/whitelist', 'shield', 'room-whitelist:view', 68, TRUE, @now_ms, @now_ms
|
||||
FROM admin_menus parent
|
||||
WHERE parent.code = 'rooms'
|
||||
ON DUPLICATE KEY UPDATE
|
||||
parent_id = VALUES(parent_id),
|
||||
title = VALUES(title),
|
||||
path = VALUES(path),
|
||||
icon = VALUES(icon),
|
||||
permission_code = VALUES(permission_code),
|
||||
sort = VALUES(sort),
|
||||
visible = VALUES(visible),
|
||||
updated_at_ms = VALUES(updated_at_ms);
|
||||
|
||||
UPDATE admin_menus
|
||||
SET sort = 69, updated_at_ms = @now_ms
|
||||
WHERE code = 'room-robots' AND sort < 69;
|
||||
|
||||
INSERT IGNORE INTO admin_role_permissions (role_id, permission_id)
|
||||
SELECT r.id, p.id
|
||||
FROM admin_roles r
|
||||
JOIN admin_permissions p ON p.code IN ('room-whitelist:view', 'room-whitelist:update')
|
||||
WHERE r.code IN ('platform-admin', 'ops-admin');
|
||||
|
||||
INSERT IGNORE INTO admin_role_permissions (role_id, permission_id)
|
||||
SELECT r.id, p.id
|
||||
FROM admin_roles r
|
||||
JOIN admin_permissions p ON p.code = 'room-whitelist:view'
|
||||
WHERE r.code IN ('auditor', 'readonly');
|
||||
@ -37,9 +37,9 @@ lucky_gift_worker:
|
||||
tencent_im:
|
||||
# Docker 本地联调全局/区域播报群;必须与 gateway/room-service 使用同一组腾讯 IM 应用配置。
|
||||
enabled: true
|
||||
sdk_app_id: 20036101
|
||||
secret_key: "dcdf53135f27e7cf8541c4ae9798fb0cb2f0e4d6c5c20022dbaea053f35cbb8c"
|
||||
admin_identifier: "900100100"
|
||||
sdk_app_id: 20040101
|
||||
secret_key: "2f6a5ec58cccf79647557a96c15e6efe89ba5a44c474096bde2589a633fcd45e"
|
||||
admin_identifier: "administrator"
|
||||
admin_user_sig_ttl: "24h"
|
||||
endpoint: "adminapisgp.im.qcloud.com"
|
||||
group_type: "ChatRoom"
|
||||
|
||||
@ -37,9 +37,9 @@ lucky_gift_worker:
|
||||
tencent_im:
|
||||
# activity-service 只负责全局/区域播报群;必须与 gateway/room-service 使用同一组腾讯 IM 应用配置。
|
||||
enabled: true
|
||||
sdk_app_id: 20036101
|
||||
secret_key: "dcdf53135f27e7cf8541c4ae9798fb0cb2f0e4d6c5c20022dbaea053f35cbb8c"
|
||||
admin_identifier: "900100100"
|
||||
sdk_app_id: 20040101
|
||||
secret_key: "2f6a5ec58cccf79647557a96c15e6efe89ba5a44c474096bde2589a633fcd45e"
|
||||
admin_identifier: "administrator"
|
||||
admin_user_sig_ttl: "24h"
|
||||
endpoint: "adminapisgp.im.qcloud.com"
|
||||
group_type: "ChatRoom"
|
||||
|
||||
@ -236,8 +236,8 @@ func (s *Service) SetUserLevel(ctx context.Context, command domain.SetUserLevelC
|
||||
if !validTrack(command.Track) {
|
||||
return domain.SetUserLevelResult{}, xerr.New(xerr.InvalidArgument, "track is invalid")
|
||||
}
|
||||
if command.Level < 1 || command.Level > 11 {
|
||||
return domain.SetUserLevelResult{}, xerr.New(xerr.InvalidArgument, "level must be between 1 and 11")
|
||||
if command.Level < 1 || command.Level > 30 {
|
||||
return domain.SetUserLevelResult{}, xerr.New(xerr.InvalidArgument, "level must be between 1 and 30")
|
||||
}
|
||||
if command.Reason == "" {
|
||||
command.Reason = "manager_center_level"
|
||||
|
||||
@ -12,9 +12,9 @@ launch_session_ttl: "15m"
|
||||
tencent_im:
|
||||
# Docker/testbox 联调房内猜拳 PK 房间群消息;必须和 gateway/room 使用同一个 IM 应用。
|
||||
enabled: true
|
||||
sdk_app_id: 20036101
|
||||
secret_key: "dcdf53135f27e7cf8541c4ae9798fb0cb2f0e4d6c5c20022dbaea053f35cbb8c"
|
||||
admin_identifier: "900100100"
|
||||
sdk_app_id: 20040101
|
||||
secret_key: "2f6a5ec58cccf79647557a96c15e6efe89ba5a44c474096bde2589a633fcd45e"
|
||||
admin_identifier: "administrator"
|
||||
admin_user_sig_ttl: "24h"
|
||||
endpoint: "adminapisgp.im.qcloud.com"
|
||||
group_type: "ChatRoom"
|
||||
|
||||
@ -12,9 +12,9 @@ launch_session_ttl: "15m"
|
||||
tencent_im:
|
||||
# 本地联调房内猜拳 PK 房间群消息;必须和 gateway/room 使用同一个 IM 应用。
|
||||
enabled: true
|
||||
sdk_app_id: 20036101
|
||||
secret_key: "dcdf53135f27e7cf8541c4ae9798fb0cb2f0e4d6c5c20022dbaea053f35cbb8c"
|
||||
admin_identifier: "900100100"
|
||||
sdk_app_id: 20040101
|
||||
secret_key: "2f6a5ec58cccf79647557a96c15e6efe89ba5a44c474096bde2589a633fcd45e"
|
||||
admin_identifier: "administrator"
|
||||
admin_user_sig_ttl: "24h"
|
||||
endpoint: "adminapisgp.im.qcloud.com"
|
||||
group_type: "ChatRoom"
|
||||
|
||||
@ -51,6 +51,12 @@ grpc_client:
|
||||
app_config:
|
||||
# App 运行时配置由后台 APP配置写入 hyapp_admin,gateway 只读下发给 App。
|
||||
mysql_dsn: "hyapp:hyapp@tcp(mysql:3306)/hyapp_admin?parseTime=true&charset=utf8mb4&loc=UTC"
|
||||
# 房间白名单等低频配置用 Redis 缓存 5 分钟,避免每次列表请求查后台库。
|
||||
redis_addr: "redis:6379"
|
||||
redis_password: ""
|
||||
redis_db: 0
|
||||
key_prefix: "gateway:app_config:"
|
||||
cache_ttl: "5m"
|
||||
leaderboard:
|
||||
# 活动用户榜单只读 wallet_transactions 的送礼事实;时间窗口统一按 UTC 计算。
|
||||
wallet_mysql_dsn: "hyapp:hyapp@tcp(mysql:3306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=UTC"
|
||||
@ -81,9 +87,9 @@ login_risk:
|
||||
blocked_timezone_prefixes: []
|
||||
tencent_im:
|
||||
# Docker 本地联调腾讯云 IM UserSig;必须与 room-service 使用同一组应用配置。
|
||||
sdk_app_id: 20036101
|
||||
secret_key: "dcdf53135f27e7cf8541c4ae9798fb0cb2f0e4d6c5c20022dbaea053f35cbb8c"
|
||||
admin_identifier: "900100100"
|
||||
sdk_app_id: 20040101
|
||||
secret_key: "2f6a5ec58cccf79647557a96c15e6efe89ba5a44c474096bde2589a633fcd45e"
|
||||
admin_identifier: "administrator"
|
||||
admin_user_sig_ttl: "24h"
|
||||
user_sig_ttl: "24h"
|
||||
endpoint: "adminapisgp.im.qcloud.com"
|
||||
|
||||
@ -55,6 +55,12 @@ grpc_client:
|
||||
app_config:
|
||||
# App 运行时配置由后台 APP配置写入 hyapp_admin,gateway 只读下发给 App。
|
||||
mysql_dsn: "TENCENT_MYSQL_USER:TENCENT_MYSQL_PASSWORD@tcp(TENCENT_MYSQL_HOST:3306)/hyapp_admin?parseTime=true&charset=utf8mb4&loc=UTC"
|
||||
# 房间白名单等低频配置用 Redis 缓存 5 分钟,避免每次列表请求查后台库。
|
||||
redis_addr: "TENCENT_REDIS_HOST:6379"
|
||||
redis_password: "TENCENT_REDIS_PASSWORD"
|
||||
redis_db: 0
|
||||
key_prefix: "gateway:app_config:"
|
||||
cache_ttl: "5m"
|
||||
leaderboard:
|
||||
# 活动用户榜单只读钱包送礼事实;线上建议配置只读账号。
|
||||
wallet_mysql_dsn: "TENCENT_MYSQL_USER:TENCENT_MYSQL_PASSWORD@tcp(TENCENT_MYSQL_HOST:3306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=UTC"
|
||||
|
||||
@ -51,6 +51,12 @@ grpc_client:
|
||||
app_config:
|
||||
# App 运行时配置由后台 APP配置写入 hyapp_admin,gateway 只读下发给 App。
|
||||
mysql_dsn: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_admin?parseTime=true&charset=utf8mb4&loc=UTC"
|
||||
# 房间白名单等低频配置用 Redis 缓存 5 分钟,避免每次列表请求查后台库。
|
||||
redis_addr: "127.0.0.1:13379"
|
||||
redis_password: ""
|
||||
redis_db: 0
|
||||
key_prefix: "gateway:app_config:"
|
||||
cache_ttl: "5m"
|
||||
leaderboard:
|
||||
# 活动用户榜单只读 wallet_transactions 的送礼事实;时间窗口统一按 UTC 计算。
|
||||
wallet_mysql_dsn: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=UTC"
|
||||
@ -81,9 +87,9 @@ login_risk:
|
||||
blocked_timezone_prefixes: []
|
||||
tencent_im:
|
||||
# 本地联调腾讯云 IM UserSig;SDKAppID 和密钥必须与 room-service 保持一致。
|
||||
sdk_app_id: 20036101
|
||||
secret_key: "dcdf53135f27e7cf8541c4ae9798fb0cb2f0e4d6c5c20022dbaea053f35cbb8c"
|
||||
admin_identifier: "900100100"
|
||||
sdk_app_id: 20040101
|
||||
secret_key: "2f6a5ec58cccf79647557a96c15e6efe89ba5a44c474096bde2589a633fcd45e"
|
||||
admin_identifier: "administrator"
|
||||
admin_user_sig_ttl: "24h"
|
||||
# 客户端 UserSig 有效期;线上建议 12h-7d,按登录刷新策略决定。
|
||||
user_sig_ttl: "24h"
|
||||
|
||||
@ -345,7 +345,22 @@ func openAppConfigReader(cfg config.AppConfigConfig) (*appconfig.MySQLReader, er
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return appconfig.OpenMySQLReader(cfg.MySQLDSN)
|
||||
reader, err := appconfig.OpenMySQLReader(cfg.MySQLDSN)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if strings.TrimSpace(cfg.RedisAddr) == "" {
|
||||
return reader, nil
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
cacheClient, err := appconfig.OpenRedisCache(ctx, cfg.RedisAddr, cfg.RedisPassword, cfg.RedisDB)
|
||||
if err != nil {
|
||||
_ = reader.Close()
|
||||
return nil, fmt.Errorf("connect app config redis: %w", err)
|
||||
}
|
||||
reader.SetRedisCache(cacheClient, cfg.KeyPrefix, cfg.CacheTTL)
|
||||
return reader, nil
|
||||
}
|
||||
|
||||
func openLeaderboardWalletDB(cfg config.LeaderboardConfig) (*sql.DB, error) {
|
||||
|
||||
@ -4,17 +4,21 @@ package appconfig
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
mysqlDriver "github.com/go-sql-driver/mysql"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
const h5LinkGroup = "h5-links"
|
||||
const roomRegionWhitelistGroup = "room-region-whitelist"
|
||||
|
||||
const listH5LinksSQL = "SELECT `key`, COALESCE(description, ''), COALESCE(value, ''), updated_at_ms FROM admin_app_configs WHERE `group` = ? ORDER BY `key` ASC"
|
||||
const getRoomRegionWhitelistSQL = "SELECT COALESCE(value, '') FROM admin_app_configs WHERE `group` = ? AND `key` = ? LIMIT 1"
|
||||
const bdLeaderPositionAliasSQL = `
|
||||
SELECT position_alias
|
||||
FROM admin_bd_leader_position_aliases
|
||||
@ -185,11 +189,15 @@ type Reader interface {
|
||||
ListSplashScreens(ctx context.Context, query SplashScreenQuery) ([]SplashScreen, error)
|
||||
ListPopups(ctx context.Context, query PopupQuery) ([]Popup, error)
|
||||
LatestVersion(ctx context.Context, query VersionQuery) (Version, error)
|
||||
RoomRegionWhitelistAllows(ctx context.Context, appCode string, userID int64) (bool, error)
|
||||
}
|
||||
|
||||
// MySQLReader 从 hyapp_admin 读取后台 App 配置。
|
||||
type MySQLReader struct {
|
||||
db *sql.DB
|
||||
db *sql.DB
|
||||
cache *redis.Client
|
||||
cachePrefix string
|
||||
cacheTTL time.Duration
|
||||
}
|
||||
|
||||
// OpenMySQLReader 创建后台配置只读连接池。
|
||||
@ -208,7 +216,44 @@ func (r *MySQLReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
return r.db.Close()
|
||||
return errors.Join(r.db.Close(), r.closeCache())
|
||||
}
|
||||
|
||||
func (r *MySQLReader) closeCache() error {
|
||||
if r == nil || r.cache == nil {
|
||||
return nil
|
||||
}
|
||||
return r.cache.Close()
|
||||
}
|
||||
|
||||
// OpenRedisCache 创建 App 配置 Redis 缓存连接;启动期探测失败直接暴露配置问题。
|
||||
func OpenRedisCache(ctx context.Context, addr string, password string, db int) (*redis.Client, error) {
|
||||
client := redis.NewClient(&redis.Options{
|
||||
Addr: strings.TrimSpace(addr),
|
||||
Password: password,
|
||||
DB: db,
|
||||
})
|
||||
if err := client.Ping(ctx).Err(); err != nil {
|
||||
_ = client.Close()
|
||||
return nil, err
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// SetRedisCache 给低频后台配置挂 Redis 五分钟读缓存,避免房间列表每次都查 hyapp_admin。
|
||||
func (r *MySQLReader) SetRedisCache(client *redis.Client, keyPrefix string, ttl time.Duration) {
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
r.cache = client
|
||||
r.cachePrefix = strings.TrimSpace(keyPrefix)
|
||||
if r.cachePrefix == "" {
|
||||
r.cachePrefix = "gateway:app_config:"
|
||||
}
|
||||
if ttl <= 0 {
|
||||
ttl = 5 * time.Minute
|
||||
}
|
||||
r.cacheTTL = ttl
|
||||
}
|
||||
|
||||
// ListH5Links 返回后台动态维护的 H5 入口集合。
|
||||
@ -466,6 +511,102 @@ func (r *MySQLReader) LatestVersion(ctx context.Context, query VersionQuery) (Ve
|
||||
return item, nil
|
||||
}
|
||||
|
||||
// RoomRegionWhitelistAllows 判断用户是否可绕过房间区域限制;结果按 app+user 缓存五分钟。
|
||||
func (r *MySQLReader) RoomRegionWhitelistAllows(ctx context.Context, appCode string, userID int64) (bool, error) {
|
||||
if userID <= 0 {
|
||||
return false, nil
|
||||
}
|
||||
if r == nil || r.db == nil {
|
||||
return false, errors.New("app config reader is not configured")
|
||||
}
|
||||
app := normalizeAppCode(appCode)
|
||||
if cached, ok, err := r.cachedRoomRegionWhitelist(ctx, app, userID); err == nil && ok {
|
||||
return cached, nil
|
||||
}
|
||||
|
||||
allowed, err := r.roomRegionWhitelistAllowsFromDB(ctx, app, userID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
r.storeRoomRegionWhitelistCache(ctx, app, userID, allowed)
|
||||
return allowed, nil
|
||||
}
|
||||
|
||||
func (r *MySQLReader) roomRegionWhitelistAllowsFromDB(ctx context.Context, appCode string, userID int64) (bool, error) {
|
||||
var raw string
|
||||
err := r.db.QueryRowContext(ctx, getRoomRegionWhitelistSQL, roomRegionWhitelistGroup, appCode).Scan(&raw)
|
||||
if errors.Is(err, sql.ErrNoRows) || isMissingTableError(err) {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
ids, err := parseRoomRegionWhitelist(raw)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
_, ok := ids[userID]
|
||||
return ok, nil
|
||||
}
|
||||
|
||||
func (r *MySQLReader) cachedRoomRegionWhitelist(ctx context.Context, appCode string, userID int64) (bool, bool, error) {
|
||||
if r == nil || r.cache == nil {
|
||||
return false, false, nil
|
||||
}
|
||||
value, err := r.cache.Get(ctx, r.roomRegionWhitelistCacheKey(appCode, userID)).Result()
|
||||
if errors.Is(err, redis.Nil) {
|
||||
return false, false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
return value == "1", true, nil
|
||||
}
|
||||
|
||||
func (r *MySQLReader) storeRoomRegionWhitelistCache(ctx context.Context, appCode string, userID int64, allowed bool) {
|
||||
if r == nil || r.cache == nil {
|
||||
return
|
||||
}
|
||||
value := "0"
|
||||
if allowed {
|
||||
value = "1"
|
||||
}
|
||||
// 缓存只优化读路径;写入失败时保持 DB 判定结果,不让 Redis 抖动阻断房间列表。
|
||||
_ = r.cache.Set(ctx, r.roomRegionWhitelistCacheKey(appCode, userID), value, r.cacheTTL).Err()
|
||||
}
|
||||
|
||||
func (r *MySQLReader) roomRegionWhitelistCacheKey(appCode string, userID int64) string {
|
||||
return strings.TrimRight(r.cachePrefix, ":") + ":room_region_whitelist:" + normalizeAppCode(appCode) + ":" + strconv.FormatInt(userID, 10)
|
||||
}
|
||||
|
||||
type roomRegionWhitelistPayload struct {
|
||||
UserIDs []string `json:"user_ids"`
|
||||
}
|
||||
|
||||
func parseRoomRegionWhitelist(raw string) (map[int64]struct{}, error) {
|
||||
raw = strings.TrimSpace(raw)
|
||||
if raw == "" {
|
||||
return map[int64]struct{}{}, nil
|
||||
}
|
||||
var payload roomRegionWhitelistPayload
|
||||
if strings.HasPrefix(raw, "[") {
|
||||
if err := json.Unmarshal([]byte(raw), &payload.UserIDs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if err := json.Unmarshal([]byte(raw), &payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := make(map[int64]struct{}, len(payload.UserIDs))
|
||||
for _, item := range payload.UserIDs {
|
||||
id, err := strconv.ParseInt(strings.TrimSpace(item), 10, 64)
|
||||
if err != nil || id <= 0 {
|
||||
continue
|
||||
}
|
||||
out[id] = struct{}{}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// StaticReader 给测试和临时环境提供内存版 H5 配置读取。
|
||||
type StaticReader struct {
|
||||
Links []H5Link
|
||||
@ -476,6 +617,7 @@ type StaticReader struct {
|
||||
Version Version
|
||||
Err error
|
||||
PositionAliases map[string]string
|
||||
RoomWhitelist map[string]bool
|
||||
}
|
||||
|
||||
// ListH5Links 返回预置 H5 配置。
|
||||
@ -556,6 +698,14 @@ func (r StaticReader) LatestVersion(_ context.Context, query VersionQuery) (Vers
|
||||
return item, nil
|
||||
}
|
||||
|
||||
// RoomRegionWhitelistAllows 返回内存白名单结果,测试可用 "app:user_id" 作为 key。
|
||||
func (r StaticReader) RoomRegionWhitelistAllows(_ context.Context, appCode string, userID int64) (bool, error) {
|
||||
if r.Err != nil {
|
||||
return false, r.Err
|
||||
}
|
||||
return r.RoomWhitelist[bdLeaderPositionAliasKey(appCode, userID)], nil
|
||||
}
|
||||
|
||||
func normalizeAppCode(value string) string {
|
||||
value = strings.ToLower(strings.TrimSpace(value))
|
||||
if value == "" {
|
||||
@ -606,13 +756,15 @@ func NormalizeBannerDisplayScope(value string) string {
|
||||
return "room"
|
||||
case "recharge", "充值页":
|
||||
return "recharge"
|
||||
case "me", "我的页", "我的":
|
||||
return "me"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func bannerDisplayScopeList(value string) []string {
|
||||
seen := make(map[string]struct{}, 3)
|
||||
seen := make(map[string]struct{}, 4)
|
||||
for _, part := range strings.Split(value, ",") {
|
||||
scope := NormalizeBannerDisplayScope(part)
|
||||
if scope != "" {
|
||||
@ -620,7 +772,7 @@ func bannerDisplayScopeList(value string) []string {
|
||||
}
|
||||
}
|
||||
out := make([]string, 0, len(seen))
|
||||
for _, scope := range []string{"home", "room", "recharge"} {
|
||||
for _, scope := range []string{"home", "room", "recharge", "me"} {
|
||||
if _, ok := seen[scope]; ok {
|
||||
out = append(out, scope)
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@ func TestNormalizeBannerDisplayScopeAcceptsChineseLabels(t *testing.T) {
|
||||
"首页": "home",
|
||||
"房间内": "room",
|
||||
"充值页": "recharge",
|
||||
"我的页": "me",
|
||||
"ME": "me",
|
||||
"ROOM": "room",
|
||||
"bad": "",
|
||||
}
|
||||
@ -19,8 +21,8 @@ func TestNormalizeBannerDisplayScopeAcceptsChineseLabels(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBannerDisplayScopeListParsesMultiScopeValue(t *testing.T) {
|
||||
got := bannerDisplayScopeList("room,home,recharge")
|
||||
want := []string{"home", "room", "recharge"}
|
||||
got := bannerDisplayScopeList("room,home,recharge,me")
|
||||
want := []string{"home", "room", "recharge", "me"}
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("scope count mismatch: got %+v want %+v", got, want)
|
||||
}
|
||||
@ -30,3 +32,25 @@ func TestBannerDisplayScopeListParsesMultiScopeValue(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseRoomRegionWhitelistSupportsObjectAndArrayPayloads(t *testing.T) {
|
||||
cases := []string{
|
||||
`{"user_ids":["325379237278126080","1001","1001","0","bad"]}`,
|
||||
`["325379237278126080","1001","1001","0","bad"]`,
|
||||
}
|
||||
for _, input := range cases {
|
||||
got, err := parseRoomRegionWhitelist(input)
|
||||
if err != nil {
|
||||
t.Fatalf("parse whitelist %s failed: %v", input, err)
|
||||
}
|
||||
if _, ok := got[325379237278126080]; !ok {
|
||||
t.Fatalf("long user id missing: %+v", got)
|
||||
}
|
||||
if _, ok := got[1001]; !ok {
|
||||
t.Fatalf("small user id missing: %+v", got)
|
||||
}
|
||||
if _, ok := got[0]; ok {
|
||||
t.Fatalf("zero user id must be ignored: %+v", got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,6 +115,16 @@ type LoginRiskFastGuardConfig struct {
|
||||
type AppConfigConfig struct {
|
||||
// MySQLDSN 指向后台管理库 hyapp_admin;gateway 只读 App 运行时配置表。
|
||||
MySQLDSN string `yaml:"mysql_dsn"`
|
||||
// RedisAddr 用于缓存低频后台配置判定,默认复用 auth_rate_limit Redis。
|
||||
RedisAddr string `yaml:"redis_addr"`
|
||||
// RedisPassword 是 Redis 鉴权密码,默认复用 auth_rate_limit Redis。
|
||||
RedisPassword string `yaml:"redis_password"`
|
||||
// RedisDB 是 Redis logical DB,默认复用 auth_rate_limit Redis。
|
||||
RedisDB int `yaml:"redis_db"`
|
||||
// KeyPrefix 隔离 App 配置缓存 key,避免和登录风控、频控共用命名空间。
|
||||
KeyPrefix string `yaml:"key_prefix"`
|
||||
// CacheTTL 控制后台配置读缓存时间;房间白名单默认五分钟。
|
||||
CacheTTL time.Duration `yaml:"cache_ttl"`
|
||||
}
|
||||
|
||||
// LeaderboardConfig 描述 App 活动榜单读取钱包送礼事实的只读数据源。
|
||||
@ -296,7 +306,10 @@ func Default() Config {
|
||||
RetryableStatusCodes: []string{"UNAVAILABLE"},
|
||||
},
|
||||
AppConfig: AppConfigConfig{
|
||||
MySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_admin?parseTime=true&charset=utf8mb4&loc=UTC",
|
||||
MySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_admin?parseTime=true&charset=utf8mb4&loc=UTC",
|
||||
RedisAddr: "127.0.0.1:13379",
|
||||
KeyPrefix: "gateway:app_config:",
|
||||
CacheTTL: 5 * time.Minute,
|
||||
},
|
||||
Leaderboard: LeaderboardConfig{
|
||||
WalletMySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=UTC",
|
||||
@ -424,6 +437,19 @@ func (cfg *Config) Normalize() error {
|
||||
RetryableStatusCodes: runtimeGRPC.RetryableStatusCodes,
|
||||
}
|
||||
cfg.AppConfig.MySQLDSN = strings.TrimSpace(cfg.AppConfig.MySQLDSN)
|
||||
cfg.AppConfig.RedisAddr = strings.TrimSpace(cfg.AppConfig.RedisAddr)
|
||||
cfg.AppConfig.KeyPrefix = strings.TrimSpace(cfg.AppConfig.KeyPrefix)
|
||||
if cfg.AppConfig.RedisAddr == "" {
|
||||
cfg.AppConfig.RedisAddr = strings.TrimSpace(cfg.AuthRateLimit.RedisAddr)
|
||||
cfg.AppConfig.RedisPassword = cfg.AuthRateLimit.RedisPassword
|
||||
cfg.AppConfig.RedisDB = cfg.AuthRateLimit.RedisDB
|
||||
}
|
||||
if cfg.AppConfig.KeyPrefix == "" {
|
||||
cfg.AppConfig.KeyPrefix = "gateway:app_config:"
|
||||
}
|
||||
if cfg.AppConfig.CacheTTL <= 0 {
|
||||
cfg.AppConfig.CacheTTL = 5 * time.Minute
|
||||
}
|
||||
cfg.Leaderboard.WalletMySQLDSN = strings.TrimSpace(cfg.Leaderboard.WalletMySQLDSN)
|
||||
cfg.LoginRisk.RedisAddr = strings.TrimSpace(cfg.LoginRisk.RedisAddr)
|
||||
cfg.LoginRisk.KeyPrefix = strings.TrimSpace(cfg.LoginRisk.KeyPrefix)
|
||||
|
||||
@ -17,6 +17,7 @@ type ConfigReader interface {
|
||||
ListSplashScreens(ctx context.Context, query appconfig.SplashScreenQuery) ([]appconfig.SplashScreen, error)
|
||||
ListPopups(ctx context.Context, query appconfig.PopupQuery) ([]appconfig.Popup, error)
|
||||
LatestVersion(ctx context.Context, query appconfig.VersionQuery) (appconfig.Version, error)
|
||||
RoomRegionWhitelistAllows(ctx context.Context, appCode string, userID int64) (bool, error)
|
||||
}
|
||||
|
||||
// ObjectUploader 是 gateway 上传接口依赖的对象存储最小能力。
|
||||
|
||||
@ -3699,8 +3699,8 @@ func TestListAppBannersReturnsAdminAppConfig(t *testing.T) {
|
||||
CoverURL: "https://cdn.example.com/banner.png",
|
||||
RoomSmallImageURL: "https://cdn.example.com/banner-small.png",
|
||||
BannerType: "h5",
|
||||
DisplayScope: "home,room",
|
||||
DisplayScopes: []string{"home", "room"},
|
||||
DisplayScope: "home,room,me",
|
||||
DisplayScopes: []string{"home", "room", "me"},
|
||||
Param: "https://h5.example.com/activity",
|
||||
Platform: "android",
|
||||
SortOrder: 10,
|
||||
@ -3714,7 +3714,7 @@ func TestListAppBannersReturnsAdminAppConfig(t *testing.T) {
|
||||
}}}
|
||||
handler.SetAppConfigReader(reader)
|
||||
router := handler.Routes(auth.NewVerifier("secret"))
|
||||
request := httptest.NewRequest(http.MethodGet, "/api/v1/app/banners?display_scope=room&platform=android&country=CN®ion_id=1", nil)
|
||||
request := httptest.NewRequest(http.MethodGet, "/api/v1/app/banners?display_scope=me&platform=android&country=CN®ion_id=1", nil)
|
||||
request.Header.Set("X-Request-ID", "req-app-banners")
|
||||
request.Header.Set("X-App-Package", "com.org.laluparty")
|
||||
recorder := httptest.NewRecorder()
|
||||
@ -3732,7 +3732,7 @@ func TestListAppBannersReturnsAdminAppConfig(t *testing.T) {
|
||||
if response.Code != httpkit.CodeOK || !ok {
|
||||
t.Fatalf("unexpected envelope: %+v", response)
|
||||
}
|
||||
if reader.bannerQuery.DisplayScope != "room" || reader.bannerQuery.Platform != "android" || reader.bannerQuery.RegionID != 1 || reader.bannerQuery.Country != "CN" {
|
||||
if reader.bannerQuery.DisplayScope != "me" || reader.bannerQuery.Platform != "android" || reader.bannerQuery.RegionID != 1 || reader.bannerQuery.Country != "CN" {
|
||||
t.Fatalf("banner query mismatch: %+v", reader.bannerQuery)
|
||||
}
|
||||
if data["total"].(float64) != 1 {
|
||||
@ -3746,11 +3746,11 @@ func TestListAppBannersReturnsAdminAppConfig(t *testing.T) {
|
||||
if !ok || first["cover_url"] != "https://cdn.example.com/banner.png" || first["type"] != "h5" || first["param"] != "https://h5.example.com/activity" {
|
||||
t.Fatalf("banner item mismatch: %+v", first)
|
||||
}
|
||||
if first["display_scope"] != "home,room" || first["room_small_image_url"] != "https://cdn.example.com/banner-small.png" {
|
||||
if first["display_scope"] != "home,room,me" || first["room_small_image_url"] != "https://cdn.example.com/banner-small.png" {
|
||||
t.Fatalf("banner display fields mismatch: %+v", first)
|
||||
}
|
||||
displayScopes, ok := first["display_scopes"].([]any)
|
||||
if !ok || len(displayScopes) != 2 || displayScopes[0] != "home" || displayScopes[1] != "room" {
|
||||
if !ok || len(displayScopes) != 3 || displayScopes[0] != "home" || displayScopes[1] != "room" || displayScopes[2] != "me" {
|
||||
t.Fatalf("banner display scopes mismatch: %+v", first)
|
||||
}
|
||||
if first["platform"] != "android" || first["sort_order"].(float64) != 10 || first["starts_at_ms"].(float64) != 1700000000000 || first["ends_at_ms"].(float64) != 1800000000000 || first["updated_at_ms"].(float64) != 1700000002000 {
|
||||
|
||||
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"hyapp/pkg/tencentrtc"
|
||||
"hyapp/services/gateway-service/internal/client"
|
||||
"hyapp/services/gateway-service/internal/transport/http/appapi"
|
||||
"hyapp/services/gateway-service/internal/transport/http/httproutes"
|
||||
)
|
||||
|
||||
@ -19,6 +20,7 @@ type Handler struct {
|
||||
userRegionClient client.UserRegionClient
|
||||
userSocialClient client.UserSocialClient
|
||||
userHostClient client.UserHostClient
|
||||
appConfigReader appapi.ConfigReader
|
||||
walletClient client.WalletClient
|
||||
growthLevelClient client.GrowthLevelClient
|
||||
achievementClient client.AchievementClient
|
||||
@ -34,6 +36,7 @@ type Config struct {
|
||||
UserRegionClient client.UserRegionClient
|
||||
UserSocialClient client.UserSocialClient
|
||||
UserHostClient client.UserHostClient
|
||||
AppConfigReader appapi.ConfigReader
|
||||
WalletClient client.WalletClient
|
||||
GrowthLevelClient client.GrowthLevelClient
|
||||
AchievementClient client.AchievementClient
|
||||
@ -50,6 +53,7 @@ func New(config Config) *Handler {
|
||||
userRegionClient: config.UserRegionClient,
|
||||
userSocialClient: config.UserSocialClient,
|
||||
userHostClient: config.UserHostClient,
|
||||
appConfigReader: config.AppConfigReader,
|
||||
walletClient: config.WalletClient,
|
||||
growthLevelClient: config.GrowthLevelClient,
|
||||
achievementClient: config.AchievementClient,
|
||||
|
||||
@ -106,12 +106,14 @@ func (h *Handler) listRooms(writer http.ResponseWriter, request *http.Request) {
|
||||
httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument")
|
||||
return
|
||||
}
|
||||
allVisibleRegions := h.roomRegionWhitelistAllows(request, viewerUserID)
|
||||
|
||||
resp, err := h.roomQueryClient.ListRooms(request.Context(), &roomv1.ListRoomsRequest{
|
||||
Meta: httpkit.RoomMeta(request, "", ""),
|
||||
ViewerUserId: viewerUserID,
|
||||
VisibleRegionId: userResp.GetUser().GetRegionId(),
|
||||
ViewerCountryCode: userResp.GetUser().GetCountry(),
|
||||
AllVisibleRegions: allVisibleRegions,
|
||||
Tab: tab,
|
||||
Cursor: request.URL.Query().Get("cursor"),
|
||||
Limit: limit,
|
||||
@ -183,6 +185,18 @@ func (h *Handler) listRoomFeeds(writer http.ResponseWriter, request *http.Reques
|
||||
httpkit.WriteOK(writer, request, roomListDataFromProto(resp))
|
||||
}
|
||||
|
||||
func (h *Handler) roomRegionWhitelistAllows(request *http.Request, viewerUserID int64) bool {
|
||||
if h.appConfigReader == nil || viewerUserID <= 0 {
|
||||
return false
|
||||
}
|
||||
allowed, err := h.appConfigReader.RoomRegionWhitelistAllows(request.Context(), appcode.FromContext(request.Context()), viewerUserID)
|
||||
if err != nil {
|
||||
// 白名单读取失败时必须 fail-closed,避免后台配置或缓存异常放大成跨区域房间泄露。
|
||||
return false
|
||||
}
|
||||
return allowed
|
||||
}
|
||||
|
||||
func (h *Handler) roomFeedRelatedUsers(request *http.Request, tab string, query string, rawCursor string) ([]*roomv1.RoomFeedRelatedUser, bool, error) {
|
||||
if tab == "visited" || tab == "followed" {
|
||||
return nil, true, nil
|
||||
|
||||
@ -31,6 +31,7 @@ func (h *Handler) Routes(jwtVerifier *auth.Verifier) http.Handler {
|
||||
UserRegionClient: h.userRegionClient,
|
||||
UserSocialClient: h.userSocialClient,
|
||||
UserHostClient: h.userHostClient,
|
||||
AppConfigReader: h.appConfigReader,
|
||||
WalletClient: h.walletClient,
|
||||
GrowthLevelClient: h.growthLevelClient,
|
||||
AchievementClient: h.achievementClient,
|
||||
|
||||
@ -10,9 +10,9 @@ mysql_auto_migrate: false
|
||||
|
||||
tencent_im:
|
||||
enabled: true
|
||||
sdk_app_id: 20036101
|
||||
secret_key: "dcdf53135f27e7cf8541c4ae9798fb0cb2f0e4d6c5c20022dbaea053f35cbb8c"
|
||||
admin_identifier: "900100100"
|
||||
sdk_app_id: 20040101
|
||||
secret_key: "2f6a5ec58cccf79647557a96c15e6efe89ba5a44c474096bde2589a633fcd45e"
|
||||
admin_identifier: "administrator"
|
||||
admin_user_sig_ttl: 24h
|
||||
endpoint: "adminapisgp.im.qcloud.com"
|
||||
request_timeout: 5s
|
||||
|
||||
@ -10,9 +10,9 @@ mysql_auto_migrate: false
|
||||
|
||||
tencent_im:
|
||||
enabled: true
|
||||
sdk_app_id: 20036101
|
||||
secret_key: "dcdf53135f27e7cf8541c4ae9798fb0cb2f0e4d6c5c20022dbaea053f35cbb8c"
|
||||
admin_identifier: "900100100"
|
||||
sdk_app_id: 20040101
|
||||
secret_key: "2f6a5ec58cccf79647557a96c15e6efe89ba5a44c474096bde2589a633fcd45e"
|
||||
admin_identifier: "administrator"
|
||||
admin_user_sig_ttl: 24h
|
||||
endpoint: "adminapisgp.im.qcloud.com"
|
||||
request_timeout: 5s
|
||||
|
||||
@ -20,6 +20,7 @@ const (
|
||||
channelTencentIMC2C = "tencent_im_c2c"
|
||||
eventWalletBalance = "WalletBalanceChanged"
|
||||
eventVIPActivated = "VipActivated"
|
||||
robotCoinAssetType = "ROBOT_COIN"
|
||||
deliveryStatusDelivering = "delivering"
|
||||
deliveryStatusDelivered = "delivered"
|
||||
deliveryStatusRetryable = "retryable"
|
||||
@ -122,10 +123,11 @@ func (r *MySQLRepository) listWalletBalanceCandidates(ctx context.Context, limit
|
||||
LEFT JOIN notice_delivery_events nde
|
||||
ON nde.source_name = ? AND nde.app_code = wo.app_code AND nde.source_event_id = wo.event_id AND nde.channel = ?
|
||||
WHERE wo.app_code = ? AND wo.event_type IN (%s)
|
||||
AND wo.asset_type <> ?
|
||||
AND nde.source_event_id IS NULL
|
||||
ORDER BY wo.created_at_ms ASC, wo.event_id ASC
|
||||
LIMIT ?`, r.walletOutboxTable, sqlPlaceholders(len(eventTypes))),
|
||||
args: append([]any{sourceWalletOutbox, channelTencentIMC2C, appCode}, stringSliceToAny(eventTypes)...),
|
||||
args: append(append([]any{sourceWalletOutbox, channelTencentIMC2C, appCode}, stringSliceToAny(eventTypes)...), robotCoinAssetType),
|
||||
},
|
||||
{
|
||||
query: fmt.Sprintf(`
|
||||
@ -134,10 +136,11 @@ func (r *MySQLRepository) listWalletBalanceCandidates(ctx context.Context, limit
|
||||
JOIN notice_delivery_events nde
|
||||
ON nde.source_name = ? AND nde.app_code = wo.app_code AND nde.source_event_id = wo.event_id AND nde.channel = ?
|
||||
WHERE wo.app_code = ? AND wo.event_type IN (%s)
|
||||
AND wo.asset_type <> ?
|
||||
AND nde.status = ? AND nde.next_retry_at_ms <= ?
|
||||
ORDER BY wo.created_at_ms ASC, wo.event_id ASC
|
||||
LIMIT ?`, r.walletOutboxTable, sqlPlaceholders(len(eventTypes))),
|
||||
args: append(append([]any{sourceWalletOutbox, channelTencentIMC2C, appCode}, stringSliceToAny(eventTypes)...), deliveryStatusRetryable, nowMs),
|
||||
args: append(append(append([]any{sourceWalletOutbox, channelTencentIMC2C, appCode}, stringSliceToAny(eventTypes)...), robotCoinAssetType), deliveryStatusRetryable, nowMs),
|
||||
},
|
||||
{
|
||||
query: fmt.Sprintf(`
|
||||
@ -146,10 +149,11 @@ func (r *MySQLRepository) listWalletBalanceCandidates(ctx context.Context, limit
|
||||
JOIN notice_delivery_events nde
|
||||
ON nde.source_name = ? AND nde.app_code = wo.app_code AND nde.source_event_id = wo.event_id AND nde.channel = ?
|
||||
WHERE wo.app_code = ? AND wo.event_type IN (%s)
|
||||
AND wo.asset_type <> ?
|
||||
AND nde.status = ? AND nde.lock_until_ms <= ?
|
||||
ORDER BY wo.created_at_ms ASC, wo.event_id ASC
|
||||
LIMIT ?`, r.walletOutboxTable, sqlPlaceholders(len(eventTypes))),
|
||||
args: append(append([]any{sourceWalletOutbox, channelTencentIMC2C, appCode}, stringSliceToAny(eventTypes)...), deliveryStatusDelivering, nowMs),
|
||||
args: append(append(append([]any{sourceWalletOutbox, channelTencentIMC2C, appCode}, stringSliceToAny(eventTypes)...), robotCoinAssetType), deliveryStatusDelivering, nowMs),
|
||||
},
|
||||
}
|
||||
for _, branch := range branches {
|
||||
|
||||
@ -73,6 +73,10 @@ func (s *Service) ProcessWalletOutboxMessage(ctx context.Context, message wallet
|
||||
if !isWalletPrivateNoticeEvent(message.EventType) {
|
||||
return false, nil
|
||||
}
|
||||
if isRobotCoinWalletNotice(message.AssetType) {
|
||||
// ROBOT_COIN 只服务机器人房间展示扣费,机器人账号不需要也不能接收用户 C2C 余额通知。
|
||||
return true, nil
|
||||
}
|
||||
options = normalizeWalletNoticeWorkerOptions(options, s.cfg.NodeID)
|
||||
if s.repository == nil {
|
||||
return true, fmt.Errorf("notice repository is not configured")
|
||||
@ -162,6 +166,10 @@ func isWalletPrivateNoticeEvent(eventType string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func isRobotCoinWalletNotice(assetType string) bool {
|
||||
return assetType == robotCoinAssetType
|
||||
}
|
||||
|
||||
func walletBalanceNoticePayload(event WalletBalanceEvent) (json.RawMessage, error) {
|
||||
var payload map[string]any
|
||||
if err := json.Unmarshal([]byte(event.PayloadJSON), &payload); err != nil {
|
||||
|
||||
@ -115,6 +115,31 @@ func TestProcessWalletOutboxMessagePublishesPrivateIM(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessWalletOutboxMessageSkipsRobotCoinPrivateIM(t *testing.T) {
|
||||
repo := &fakeRepository{}
|
||||
publisher := &fakePublisher{}
|
||||
service := New(Config{NodeID: "node-a"}, repo, publisher)
|
||||
|
||||
handled, err := service.ProcessWalletOutboxMessage(context.Background(), walletmq.WalletOutboxMessage{
|
||||
AppCode: "lalu",
|
||||
EventID: "robot-wallet-1",
|
||||
EventType: "WalletBalanceChanged",
|
||||
TransactionID: "robot-tx-1",
|
||||
CommandID: "robot-cmd-1",
|
||||
UserID: 100001,
|
||||
AssetType: robotCoinAssetType,
|
||||
AvailableDelta: -1,
|
||||
PayloadJSON: `{"available_after":999}`,
|
||||
OccurredAtMS: 1710000000000,
|
||||
}, WalletNoticeWorkerOptions{MaxRetryCount: 3})
|
||||
if err != nil {
|
||||
t.Fatalf("ProcessWalletOutboxMessage failed: %v", err)
|
||||
}
|
||||
if !handled || len(repo.claimedMessages) != 0 || len(repo.delivered) != 0 || len(publisher.messages) != 0 {
|
||||
t.Fatalf("robot coin notice must be acked without c2c delivery: handled=%v claimed=%d delivered=%d messages=%d", handled, len(repo.claimedMessages), len(repo.delivered), len(publisher.messages))
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessWalletBalanceNoticesMarksRetryable(t *testing.T) {
|
||||
repo := &fakeRepository{
|
||||
events: []WalletBalanceEvent{{
|
||||
|
||||
@ -19,12 +19,14 @@ rank_limit: 20
|
||||
snapshot_every_n: 10
|
||||
wallet_service_addr: "wallet-service:13004"
|
||||
activity_service_addr: "activity-service:13006"
|
||||
robot_service_addr: "robot-service:13011"
|
||||
user_service_addr: "user-service:13005"
|
||||
tencent_im:
|
||||
# Docker 本地联调腾讯云 IM REST 桥接;必须与 gateway-service 使用同一组应用配置。
|
||||
enabled: true
|
||||
sdk_app_id: 20036101
|
||||
secret_key: "dcdf53135f27e7cf8541c4ae9798fb0cb2f0e4d6c5c20022dbaea053f35cbb8c"
|
||||
admin_identifier: "900100100"
|
||||
sdk_app_id: 20040101
|
||||
secret_key: "2f6a5ec58cccf79647557a96c15e6efe89ba5a44c474096bde2589a633fcd45e"
|
||||
admin_identifier: "administrator"
|
||||
admin_user_sig_ttl: "24h"
|
||||
endpoint: "adminapisgp.im.qcloud.com"
|
||||
group_type: "ChatRoom"
|
||||
@ -67,6 +69,13 @@ rocketmq:
|
||||
tencent_im_consumer_enabled: true
|
||||
tencent_im_consumer_group: "hyapp-room-im-bridge"
|
||||
consumer_max_reconsume_times: 16
|
||||
robot_room_outbox:
|
||||
enabled: true
|
||||
topic: "hyapp_robot_room_outbox"
|
||||
producer_group: "hyapp-room-robot-outbox-producer"
|
||||
tencent_im_consumer_enabled: true
|
||||
tencent_im_consumer_group: "hyapp-test-room-robot-im-bridge"
|
||||
consumer_max_reconsume_times: 16
|
||||
rocket_launch:
|
||||
enabled: true
|
||||
topic: "hyapp_room_rocket_launch"
|
||||
@ -89,3 +98,14 @@ outbox_worker:
|
||||
max_retry_count: 10
|
||||
initial_backoff: "5s"
|
||||
max_backoff: "5m"
|
||||
robot_outbox_worker:
|
||||
# Docker 本地单独投递机器人展示事件,避免压住主 room_outbox fanout。
|
||||
enabled: true
|
||||
publish_mode: "mq"
|
||||
poll_interval: "1s"
|
||||
batch_size: 30
|
||||
publish_timeout: "3s"
|
||||
retry_strategy: "exponential_backoff"
|
||||
max_retry_count: 10
|
||||
initial_backoff: "5s"
|
||||
max_backoff: "5m"
|
||||
|
||||
@ -18,6 +18,8 @@ rank_limit: 20
|
||||
snapshot_every_n: 10
|
||||
wallet_service_addr: "wallet-service.internal:13004"
|
||||
activity_service_addr: "activity-service.internal:13006"
|
||||
robot_service_addr: "robot-service.internal:13011"
|
||||
user_service_addr: "user-service.internal:13005"
|
||||
tencent_im:
|
||||
# 线上开启后,腾讯云 IM 建群和房间系统消息都由 room_outbox worker 异步投递。
|
||||
enabled: true
|
||||
@ -77,6 +79,13 @@ rocketmq:
|
||||
tencent_im_consumer_enabled: true
|
||||
tencent_im_consumer_group: "hyapp-room-im-bridge"
|
||||
consumer_max_reconsume_times: 16
|
||||
robot_room_outbox:
|
||||
enabled: true
|
||||
topic: "hyapp_robot_room_outbox"
|
||||
producer_group: "hyapp-room-robot-outbox-producer"
|
||||
tencent_im_consumer_enabled: true
|
||||
tencent_im_consumer_group: "hyapp-room-robot-im-bridge"
|
||||
consumer_max_reconsume_times: 16
|
||||
rocket_launch:
|
||||
enabled: true
|
||||
topic: "hyapp_room_rocket_launch"
|
||||
@ -99,3 +108,14 @@ outbox_worker:
|
||||
max_retry_count: 10
|
||||
initial_backoff: "5s"
|
||||
max_backoff: "5m"
|
||||
robot_outbox_worker:
|
||||
# 机器人房间展示事件独立投递,只服务 IM 展示,不投 activity/statistics 主业务消费者。
|
||||
enabled: true
|
||||
publish_mode: "mq"
|
||||
poll_interval: "1s"
|
||||
batch_size: 30
|
||||
publish_timeout: "3s"
|
||||
retry_strategy: "exponential_backoff"
|
||||
max_retry_count: 10
|
||||
initial_backoff: "5s"
|
||||
max_backoff: "5m"
|
||||
|
||||
@ -19,12 +19,14 @@ node_registry_heartbeat_interval: "10s"
|
||||
owner_forward_timeout: "2s"
|
||||
wallet_service_addr: "127.0.0.1:13004"
|
||||
activity_service_addr: "127.0.0.1:13006"
|
||||
robot_service_addr: "127.0.0.1:13011"
|
||||
user_service_addr: "127.0.0.1:13005"
|
||||
tencent_im:
|
||||
# 本地联调腾讯云 IM REST 桥接;SDKAppID、密钥和管理员账号必须来自同一个应用。
|
||||
enabled: true
|
||||
sdk_app_id: 20036101
|
||||
secret_key: "dcdf53135f27e7cf8541c4ae9798fb0cb2f0e4d6c5c20022dbaea053f35cbb8c"
|
||||
admin_identifier: "900100100"
|
||||
sdk_app_id: 20040101
|
||||
secret_key: "2f6a5ec58cccf79647557a96c15e6efe89ba5a44c474096bde2589a633fcd45e"
|
||||
admin_identifier: "administrator"
|
||||
admin_user_sig_ttl: "24h"
|
||||
# REST API 区域域名必须匹配腾讯云 IM 应用的数据存储区域。
|
||||
endpoint: "adminapisgp.im.qcloud.com"
|
||||
@ -70,6 +72,13 @@ rocketmq:
|
||||
tencent_im_consumer_enabled: true
|
||||
tencent_im_consumer_group: "hyapp-room-im-bridge"
|
||||
consumer_max_reconsume_times: 16
|
||||
robot_room_outbox:
|
||||
enabled: true
|
||||
topic: "hyapp_robot_room_outbox"
|
||||
producer_group: "hyapp-room-robot-outbox-producer"
|
||||
tencent_im_consumer_enabled: true
|
||||
tencent_im_consumer_group: "hyapp-test-room-robot-im-bridge"
|
||||
consumer_max_reconsume_times: 16
|
||||
rocket_launch:
|
||||
enabled: true
|
||||
topic: "hyapp_room_rocket_launch"
|
||||
@ -92,3 +101,14 @@ outbox_worker:
|
||||
max_retry_count: 10
|
||||
initial_backoff: "5s"
|
||||
max_backoff: "5m"
|
||||
robot_outbox_worker:
|
||||
# 机器人展示事件走独立 outbox/topic,只投房间 IM,不占用真人 room_outbox 主流程。
|
||||
enabled: true
|
||||
publish_mode: "mq"
|
||||
poll_interval: "1s"
|
||||
batch_size: 30
|
||||
publish_timeout: "3s"
|
||||
retry_strategy: "exponential_backoff"
|
||||
max_retry_count: 10
|
||||
initial_backoff: "5s"
|
||||
max_backoff: "5m"
|
||||
|
||||
@ -156,6 +156,27 @@ CREATE TABLE IF NOT EXISTS room_outbox (
|
||||
KEY idx_room_outbox_retention (app_code, status, updated_at_ms, event_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间事件 outbox 表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS room_robot_outbox (
|
||||
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
|
||||
event_id VARCHAR(128) NOT NULL COMMENT '事件幂等 ID',
|
||||
event_type VARCHAR(64) NOT NULL COMMENT '事件类型',
|
||||
room_id VARCHAR(64) NOT NULL COMMENT '机器人房间 ID',
|
||||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||||
worker_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'worker ID',
|
||||
lock_until_ms BIGINT NULL COMMENT '锁定过期时间,UTC epoch ms',
|
||||
envelope LONGBLOB NOT NULL COMMENT '事件信封',
|
||||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||||
retry_count INT NOT NULL DEFAULT 0 COMMENT '重试次数',
|
||||
next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '下一次重试时间,UTC epoch ms',
|
||||
last_error TEXT NULL COMMENT '最后一次失败原因',
|
||||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||||
PRIMARY KEY (app_code, event_id),
|
||||
KEY idx_room_robot_outbox_pending (app_code, status, next_retry_at_ms, created_at_ms, event_id),
|
||||
KEY idx_room_robot_outbox_claim (app_code, status, lock_until_ms, created_at_ms, event_id),
|
||||
KEY idx_room_robot_outbox_event_created (app_code, event_type, created_at_ms, event_id),
|
||||
KEY idx_room_robot_outbox_retention (app_code, status, updated_at_ms, event_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='机器人房间展示事件 outbox 表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS room_user_feed_entries (
|
||||
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
|
||||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||||
@ -238,6 +259,8 @@ CREATE TABLE IF NOT EXISTS room_robot_rooms (
|
||||
status VARCHAR(32) NOT NULL COMMENT '运行状态:active/stopped',
|
||||
owner_robot_user_id BIGINT NOT NULL COMMENT '房主机器人用户 ID',
|
||||
robot_user_ids_json JSON NOT NULL COMMENT '本房间占用的机器人用户 ID 集合',
|
||||
active_robot_count INT NOT NULL DEFAULT 0 COMMENT '房间内同时保持的活跃机器人数量,0 表示兼容旧配置全量在线',
|
||||
seat_count INT NOT NULL DEFAULT 10 COMMENT '机器人房间麦位数:10/15/20',
|
||||
gift_ids_json JSON NOT NULL COMMENT '普通礼物 ID 集合',
|
||||
lucky_gift_ids_json JSON NOT NULL COMMENT '幸运礼物 ID 集合',
|
||||
normal_gift_interval_ms BIGINT NOT NULL COMMENT '普通礼物间隔毫秒',
|
||||
@ -245,6 +268,11 @@ CREATE TABLE IF NOT EXISTS room_robot_rooms (
|
||||
lucky_combo_max BIGINT NOT NULL COMMENT '幸运礼物最大连击次数',
|
||||
lucky_pause_min_ms BIGINT NOT NULL COMMENT '幸运礼物连击后最小暂停毫秒',
|
||||
lucky_pause_max_ms BIGINT NOT NULL COMMENT '幸运礼物连击后最大暂停毫秒',
|
||||
robot_stay_min_ms BIGINT NOT NULL DEFAULT 180000 COMMENT '机器人单次最短停留毫秒',
|
||||
robot_stay_max_ms BIGINT NOT NULL DEFAULT 600000 COMMENT '机器人单次最长停留毫秒',
|
||||
robot_replace_min_ms BIGINT NOT NULL DEFAULT 0 COMMENT '机器人离开后最短补位延迟毫秒',
|
||||
robot_replace_max_ms BIGINT NOT NULL DEFAULT 60000 COMMENT '机器人离开后最长补位延迟毫秒',
|
||||
max_gift_senders BIGINT NOT NULL DEFAULT 1 COMMENT '同一时间最多允许送礼的机器人数量',
|
||||
created_by_admin_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建管理员 ID',
|
||||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||||
@ -253,6 +281,36 @@ CREATE TABLE IF NOT EXISTS room_robot_rooms (
|
||||
KEY idx_room_robot_rooms_owner (app_code, owner_robot_user_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='机器人房间后台配置表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS room_human_robot_configs (
|
||||
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
|
||||
enabled BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否启用真人房间机器人行为',
|
||||
candidate_room_max_online INT NOT NULL DEFAULT 5 COMMENT '低于该在线人数的同国家真人房可进入机器人',
|
||||
room_full_stop_online INT NOT NULL DEFAULT 10 COMMENT '房间达到该在线人数后停止补机器人',
|
||||
room_target_min_online INT NOT NULL DEFAULT 8 COMMENT '房间随机目标总人数下限',
|
||||
room_target_max_online INT NOT NULL DEFAULT 10 COMMENT '房间随机目标总人数上限',
|
||||
robot_stay_min_ms BIGINT NOT NULL DEFAULT 60000 COMMENT '机器人单次最短停留毫秒',
|
||||
robot_stay_max_ms BIGINT NOT NULL DEFAULT 600000 COMMENT '机器人单次最长停留毫秒',
|
||||
robot_replace_min_ms BIGINT NOT NULL DEFAULT 60000 COMMENT '机器人离开后最短补位延迟毫秒',
|
||||
robot_replace_max_ms BIGINT NOT NULL DEFAULT 180000 COMMENT '机器人离开后最长补位延迟毫秒',
|
||||
normal_gift_interval_ms BIGINT NOT NULL DEFAULT 10000 COMMENT '普通礼物间隔毫秒',
|
||||
normal_gift_interval_min_ms BIGINT NOT NULL DEFAULT 1000 COMMENT '普通礼物最短随机间隔毫秒',
|
||||
normal_gift_interval_max_ms BIGINT NOT NULL DEFAULT 20000 COMMENT '普通礼物最长随机间隔毫秒',
|
||||
gift_ids_json JSON NOT NULL COMMENT '普通礼物 ID 集合',
|
||||
lucky_gift_ids_json JSON NOT NULL COMMENT '幸运礼物 ID 集合',
|
||||
super_lucky_gift_ids_json JSON NOT NULL COMMENT '超级幸运礼物 ID 集合',
|
||||
lucky_combo_min BIGINT NOT NULL DEFAULT 1 COMMENT '幸运礼物最小连击次数',
|
||||
lucky_combo_max BIGINT NOT NULL DEFAULT 3 COMMENT '幸运礼物最大连击次数',
|
||||
lucky_pause_min_ms BIGINT NOT NULL DEFAULT 5000 COMMENT '幸运礼物连击后最小暂停毫秒',
|
||||
lucky_pause_max_ms BIGINT NOT NULL DEFAULT 20000 COMMENT '幸运礼物连击后最大暂停毫秒',
|
||||
max_gift_senders BIGINT NOT NULL DEFAULT 1 COMMENT '同一时间最多送礼机器人数量',
|
||||
country_pools_json JSON NOT NULL COMMENT '国家机器人池配置',
|
||||
updated_by_admin_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '最后更新管理员 ID',
|
||||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||||
PRIMARY KEY (app_code),
|
||||
KEY idx_room_human_robot_enabled (app_code, enabled)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='真人房间机器人行为配置表';
|
||||
|
||||
INSERT IGNORE INTO room_seat_configs (
|
||||
app_code,
|
||||
allowed_seat_counts,
|
||||
|
||||
@ -47,6 +47,10 @@ type App struct {
|
||||
walletConn *grpc.ClientConn
|
||||
// activityConn 是 room outbox 事实投递到 activity-service 的 best-effort 通道。
|
||||
activityConn *grpc.ClientConn
|
||||
// robotConn 是真人房间机器人运行时读取全站机器人池的依赖。
|
||||
robotConn *grpc.ClientConn
|
||||
// userConn 是真人房间机器人运行时读取机器人国家资料的依赖。
|
||||
userConn *grpc.ClientConn
|
||||
// repository 是 MySQL 持久化实现,保存 meta、command log、snapshot 和 outbox。
|
||||
repository *mysqlstorage.Repository
|
||||
// redisClose 关闭 Redis client,Redis directory 本身不拥有额外生命周期。
|
||||
@ -92,6 +96,26 @@ func New(cfg config.Config) (*App, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
robotConn, err := grpc.Dial(cfg.RobotServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
closeClientConn(activityConn)
|
||||
_ = walletConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
userConn, err := grpc.Dial(cfg.UserServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
closeClientConn(robotConn)
|
||||
closeClientConn(activityConn)
|
||||
_ = walletConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
closeRobotDepsOnError := true
|
||||
defer func() {
|
||||
if closeRobotDepsOnError {
|
||||
closeClientConn(userConn)
|
||||
closeClientConn(robotConn)
|
||||
}
|
||||
}()
|
||||
|
||||
startupCtx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
@ -153,9 +177,10 @@ func New(cfg config.Config) (*App, error) {
|
||||
rtcUserRemover = rtcClient
|
||||
}
|
||||
|
||||
mqProducers := make([]*rocketmqx.Producer, 0, 2)
|
||||
mqConsumers := make([]*rocketmqx.Consumer, 0, 3)
|
||||
mqProducers := make([]*rocketmqx.Producer, 0, 3)
|
||||
mqConsumers := make([]*rocketmqx.Consumer, 0, 4)
|
||||
var rocketLaunchScheduler integration.RoomRocketLaunchScheduler
|
||||
robotOutboxPublishers := make([]integration.OutboxPublisher, 0, 1)
|
||||
if cfg.OutboxWorker.PublishMode == config.OutboxPublishModeDirect || cfg.OutboxWorker.PublishMode == config.OutboxPublishModeDual {
|
||||
if activityConn != nil {
|
||||
activityPublisher := integration.NewActivityOutboxPublisher(activityv1.NewRoomEventConsumerServiceClient(activityConn), time.Second)
|
||||
@ -165,6 +190,12 @@ func New(cfg config.Config) (*App, error) {
|
||||
outboxPublishers = append(outboxPublishers, tencentPublisher)
|
||||
}
|
||||
}
|
||||
if cfg.RobotOutboxWorker.PublishMode == config.OutboxPublishModeDirect || cfg.RobotOutboxWorker.PublishMode == config.OutboxPublishModeDual {
|
||||
if tencentPublisher != nil {
|
||||
// 机器人展示事件只需要 IM 房间消息;不投 activity/statistics,避免污染真人房间主业务链路。
|
||||
robotOutboxPublishers = append(robotOutboxPublishers, tencentPublisher)
|
||||
}
|
||||
}
|
||||
if cfg.OutboxWorker.PublishMode == config.OutboxPublishModeMQ || cfg.OutboxWorker.PublishMode == config.OutboxPublishModeDual {
|
||||
outboxProducer, err := rocketmqx.NewProducer(rocketMQProducerConfig(cfg.RocketMQ, cfg.RocketMQ.RoomOutbox.ProducerGroup))
|
||||
if err != nil {
|
||||
@ -177,6 +208,18 @@ func New(cfg config.Config) (*App, error) {
|
||||
mqProducers = append(mqProducers, outboxProducer)
|
||||
outboxPublishers = append(outboxPublishers, integration.NewRocketMQOutboxPublisher(outboxProducer, cfg.RocketMQ.RoomOutbox.Topic))
|
||||
}
|
||||
if cfg.RobotOutboxWorker.PublishMode == config.OutboxPublishModeMQ || cfg.RobotOutboxWorker.PublishMode == config.OutboxPublishModeDual {
|
||||
robotOutboxProducer, err := rocketmqx.NewProducer(rocketMQProducerConfig(cfg.RocketMQ, cfg.RocketMQ.RobotRoomOutbox.ProducerGroup))
|
||||
if err != nil {
|
||||
_ = repository.Close()
|
||||
closeClientConn(activityConn)
|
||||
_ = walletConn.Close()
|
||||
_ = redisClient.Close()
|
||||
return nil, err
|
||||
}
|
||||
mqProducers = append(mqProducers, robotOutboxProducer)
|
||||
robotOutboxPublishers = append(robotOutboxPublishers, integration.NewRocketMQOutboxPublisher(robotOutboxProducer, cfg.RocketMQ.RobotRoomOutbox.Topic))
|
||||
}
|
||||
if cfg.RocketMQ.RocketLaunch.Enabled {
|
||||
rocketProducer, err := rocketmqx.NewProducer(rocketMQProducerConfig(cfg.RocketMQ, cfg.RocketMQ.RocketLaunch.ProducerGroup))
|
||||
if err != nil {
|
||||
@ -190,6 +233,7 @@ func New(cfg config.Config) (*App, error) {
|
||||
rocketLaunchScheduler = integration.NewRocketMQRocketLaunchScheduler(rocketProducer, cfg.RocketMQ.RocketLaunch.Topic)
|
||||
}
|
||||
outboxPublisher := integration.NewCompositeOutboxPublisher(outboxPublishers...)
|
||||
robotOutboxPublisher := integration.NewCompositeOutboxPublisher(robotOutboxPublishers...)
|
||||
var luckyGiftClient integration.LuckyGiftClient
|
||||
if activityConn != nil {
|
||||
luckyGiftClient = integration.NewGRPCLuckyGiftClient(activityConn)
|
||||
@ -205,6 +249,8 @@ func New(cfg config.Config) (*App, error) {
|
||||
MicPublishTimeout: cfg.MicPublishTimeout,
|
||||
RTCUserRemover: rtcUserRemover,
|
||||
RoomRocketLaunchScheduler: rocketLaunchScheduler,
|
||||
RobotOutboxPublisher: robotOutboxPublisher,
|
||||
HumanRobotPoolProvider: integration.NewGRPCHumanRoomRobotPoolProvider(robotConn, userConn),
|
||||
RoomGiftLeaderboard: roomservice.NewRedisRoomGiftLeaderboardStore(redisClient),
|
||||
LuckyGiftSendLocker: roomservice.NewRedisLuckyGiftSendLocker(redisClient),
|
||||
LuckyGiftSendLockTTL: cfg.LuckyGiftSendLockTTL,
|
||||
@ -264,6 +310,37 @@ func New(cfg config.Config) (*App, error) {
|
||||
}
|
||||
mqConsumers = append(mqConsumers, imConsumer)
|
||||
}
|
||||
if cfg.RocketMQ.RobotRoomOutbox.TencentIMConsumerEnabled && tencentPublisher == nil {
|
||||
_ = repository.Close()
|
||||
closeClientConn(activityConn)
|
||||
_ = walletConn.Close()
|
||||
_ = redisClient.Close()
|
||||
return nil, errors.New("rocketmq robot_room_outbox tencent_im consumer requires tencent_im.enabled")
|
||||
}
|
||||
if cfg.RocketMQ.RobotRoomOutbox.TencentIMConsumerEnabled && tencentPublisher != nil {
|
||||
robotIMConsumer, err := rocketmqx.NewConsumer(rocketMQConsumerConfig(cfg.RocketMQ, cfg.RocketMQ.RobotRoomOutbox.TencentIMConsumerGroup, cfg.RocketMQ.RobotRoomOutbox.ConsumerMaxReconsumeTimes))
|
||||
if err != nil {
|
||||
_ = repository.Close()
|
||||
closeClientConn(activityConn)
|
||||
_ = walletConn.Close()
|
||||
_ = redisClient.Close()
|
||||
return nil, err
|
||||
}
|
||||
if err := robotIMConsumer.Subscribe(cfg.RocketMQ.RobotRoomOutbox.Topic, roommq.TagRoomOutboxEvent, func(ctx context.Context, message rocketmqx.ConsumedMessage) error {
|
||||
envelope, _, err := roommq.DecodeRoomOutboxMessage(message.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tencentPublisher.PublishOutboxEvent(appcode.WithContext(ctx, envelope.GetAppCode()), envelope)
|
||||
}); err != nil {
|
||||
_ = repository.Close()
|
||||
closeClientConn(activityConn)
|
||||
_ = walletConn.Close()
|
||||
_ = redisClient.Close()
|
||||
return nil, err
|
||||
}
|
||||
mqConsumers = append(mqConsumers, robotIMConsumer)
|
||||
}
|
||||
if cfg.RocketMQ.UserOutbox.Enabled {
|
||||
userConsumer, err := rocketmqx.NewConsumer(rocketMQConsumerConfig(cfg.RocketMQ, cfg.RocketMQ.UserOutbox.ConsumerGroup, cfg.RocketMQ.UserOutbox.ConsumerMaxReconsumeTimes))
|
||||
if err != nil {
|
||||
@ -317,6 +394,7 @@ func New(cfg config.Config) (*App, error) {
|
||||
return nil, err
|
||||
}
|
||||
workerCtx, workerCancel := context.WithCancel(context.Background())
|
||||
closeRobotDepsOnError = false
|
||||
|
||||
return &App{
|
||||
cfg: cfg,
|
||||
@ -325,6 +403,8 @@ func New(cfg config.Config) (*App, error) {
|
||||
listener: listener,
|
||||
walletConn: walletConn,
|
||||
activityConn: activityConn,
|
||||
robotConn: robotConn,
|
||||
userConn: userConn,
|
||||
repository: repository,
|
||||
redisClose: redisClient.Close,
|
||||
nodeRegistry: directory,
|
||||
@ -391,9 +471,25 @@ func (a *App) Run() error {
|
||||
})
|
||||
})
|
||||
}
|
||||
if a.cfg.RobotOutboxWorker.Enabled {
|
||||
a.workerWG.Go(func() {
|
||||
a.service.RunRobotOutboxWorker(a.workerCtx, roomservice.OutboxWorkerOptions{
|
||||
PollInterval: a.cfg.RobotOutboxWorker.PollInterval,
|
||||
BatchSize: a.cfg.RobotOutboxWorker.BatchSize,
|
||||
PublishTimeout: a.cfg.RobotOutboxWorker.PublishTimeout,
|
||||
RetryStrategy: a.cfg.RobotOutboxWorker.RetryStrategy,
|
||||
MaxRetryCount: a.cfg.RobotOutboxWorker.MaxRetryCount,
|
||||
InitialBackoff: a.cfg.RobotOutboxWorker.InitialBackoff,
|
||||
MaxBackoff: a.cfg.RobotOutboxWorker.MaxBackoff,
|
||||
})
|
||||
})
|
||||
}
|
||||
a.workerWG.Go(func() {
|
||||
a.service.RunRobotRoomRuntimeManager(a.workerCtx, 10*time.Second)
|
||||
})
|
||||
a.workerWG.Go(func() {
|
||||
a.service.RunHumanRoomRobotRuntimeManager(a.workerCtx, 15*time.Second)
|
||||
})
|
||||
|
||||
err := a.grpcServer.Serve(a.listener)
|
||||
a.health.MarkGRPCStopped()
|
||||
@ -435,6 +531,12 @@ func (a *App) Close() {
|
||||
if a.activityConn != nil {
|
||||
_ = a.activityConn.Close()
|
||||
}
|
||||
if a.robotConn != nil {
|
||||
_ = a.robotConn.Close()
|
||||
}
|
||||
if a.userConn != nil {
|
||||
_ = a.userConn.Close()
|
||||
}
|
||||
if a.repository != nil {
|
||||
// MySQL 连接池最后释放,保证 GracefulStop 期间仍可完成持久化。
|
||||
_ = a.repository.Close()
|
||||
|
||||
@ -52,6 +52,10 @@ type Config struct {
|
||||
WalletServiceAddr string `yaml:"wallet_service_addr"`
|
||||
// ActivityServiceAddr 是房间事实事件投给 activity-service 的内部 gRPC 地址。
|
||||
ActivityServiceAddr string `yaml:"activity_service_addr"`
|
||||
// RobotServiceAddr 是真人房间机器人运行时读取全站机器人池的内部 gRPC 地址。
|
||||
RobotServiceAddr string `yaml:"robot_service_addr"`
|
||||
// UserServiceAddr 是真人房间机器人运行时按用户资料分国家的内部 gRPC 地址。
|
||||
UserServiceAddr string `yaml:"user_service_addr"`
|
||||
// TencentIM 是腾讯云 IM 群组和房间系统消息的外部集成配置。
|
||||
TencentIM TencentIMConfig `yaml:"tencent_im"`
|
||||
// TencentRTC 是平台级封禁后移出实时音频房的外部集成配置。
|
||||
@ -84,6 +88,8 @@ type Config struct {
|
||||
RocketMQ RocketMQConfig `yaml:"rocketmq"`
|
||||
// OutboxWorker 控制 room_outbox 到腾讯云 IM 补偿投递 worker。
|
||||
OutboxWorker OutboxWorkerConfig `yaml:"outbox_worker"`
|
||||
// RobotOutboxWorker 控制机器人房间展示 outbox,避免机器人流量抢占主 room_outbox。
|
||||
RobotOutboxWorker OutboxWorkerConfig `yaml:"robot_outbox_worker"`
|
||||
// Log 控制 stdout 结构化日志格式、等级和 access body 策略。
|
||||
Log logx.Config `yaml:"log"`
|
||||
}
|
||||
@ -123,6 +129,7 @@ type RocketMQConfig struct {
|
||||
SendTimeout time.Duration `yaml:"send_timeout"`
|
||||
Retry int `yaml:"retry"`
|
||||
RoomOutbox RoomOutboxMQConfig `yaml:"room_outbox"`
|
||||
RobotRoomOutbox RoomOutboxMQConfig `yaml:"robot_room_outbox"`
|
||||
RocketLaunch RocketLaunchMQConfig `yaml:"rocket_launch"`
|
||||
UserOutbox UserOutboxMQConfig `yaml:"user_outbox"`
|
||||
}
|
||||
@ -245,6 +252,8 @@ func Default() Config {
|
||||
SnapshotEveryN: 10,
|
||||
WalletServiceAddr: "127.0.0.1:13004",
|
||||
ActivityServiceAddr: "127.0.0.1:13006",
|
||||
RobotServiceAddr: "127.0.0.1:13011",
|
||||
UserServiceAddr: "127.0.0.1:13005",
|
||||
TencentIM: TencentIMConfig{
|
||||
Enabled: false,
|
||||
AdminIdentifier: "administrator",
|
||||
@ -272,6 +281,7 @@ func Default() Config {
|
||||
RoomRocketLaunchScanInterval: time.Second,
|
||||
RocketMQ: defaultRocketMQConfig(),
|
||||
OutboxWorker: defaultOutboxWorkerConfig(),
|
||||
RobotOutboxWorker: defaultOutboxWorkerConfig(),
|
||||
Log: logx.Config{
|
||||
Level: "info",
|
||||
Format: "json",
|
||||
@ -308,6 +318,14 @@ func defaultRocketMQConfig() RocketMQConfig {
|
||||
TencentIMConsumerGroup: "hyapp-room-im-bridge",
|
||||
ConsumerMaxReconsumeTimes: 16,
|
||||
},
|
||||
RobotRoomOutbox: RoomOutboxMQConfig{
|
||||
Enabled: false,
|
||||
Topic: "hyapp_robot_room_outbox",
|
||||
ProducerGroup: "hyapp-room-robot-outbox-producer",
|
||||
TencentIMConsumerEnabled: false,
|
||||
TencentIMConsumerGroup: "hyapp-room-robot-im-bridge",
|
||||
ConsumerMaxReconsumeTimes: 16,
|
||||
},
|
||||
RocketLaunch: RocketLaunchMQConfig{
|
||||
Enabled: false,
|
||||
Topic: "hyapp_room_rocket_launch",
|
||||
@ -377,6 +395,14 @@ func Normalize(cfg Config) (Config, error) {
|
||||
if cfg.ActivityServiceAddr == "" {
|
||||
cfg.ActivityServiceAddr = "127.0.0.1:13006"
|
||||
}
|
||||
cfg.RobotServiceAddr = strings.TrimSpace(cfg.RobotServiceAddr)
|
||||
if cfg.RobotServiceAddr == "" {
|
||||
cfg.RobotServiceAddr = "127.0.0.1:13011"
|
||||
}
|
||||
cfg.UserServiceAddr = strings.TrimSpace(cfg.UserServiceAddr)
|
||||
if cfg.UserServiceAddr == "" {
|
||||
cfg.UserServiceAddr = "127.0.0.1:13005"
|
||||
}
|
||||
cfg.TencentRTC.SecretID = strings.TrimSpace(cfg.TencentRTC.SecretID)
|
||||
cfg.TencentRTC.SecretKey = strings.TrimSpace(cfg.TencentRTC.SecretKey)
|
||||
cfg.TencentRTC.Region = strings.TrimSpace(cfg.TencentRTC.Region)
|
||||
@ -395,7 +421,12 @@ func Normalize(cfg Config) (Config, error) {
|
||||
return Config{}, err
|
||||
}
|
||||
cfg.OutboxWorker = outboxWorker
|
||||
rocketMQ, err := normalizeRocketMQConfig(cfg.RocketMQ, cfg.OutboxWorker.PublishMode)
|
||||
robotOutboxWorker, err := normalizeOutboxWorkerConfig(cfg.RobotOutboxWorker)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
cfg.RobotOutboxWorker = robotOutboxWorker
|
||||
rocketMQ, err := normalizeRocketMQConfig(cfg.RocketMQ, cfg.OutboxWorker.PublishMode, cfg.RobotOutboxWorker.PublishMode)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
@ -462,7 +493,7 @@ func normalizeOutboxWorkerConfig(cfg OutboxWorkerConfig) (OutboxWorkerConfig, er
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func normalizeRocketMQConfig(cfg RocketMQConfig, publishMode string) (RocketMQConfig, error) {
|
||||
func normalizeRocketMQConfig(cfg RocketMQConfig, publishMode string, robotPublishMode string) (RocketMQConfig, error) {
|
||||
defaults := defaultRocketMQConfig()
|
||||
cfg.NameServers = normalizeStringSlice(cfg.NameServers)
|
||||
cfg.NameServerDomain = strings.TrimSpace(cfg.NameServerDomain)
|
||||
@ -488,6 +519,18 @@ func normalizeRocketMQConfig(cfg RocketMQConfig, publishMode string) (RocketMQCo
|
||||
if cfg.RoomOutbox.ConsumerMaxReconsumeTimes <= 0 {
|
||||
cfg.RoomOutbox.ConsumerMaxReconsumeTimes = defaults.RoomOutbox.ConsumerMaxReconsumeTimes
|
||||
}
|
||||
if cfg.RobotRoomOutbox.Topic = strings.TrimSpace(cfg.RobotRoomOutbox.Topic); cfg.RobotRoomOutbox.Topic == "" {
|
||||
cfg.RobotRoomOutbox.Topic = defaults.RobotRoomOutbox.Topic
|
||||
}
|
||||
if cfg.RobotRoomOutbox.ProducerGroup = strings.TrimSpace(cfg.RobotRoomOutbox.ProducerGroup); cfg.RobotRoomOutbox.ProducerGroup == "" {
|
||||
cfg.RobotRoomOutbox.ProducerGroup = defaults.RobotRoomOutbox.ProducerGroup
|
||||
}
|
||||
if cfg.RobotRoomOutbox.TencentIMConsumerGroup = strings.TrimSpace(cfg.RobotRoomOutbox.TencentIMConsumerGroup); cfg.RobotRoomOutbox.TencentIMConsumerGroup == "" {
|
||||
cfg.RobotRoomOutbox.TencentIMConsumerGroup = defaults.RobotRoomOutbox.TencentIMConsumerGroup
|
||||
}
|
||||
if cfg.RobotRoomOutbox.ConsumerMaxReconsumeTimes <= 0 {
|
||||
cfg.RobotRoomOutbox.ConsumerMaxReconsumeTimes = defaults.RobotRoomOutbox.ConsumerMaxReconsumeTimes
|
||||
}
|
||||
if cfg.RocketLaunch.Topic = strings.TrimSpace(cfg.RocketLaunch.Topic); cfg.RocketLaunch.Topic == "" {
|
||||
cfg.RocketLaunch.Topic = defaults.RocketLaunch.Topic
|
||||
}
|
||||
@ -509,7 +552,7 @@ func normalizeRocketMQConfig(cfg RocketMQConfig, publishMode string) (RocketMQCo
|
||||
if cfg.UserOutbox.ConsumerMaxReconsumeTimes <= 0 {
|
||||
cfg.UserOutbox.ConsumerMaxReconsumeTimes = defaults.UserOutbox.ConsumerMaxReconsumeTimes
|
||||
}
|
||||
if cfg.RoomOutbox.Enabled || cfg.RocketLaunch.Enabled || cfg.UserOutbox.Enabled || cfg.RoomOutbox.TencentIMConsumerEnabled {
|
||||
if cfg.RoomOutbox.Enabled || cfg.RobotRoomOutbox.Enabled || cfg.RocketLaunch.Enabled || cfg.UserOutbox.Enabled || cfg.RoomOutbox.TencentIMConsumerEnabled || cfg.RobotRoomOutbox.TencentIMConsumerEnabled {
|
||||
cfg.Enabled = true
|
||||
}
|
||||
if publishMode == OutboxPublishModeMQ || publishMode == OutboxPublishModeDual {
|
||||
@ -517,6 +560,11 @@ func normalizeRocketMQConfig(cfg RocketMQConfig, publishMode string) (RocketMQCo
|
||||
return RocketMQConfig{}, fmt.Errorf("outbox_worker publish_mode %q requires rocketmq.room_outbox.enabled", publishMode)
|
||||
}
|
||||
}
|
||||
if robotPublishMode == OutboxPublishModeMQ || robotPublishMode == OutboxPublishModeDual {
|
||||
if !cfg.RobotRoomOutbox.Enabled {
|
||||
return RocketMQConfig{}, fmt.Errorf("robot_outbox_worker publish_mode %q requires rocketmq.robot_room_outbox.enabled", robotPublishMode)
|
||||
}
|
||||
}
|
||||
if cfg.Enabled {
|
||||
if len(cfg.NameServers) == 0 && cfg.NameServerDomain == "" {
|
||||
return RocketMQConfig{}, fmt.Errorf("rocketmq name_servers or name_server_domain is required")
|
||||
|
||||
@ -34,13 +34,22 @@ func TestLoad(t *testing.T) {
|
||||
if cfg.WalletServiceAddr != "127.0.0.1:13004" {
|
||||
t.Fatalf("unexpected wallet addr: %s", cfg.WalletServiceAddr)
|
||||
}
|
||||
if cfg.TencentIM.SDKAppID != 20040101 || cfg.TencentIM.SecretKey == "" || cfg.TencentIM.AdminIdentifier != "administrator" {
|
||||
t.Fatalf("local room-service must use test Tencent IM account: %+v", cfg.TencentIM)
|
||||
}
|
||||
if !cfg.OutboxWorker.Enabled || cfg.OutboxWorker.PublishMode != OutboxPublishModeMQ || cfg.OutboxWorker.PollInterval != time.Second || cfg.OutboxWorker.BatchSize != 100 || cfg.OutboxWorker.PublishTimeout != 3*time.Second || cfg.OutboxWorker.RetryStrategy != "exponential_backoff" || cfg.OutboxWorker.MaxRetryCount != 10 || cfg.OutboxWorker.InitialBackoff != 5*time.Second || cfg.OutboxWorker.MaxBackoff != 5*time.Minute {
|
||||
t.Fatalf("unexpected outbox worker config: %+v", cfg.OutboxWorker)
|
||||
}
|
||||
if !cfg.RobotOutboxWorker.Enabled || cfg.RobotOutboxWorker.PublishMode != OutboxPublishModeMQ || cfg.RobotOutboxWorker.PollInterval != time.Second || cfg.RobotOutboxWorker.BatchSize != 30 || cfg.RobotOutboxWorker.PublishTimeout != 3*time.Second || cfg.RobotOutboxWorker.RetryStrategy != "exponential_backoff" || cfg.RobotOutboxWorker.MaxRetryCount != 10 || cfg.RobotOutboxWorker.InitialBackoff != 5*time.Second || cfg.RobotOutboxWorker.MaxBackoff != 5*time.Minute {
|
||||
t.Fatalf("unexpected robot outbox worker config: %+v", cfg.RobotOutboxWorker)
|
||||
}
|
||||
// 本地默认也走 room_outbox MQ、IM bridge 和火箭延迟唤醒,避免本地直投和线上 MQ 语义分叉。
|
||||
if !cfg.RocketMQ.Enabled || !cfg.RocketMQ.RoomOutbox.Enabled || !cfg.RocketMQ.RoomOutbox.TencentIMConsumerEnabled || !cfg.RocketMQ.RocketLaunch.Enabled || !cfg.RocketMQ.UserOutbox.Enabled {
|
||||
if !cfg.RocketMQ.Enabled || !cfg.RocketMQ.RoomOutbox.Enabled || !cfg.RocketMQ.RoomOutbox.TencentIMConsumerEnabled || !cfg.RocketMQ.RobotRoomOutbox.Enabled || !cfg.RocketMQ.RobotRoomOutbox.TencentIMConsumerEnabled || !cfg.RocketMQ.RocketLaunch.Enabled || !cfg.RocketMQ.UserOutbox.Enabled {
|
||||
t.Fatalf("local config must enable room MQ fanout and IM bridge: %+v", cfg.RocketMQ)
|
||||
}
|
||||
if cfg.RocketMQ.RobotRoomOutbox.TencentIMConsumerGroup != "hyapp-test-room-robot-im-bridge" {
|
||||
t.Fatalf("local robot IM bridge group mismatch: %s", cfg.RocketMQ.RobotRoomOutbox.TencentIMConsumerGroup)
|
||||
}
|
||||
}
|
||||
|
||||
// TestLoadTencentExample 验证线上腾讯云 IM 模板能覆盖本地默认配置。
|
||||
@ -71,9 +80,15 @@ func TestLoadTencentExample(t *testing.T) {
|
||||
if !cfg.OutboxWorker.Enabled || cfg.OutboxWorker.RetryStrategy != "exponential_backoff" || cfg.OutboxWorker.MaxRetryCount != 10 {
|
||||
t.Fatalf("tencent example must configure outbox worker: %+v", cfg.OutboxWorker)
|
||||
}
|
||||
if cfg.OutboxWorker.PublishMode != OutboxPublishModeMQ || !cfg.RocketMQ.RoomOutbox.Enabled || !cfg.RocketMQ.RocketLaunch.Enabled {
|
||||
if !cfg.RobotOutboxWorker.Enabled || cfg.RobotOutboxWorker.PublishMode != OutboxPublishModeMQ || cfg.RobotOutboxWorker.BatchSize != 30 {
|
||||
t.Fatalf("tencent example must configure robot outbox worker: %+v", cfg.RobotOutboxWorker)
|
||||
}
|
||||
if cfg.OutboxWorker.PublishMode != OutboxPublishModeMQ || !cfg.RocketMQ.RoomOutbox.Enabled || !cfg.RocketMQ.RobotRoomOutbox.Enabled || !cfg.RocketMQ.RocketLaunch.Enabled {
|
||||
t.Fatalf("tencent example must route room outbox and rocket launch through RocketMQ: mode=%s mq=%+v", cfg.OutboxWorker.PublishMode, cfg.RocketMQ)
|
||||
}
|
||||
if cfg.RocketMQ.RobotRoomOutbox.TencentIMConsumerGroup != "hyapp-room-robot-im-bridge" {
|
||||
t.Fatalf("prod robot IM bridge group mismatch: %s", cfg.RocketMQ.RobotRoomOutbox.TencentIMConsumerGroup)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadDockerConfigStartsRoomIMBridgeWhenOutboxUsesMQ(t *testing.T) {
|
||||
@ -91,6 +106,12 @@ func TestLoadDockerConfigStartsRoomIMBridgeWhenOutboxUsesMQ(t *testing.T) {
|
||||
if !cfg.RocketMQ.RoomOutbox.TencentIMConsumerEnabled {
|
||||
t.Fatalf("docker mq room outbox must start Tencent IM bridge consumer")
|
||||
}
|
||||
if cfg.RobotOutboxWorker.PublishMode != OutboxPublishModeMQ || !cfg.RocketMQ.RobotRoomOutbox.Enabled || !cfg.RocketMQ.RobotRoomOutbox.TencentIMConsumerEnabled {
|
||||
t.Fatalf("docker config must start robot outbox MQ and IM bridge: worker=%+v mq=%+v", cfg.RobotOutboxWorker, cfg.RocketMQ.RobotRoomOutbox)
|
||||
}
|
||||
if cfg.TencentIM.SDKAppID != 20040101 || cfg.TencentIM.AdminIdentifier != "administrator" || cfg.RocketMQ.RobotRoomOutbox.TencentIMConsumerGroup != "hyapp-test-room-robot-im-bridge" {
|
||||
t.Fatalf("docker config must use test IM account and robot group: im=%+v group=%s", cfg.TencentIM, cfg.RocketMQ.RobotRoomOutbox.TencentIMConsumerGroup)
|
||||
}
|
||||
if !cfg.TencentIM.Enabled {
|
||||
t.Fatalf("Tencent IM bridge consumer requires tencent_im.enabled")
|
||||
}
|
||||
|
||||
141
services/room-service/internal/integration/human_robot_pool.go
Normal file
141
services/room-service/internal/integration/human_robot_pool.go
Normal file
@ -0,0 +1,141 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
robotv1 "hyapp.local/api/proto/robot/v1"
|
||||
userv1 "hyapp.local/api/proto/user/v1"
|
||||
"hyapp/pkg/appcode"
|
||||
)
|
||||
|
||||
const humanRobotPoolPageSize = int32(200)
|
||||
|
||||
// HumanRoomRobotPool 是真人房间机器人运行时按国家分组后的账号池。
|
||||
type HumanRoomRobotPool struct {
|
||||
CountryCode string
|
||||
RobotUserIDs []int64
|
||||
}
|
||||
|
||||
// HumanRoomRobotPoolProvider 屏蔽 robot-service 和 user-service 的组合查询细节。
|
||||
type HumanRoomRobotPoolProvider interface {
|
||||
ListHumanRoomRobotPools(ctx context.Context, appCode string) ([]HumanRoomRobotPool, error)
|
||||
}
|
||||
|
||||
type GRPCHumanRoomRobotPoolProvider struct {
|
||||
robots robotv1.GameRobotServiceClient
|
||||
users userv1.UserServiceClient
|
||||
}
|
||||
|
||||
func NewGRPCHumanRoomRobotPoolProvider(robotConn grpc.ClientConnInterface, userConn grpc.ClientConnInterface) *GRPCHumanRoomRobotPoolProvider {
|
||||
return &GRPCHumanRoomRobotPoolProvider{
|
||||
robots: robotv1.NewGameRobotServiceClient(robotConn),
|
||||
users: userv1.NewUserServiceClient(userConn),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *GRPCHumanRoomRobotPoolProvider) ListHumanRoomRobotPools(ctx context.Context, appCode string) ([]HumanRoomRobotPool, error) {
|
||||
if p == nil || p.robots == nil || p.users == nil {
|
||||
return nil, fmt.Errorf("human room robot pool provider is not configured")
|
||||
}
|
||||
app := appcode.Normalize(appCode)
|
||||
userIDs, err := p.listActiveRobotUserIDs(ctx, app)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(userIDs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
groups := make(map[string][]int64)
|
||||
for start := 0; start < len(userIDs); start += int(humanRobotPoolPageSize) {
|
||||
end := start + int(humanRobotPoolPageSize)
|
||||
if end > len(userIDs) {
|
||||
end = len(userIDs)
|
||||
}
|
||||
resp, err := p.users.BatchGetUsers(ctx, &userv1.BatchGetUsersRequest{
|
||||
Meta: userRequestMeta(app, "room-human-robot-users"),
|
||||
UserIds: userIDs[start:end],
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, userID := range userIDs[start:end] {
|
||||
user := resp.GetUsers()[userID]
|
||||
countryCode := normalizePoolCountryCode(user.GetCountry())
|
||||
if countryCode == "" {
|
||||
continue
|
||||
}
|
||||
groups[countryCode] = append(groups[countryCode], userID)
|
||||
}
|
||||
}
|
||||
pools := make([]HumanRoomRobotPool, 0, len(groups))
|
||||
for countryCode, ids := range groups {
|
||||
pools = append(pools, HumanRoomRobotPool{CountryCode: countryCode, RobotUserIDs: ids})
|
||||
}
|
||||
sort.Slice(pools, func(i, j int) bool { return pools[i].CountryCode < pools[j].CountryCode })
|
||||
return pools, nil
|
||||
}
|
||||
|
||||
func (p *GRPCHumanRoomRobotPoolProvider) listActiveRobotUserIDs(ctx context.Context, app string) ([]int64, error) {
|
||||
userIDs := make([]int64, 0, humanRobotPoolPageSize)
|
||||
cursor := ""
|
||||
for {
|
||||
resp, err := p.robots.ListGameRobots(ctx, &robotv1.ListGameRobotsRequest{
|
||||
Meta: robotRequestMeta(app, "room-human-robot-pool"),
|
||||
Status: "active",
|
||||
PageSize: humanRobotPoolPageSize,
|
||||
Cursor: cursor,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, robot := range resp.GetRobots() {
|
||||
if robot.GetUserId() > 0 {
|
||||
userIDs = append(userIDs, robot.GetUserId())
|
||||
}
|
||||
}
|
||||
cursor = strings.TrimSpace(resp.GetNextCursor())
|
||||
if cursor == "" {
|
||||
return uniquePositiveInt64(userIDs), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func robotRequestMeta(appCode string, requestID string) *robotv1.RequestMeta {
|
||||
return &robotv1.RequestMeta{
|
||||
RequestId: requestID,
|
||||
Caller: "room-service",
|
||||
AppCode: appcode.Normalize(appCode),
|
||||
SentAtMs: time.Now().UTC().UnixMilli(),
|
||||
}
|
||||
}
|
||||
|
||||
func userRequestMeta(appCode string, requestID string) *userv1.RequestMeta {
|
||||
return &userv1.RequestMeta{
|
||||
RequestId: requestID,
|
||||
Caller: "room-service",
|
||||
AppCode: appcode.Normalize(appCode),
|
||||
SentAtMs: time.Now().UTC().UnixMilli(),
|
||||
}
|
||||
}
|
||||
|
||||
func normalizePoolCountryCode(value string) string {
|
||||
return strings.ToUpper(strings.TrimSpace(value))
|
||||
}
|
||||
|
||||
func uniquePositiveInt64(values []int64) []int64 {
|
||||
seen := make(map[int64]bool, len(values))
|
||||
out := make([]int64, 0, len(values))
|
||||
for _, value := range values {
|
||||
if value <= 0 || seen[value] {
|
||||
continue
|
||||
}
|
||||
seen[value] = true
|
||||
out = append(out, value)
|
||||
}
|
||||
return out
|
||||
}
|
||||
@ -315,6 +315,33 @@ func roomEventFromEnvelope(envelope *roomeventsv1.EventEnvelope) (tencentim.Room
|
||||
"gift_effect_types": string(effectTypesJSON),
|
||||
}
|
||||
return base, true, nil
|
||||
case "RoomHeatChanged":
|
||||
// 机器人通道也会投递热度展示事件,客户端可独立刷新房间热度,不依赖主 outbox。
|
||||
var body roomeventsv1.RoomHeatChanged
|
||||
if err := proto.Unmarshal(envelope.GetBody(), &body); err != nil {
|
||||
return tencentim.RoomEvent{}, false, err
|
||||
}
|
||||
base.RoomHeat = body.GetCurrentHeat()
|
||||
base.Attributes = map[string]string{
|
||||
"delta": fmt.Sprintf("%d", body.GetDelta()),
|
||||
"room_heat": fmt.Sprintf("%d", body.GetCurrentHeat()),
|
||||
}
|
||||
return base, true, nil
|
||||
case "RoomRankChanged":
|
||||
// 麦位收礼热度属于房间内展示数据;机器人事件只在 robot outbox 内广播。
|
||||
var body roomeventsv1.RoomRankChanged
|
||||
if err := proto.Unmarshal(envelope.GetBody(), &body); err != nil {
|
||||
return tencentim.RoomEvent{}, false, err
|
||||
}
|
||||
base.ActorUserID = body.GetUserId()
|
||||
base.TargetUserID = body.GetUserId()
|
||||
base.GiftValue = body.GetGiftValue()
|
||||
base.Attributes = map[string]string{
|
||||
"user_id": fmt.Sprintf("%d", body.GetUserId()),
|
||||
"score": fmt.Sprintf("%d", body.GetScore()),
|
||||
"gift_value": fmt.Sprintf("%d", body.GetGiftValue()),
|
||||
}
|
||||
return base, true, nil
|
||||
case "RoomRobotLuckyGiftDrawn":
|
||||
// 机器人幸运礼物只发房间展示协议,不进入 activity-service 真实抽奖和奖池链路。
|
||||
var body roomeventsv1.RoomRobotLuckyGiftDrawn
|
||||
@ -471,6 +498,10 @@ func eventTypeForClient(eventType string) string {
|
||||
return "room_user_unbanned"
|
||||
case "RoomGiftSent":
|
||||
return "room_gift_sent"
|
||||
case "RoomHeatChanged":
|
||||
return "room_heat_changed"
|
||||
case "RoomRankChanged":
|
||||
return "room_rank_changed"
|
||||
case "RoomRobotLuckyGiftDrawn":
|
||||
return "lucky_gift_drawn"
|
||||
case "RoomRocketFuelChanged":
|
||||
|
||||
@ -113,6 +113,76 @@ func TestRoomGiftSentCarriesTargetGiftValueInIMAttributes(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoomHeatAndRankChangedPublishDisplayIMEvents(t *testing.T) {
|
||||
heatRecord, err := outbox.Build("room-robot-heat", "RoomHeatChanged", 9, time.Now(), &roomeventsv1.RoomHeatChanged{
|
||||
Delta: 120,
|
||||
CurrentHeat: 880,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Build RoomHeatChanged envelope failed: %v", err)
|
||||
}
|
||||
heatEvent, publish, err := roomEventFromEnvelope(heatRecord.Envelope)
|
||||
if err != nil {
|
||||
t.Fatalf("RoomHeatChanged should decode: %v", err)
|
||||
}
|
||||
if !publish || heatEvent.EventType != "room_heat_changed" || heatEvent.RoomHeat != 880 || heatEvent.Attributes["delta"] != "120" {
|
||||
t.Fatalf("heat IM event mismatch: publish=%t event=%+v", publish, heatEvent)
|
||||
}
|
||||
|
||||
rankRecord, err := outbox.Build("room-robot-rank", "RoomRankChanged", 10, time.Now(), &roomeventsv1.RoomRankChanged{
|
||||
UserId: 1002,
|
||||
Score: 360,
|
||||
GiftValue: 360,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Build RoomRankChanged envelope failed: %v", err)
|
||||
}
|
||||
rankEvent, publish, err := roomEventFromEnvelope(rankRecord.Envelope)
|
||||
if err != nil {
|
||||
t.Fatalf("RoomRankChanged should decode: %v", err)
|
||||
}
|
||||
if !publish || rankEvent.EventType != "room_rank_changed" || rankEvent.TargetUserID != 1002 || rankEvent.GiftValue != 360 || rankEvent.Attributes["score"] != "360" {
|
||||
t.Fatalf("rank IM event mismatch: publish=%t event=%+v", publish, rankEvent)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoomRobotLuckyGiftDrawnPublishesLuckyGiftIMEvent(t *testing.T) {
|
||||
record, err := outbox.Build("room-robot-lucky", "RoomRobotLuckyGiftDrawn", 11, time.Now(), &roomeventsv1.RoomRobotLuckyGiftDrawn{
|
||||
DrawId: "robot_lucky_draw_1",
|
||||
CommandId: "cmd_robot_lucky_1",
|
||||
SenderUserId: 1001,
|
||||
TargetUserId: 1002,
|
||||
GiftId: "gift_lucky_1",
|
||||
GiftCount: 1,
|
||||
PoolId: "robot_lucky_display",
|
||||
MultiplierPpm: 5000000,
|
||||
BaseRewardCoins: 500,
|
||||
EffectiveRewardCoins: 500,
|
||||
CreatedAtMs: 1778000000000,
|
||||
VisibleRegionId: 86,
|
||||
IsRobot: true,
|
||||
Synthetic: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Build RoomRobotLuckyGiftDrawn envelope failed: %v", err)
|
||||
}
|
||||
|
||||
event, publish, err := roomEventFromEnvelope(record.Envelope)
|
||||
if err != nil {
|
||||
t.Fatalf("RoomRobotLuckyGiftDrawn should decode: %v", err)
|
||||
}
|
||||
if !publish || event.EventType != "lucky_gift_drawn" || event.ActorUserID != 1001 || event.TargetUserID != 1002 {
|
||||
t.Fatalf("robot lucky gift IM event mismatch: publish=%t event=%+v", publish, event)
|
||||
}
|
||||
if event.Attributes["draw_id"] != "robot_lucky_draw_1" ||
|
||||
event.Attributes["gift_id"] != "gift_lucky_1" ||
|
||||
event.Attributes["pool_id"] != "robot_lucky_display" ||
|
||||
event.Attributes["effective_reward_coins"] != "500" ||
|
||||
event.Attributes["reward_status"] != "granted" {
|
||||
t.Fatalf("robot lucky gift IM attributes mismatch: %+v", event.Attributes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoomMicChangedCarriesTargetGiftValueInIMAttributes(t *testing.T) {
|
||||
record, err := outbox.Build("room-mic-value", "RoomMicChanged", 9, time.Now(), &roomeventsv1.RoomMicChanged{
|
||||
ActorUserId: 1001,
|
||||
|
||||
@ -476,6 +476,8 @@ type SendGift struct {
|
||||
RocketCurrentContributions []RocketContribution `json:"rocket_current_contributions,omitempty"`
|
||||
// RobotGift 表示本次礼物只服务机器人房间展示;不写真实统计、任务、周星和房间贡献榜。
|
||||
RobotGift bool `json:"robot_gift,omitempty"`
|
||||
// RobotWalletGift 表示本次礼物由机器人钱包结算;真人房间机器人可以用它贡献真实房间热度。
|
||||
RobotWalletGift bool `json:"robot_wallet_gift,omitempty"`
|
||||
// SyntheticLuckyGift 表示幸运礼物只生成展示事件,不调用真实 activity 抽奖和奖池。
|
||||
SyntheticLuckyGift bool `json:"synthetic_lucky_gift,omitempty"`
|
||||
// SyntheticLuckyRewardCoins 是机器人幸运礼物展示用爆奖金币值,不代表真实钱包返奖。
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"math/rand"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
roomv1 "hyapp.local/api/proto/room/v1"
|
||||
@ -21,6 +22,16 @@ const (
|
||||
robotRoomStatusStopped = "stopped"
|
||||
robotRoomMode = "voice"
|
||||
robotRoomLuckyPoolID = "robot_lucky_display"
|
||||
|
||||
maxRobotLuckyComboPerCycle = int64(3)
|
||||
|
||||
defaultRobotStayMinMS = int64(3 * 60 * 1000)
|
||||
defaultRobotStayMaxMS = int64(10 * 60 * 1000)
|
||||
defaultRobotReplaceMinMS = int64(0)
|
||||
defaultRobotReplaceMaxMS = int64(60 * 1000)
|
||||
defaultMaxGiftSenders = int64(1)
|
||||
|
||||
defaultRobotRoomSeatCount = int32(10)
|
||||
)
|
||||
|
||||
func (s *Service) AdminListRobotRooms(ctx context.Context, req *roomv1.AdminListRobotRoomsRequest) (*roomv1.AdminListRobotRoomsResponse, error) {
|
||||
@ -152,11 +163,15 @@ func (s *Service) buildRobotRoomConfig(ctx context.Context, req *roomv1.AdminCre
|
||||
if selectedCount > len(available) {
|
||||
selectedCount = len(available)
|
||||
}
|
||||
selected := selectRobotUsers(rng, ownerID, available, selectedCount)
|
||||
robotPool := selectRobotUsers(rng, ownerID, available, len(available))
|
||||
rule, err := normalizeRobotRoomGiftRule(req.GetGiftRule())
|
||||
if err != nil {
|
||||
return RobotRoomConfig{}, err
|
||||
}
|
||||
seatCount := normalizeRobotRoomSeatCount(req.GetSeatCount())
|
||||
if seatCount <= 0 {
|
||||
return RobotRoomConfig{}, xerr.New(xerr.InvalidArgument, "robot room seat_count is invalid")
|
||||
}
|
||||
roomID := fmt.Sprintf("robot_%d_%d", now.UnixMilli(), rng.Intn(900000)+100000)
|
||||
if !roomid.ValidStringID(roomID) {
|
||||
return RobotRoomConfig{}, xerr.New(xerr.Internal, "generated robot room id is invalid")
|
||||
@ -176,9 +191,12 @@ func (s *Service) buildRobotRoomConfig(ctx context.Context, req *roomv1.AdminCre
|
||||
Title: title,
|
||||
CoverURL: coverURL,
|
||||
VisibleRegionID: normalizeVisibleRegionID(req.GetVisibleRegionId()),
|
||||
OwnerCountryCode: normalizeRoomCountryCode(req.GetOwnerCountryCode()),
|
||||
Status: robotRoomStatusActive,
|
||||
OwnerRobotUserID: ownerID,
|
||||
RobotUserIDs: selected,
|
||||
RobotUserIDs: robotPool,
|
||||
ActiveRobotCount: int32(selectedCount),
|
||||
SeatCount: seatCount,
|
||||
GiftRule: rule,
|
||||
CreatedByAdminID: req.GetAdminId(),
|
||||
CreatedAtMS: now.UnixMilli(),
|
||||
@ -187,6 +205,7 @@ func (s *Service) buildRobotRoomConfig(ctx context.Context, req *roomv1.AdminCre
|
||||
}
|
||||
|
||||
func (s *Service) bootstrapRobotRoom(ctx context.Context, config RobotRoomConfig) error {
|
||||
activeIDs := robotRoomInitialActiveIDs(config)
|
||||
_, err := s.CreateRoom(ctx, &roomv1.CreateRoomRequest{
|
||||
Meta: &roomv1.RequestMeta{
|
||||
RequestId: fmt.Sprintf("admin-robot-room-create-%s", config.RoomID),
|
||||
@ -196,19 +215,20 @@ func (s *Service) bootstrapRobotRoom(ctx context.Context, config RobotRoomConfig
|
||||
AppCode: config.AppCode,
|
||||
SentAtMs: s.clock.Now().UnixMilli(),
|
||||
},
|
||||
SeatCount: int32(max(10, len(config.RobotUserIDs))),
|
||||
Mode: robotRoomMode,
|
||||
VisibleRegionId: config.VisibleRegionID,
|
||||
RoomName: config.Title,
|
||||
RoomAvatar: config.CoverURL,
|
||||
RoomShortId: config.RoomShortID,
|
||||
RobotRoom: true,
|
||||
RobotUserIds: config.RobotUserIDs,
|
||||
SeatCount: config.SeatCount,
|
||||
Mode: robotRoomMode,
|
||||
VisibleRegionId: config.VisibleRegionID,
|
||||
OwnerCountryCode: config.OwnerCountryCode,
|
||||
RoomName: config.Title,
|
||||
RoomAvatar: config.CoverURL,
|
||||
RoomShortId: config.RoomShortID,
|
||||
RobotRoom: true,
|
||||
RobotUserIds: config.RobotUserIDs,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, userID := range config.RobotUserIDs {
|
||||
for _, userID := range activeIDs {
|
||||
if userID == config.OwnerRobotUserID {
|
||||
continue
|
||||
}
|
||||
@ -219,7 +239,7 @@ func (s *Service) bootstrapRobotRoom(ctx context.Context, config RobotRoomConfig
|
||||
return err
|
||||
}
|
||||
}
|
||||
for index, userID := range config.RobotUserIDs {
|
||||
for index, userID := range activeIDs {
|
||||
if _, err := s.RobotVirtualMicUp(ctx, RobotMicUpInput{
|
||||
Meta: robotRoomCommandMeta(config, config.OwnerRobotUserID, fmt.Sprintf("mic:%d", userID)),
|
||||
TargetUserID: userID,
|
||||
@ -236,6 +256,7 @@ func (s *Service) RunRobotRoomRuntimeManager(ctx context.Context, interval time.
|
||||
if interval <= 0 {
|
||||
interval = 10 * time.Second
|
||||
}
|
||||
logx.Info(ctx, "robot_room_runtime_manager_started", slog.Int64("interval_ms", interval.Milliseconds()))
|
||||
ticker := time.NewTicker(interval)
|
||||
defer ticker.Stop()
|
||||
s.startActiveRobotRooms(ctx)
|
||||
@ -256,6 +277,7 @@ func (s *Service) startActiveRobotRooms(ctx context.Context) {
|
||||
logx.Warn(ctx, "robot_room_runtime_scan_failed", slog.String("error", err.Error()))
|
||||
return
|
||||
}
|
||||
logx.Info(ctx, "robot_room_runtime_scan_completed", slog.Int("active_room_count", len(configs)))
|
||||
for _, config := range configs {
|
||||
s.startRobotRoomRuntime(ctx, config)
|
||||
}
|
||||
@ -263,37 +285,79 @@ func (s *Service) startActiveRobotRooms(ctx context.Context) {
|
||||
|
||||
func (s *Service) startRobotRoomRuntime(parent context.Context, config RobotRoomConfig) {
|
||||
if config.Status != robotRoomStatusActive || len(config.RobotUserIDs) < 2 {
|
||||
logx.Info(parent, "robot_room_runtime_start_skipped",
|
||||
slog.String("room_id", config.RoomID),
|
||||
slog.String("status", config.Status),
|
||||
slog.Int("robot_count", len(config.RobotUserIDs)),
|
||||
)
|
||||
return
|
||||
}
|
||||
if err := parent.Err(); err != nil {
|
||||
// 管理端创建/启停请求的 ctx 会随 HTTP/gRPC 请求结束而取消;已取消的 ctx 不能写入
|
||||
// runtime map,否则后台恢复扫描会误以为该房间仍在运行。
|
||||
logx.Warn(parent, "robot_room_runtime_parent_cancelled", slog.String("room_id", config.RoomID), slog.String("error", err.Error()))
|
||||
return
|
||||
}
|
||||
s.robotRuntimeMu.Lock()
|
||||
if s.robotRuntimes == nil {
|
||||
s.robotRuntimes = make(map[string]context.CancelFunc)
|
||||
s.robotRuntimes = make(map[string]robotRoomRuntime)
|
||||
}
|
||||
if _, exists := s.robotRuntimes[config.RoomID]; exists {
|
||||
s.robotRuntimeMu.Unlock()
|
||||
logx.Info(parent, "robot_room_runtime_start_skipped",
|
||||
slog.String("room_id", config.RoomID),
|
||||
slog.String("status", config.Status),
|
||||
slog.Int("robot_count", len(config.RobotUserIDs)),
|
||||
slog.String("reason", "already_running"),
|
||||
)
|
||||
return
|
||||
}
|
||||
s.robotRuntimeMu.Unlock()
|
||||
|
||||
if err := s.ensureRobotRoomParticipants(parent, config); err != nil {
|
||||
logx.Warn(parent, "robot_room_runtime_prepare_failed", slog.String("room_id", config.RoomID), slog.String("error", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
s.robotRuntimeMu.Lock()
|
||||
if _, exists := s.robotRuntimes[config.RoomID]; exists {
|
||||
s.robotRuntimeMu.Unlock()
|
||||
return
|
||||
}
|
||||
ctx, cancel := context.WithCancel(appcode.WithContext(parent, config.AppCode))
|
||||
s.robotRuntimes[config.RoomID] = cancel
|
||||
token := fmt.Sprintf("%s:%d", config.RoomID, time.Now().UTC().UnixNano())
|
||||
s.robotRuntimes[config.RoomID] = robotRoomRuntime{cancel: cancel, token: token}
|
||||
s.robotRuntimeMu.Unlock()
|
||||
go s.runRobotRoomRuntime(ctx, config)
|
||||
logx.Info(ctx, "robot_room_runtime_started",
|
||||
slog.String("room_id", config.RoomID),
|
||||
slog.Int64("owner_robot_user_id", config.OwnerRobotUserID),
|
||||
slog.Int("robot_count", len(config.RobotUserIDs)),
|
||||
slog.Int("normal_gift_count", len(config.GiftRule.GiftIDs)),
|
||||
slog.Int("lucky_gift_count", len(config.GiftRule.LuckyGiftIDs)),
|
||||
)
|
||||
go func() {
|
||||
defer s.clearRobotRoomRuntime(config.RoomID, token)
|
||||
s.runRobotRoomRuntime(ctx, config)
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *Service) stopRobotRoomRuntime(roomID string) {
|
||||
s.robotRuntimeMu.Lock()
|
||||
cancel := s.robotRuntimes[roomID]
|
||||
runtime := s.robotRuntimes[roomID]
|
||||
delete(s.robotRuntimes, roomID)
|
||||
s.robotRuntimeMu.Unlock()
|
||||
if cancel != nil {
|
||||
cancel()
|
||||
if runtime.cancel != nil {
|
||||
runtime.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) stopAllRobotRoomRuntimes() {
|
||||
s.robotRuntimeMu.Lock()
|
||||
cancels := make([]context.CancelFunc, 0, len(s.robotRuntimes))
|
||||
for roomID, cancel := range s.robotRuntimes {
|
||||
cancels = append(cancels, cancel)
|
||||
for roomID, runtime := range s.robotRuntimes {
|
||||
if runtime.cancel != nil {
|
||||
cancels = append(cancels, runtime.cancel)
|
||||
}
|
||||
delete(s.robotRuntimes, roomID)
|
||||
}
|
||||
s.robotRuntimeMu.Unlock()
|
||||
@ -302,16 +366,158 @@ func (s *Service) stopAllRobotRoomRuntimes() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) clearRobotRoomRuntime(roomID string, token string) {
|
||||
s.robotRuntimeMu.Lock()
|
||||
defer s.robotRuntimeMu.Unlock()
|
||||
runtime, exists := s.robotRuntimes[roomID]
|
||||
if !exists || runtime.token != token {
|
||||
return
|
||||
}
|
||||
delete(s.robotRuntimes, roomID)
|
||||
}
|
||||
|
||||
func (s *Service) ensureRobotRoomParticipants(ctx context.Context, config RobotRoomConfig) error {
|
||||
roomCtx := appcode.WithContext(ctx, config.AppCode)
|
||||
snapshot, err := s.currentSnapshot(roomCtx, config.RoomID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
online := make(map[int64]bool, len(snapshot.GetOnlineUsers()))
|
||||
for _, user := range snapshot.GetOnlineUsers() {
|
||||
online[user.GetUserId()] = true
|
||||
}
|
||||
activeTarget := robotRoomActiveTarget(config)
|
||||
activeRobots := onlineRobotIDs(config.RobotUserIDs, online)
|
||||
missing := activeTarget - len(activeRobots)
|
||||
if missing > 0 {
|
||||
for _, userID := range robotRoomFillCandidates(config, online, missing) {
|
||||
// active 机器人房从持久化配置恢复时,旧进程可能已经把机器人 stale 成 left;
|
||||
// 这里只补齐后台配置的活跃人数,不再把整个候选池一次性塞回房间。
|
||||
if err := s.joinRobotRoomUser(roomCtx, config, userID, 0, fmt.Sprintf("runtime-join:%d:%d", userID, time.Now().UTC().UnixNano())); err != nil {
|
||||
return err
|
||||
}
|
||||
online[userID] = true
|
||||
activeRobots = append(activeRobots, userID)
|
||||
}
|
||||
}
|
||||
|
||||
snapshot, err = s.currentSnapshot(roomCtx, config.RoomID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
seated := make(map[int64]bool, len(config.RobotUserIDs))
|
||||
occupiedSeats := make(map[int32]bool, len(snapshot.GetMicSeats()))
|
||||
for _, seat := range snapshot.GetMicSeats() {
|
||||
userID := seat.GetUserId()
|
||||
if userID > 0 {
|
||||
seated[userID] = true
|
||||
occupiedSeats[seat.GetSeatNo()] = true
|
||||
}
|
||||
}
|
||||
for _, userID := range activeRobots {
|
||||
if userID <= 0 || seated[userID] {
|
||||
continue
|
||||
}
|
||||
seatNo := preferredRobotSeatNo(config, userID)
|
||||
if occupiedSeats[seatNo] {
|
||||
seatNo = firstFreeRobotSeatNo(snapshot.GetMicSeats(), activeTarget)
|
||||
if seatNo <= 0 {
|
||||
logx.Warn(roomCtx, "robot_room_runtime_mic_restore_skipped", slog.String("room_id", config.RoomID), slog.Int64("robot_user_id", userID), slog.String("reason", "no_free_seat"))
|
||||
continue
|
||||
}
|
||||
}
|
||||
// 虚拟麦位只服务机器人房展示;若并发恢复导致机器人已上麦,Conflict 可视为达成目标。
|
||||
if _, err := s.RobotVirtualMicUp(roomCtx, RobotMicUpInput{
|
||||
Meta: robotRoomCommandMeta(config, config.OwnerRobotUserID, fmt.Sprintf("runtime-mic:%d:%d", userID, time.Now().UTC().UnixNano())),
|
||||
TargetUserID: userID,
|
||||
SeatNo: seatNo,
|
||||
}); err != nil {
|
||||
if xerr.CodeOf(err) == xerr.Conflict && strings.Contains(xerr.MessageOf(err), "already on seat") {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
occupiedSeats[seatNo] = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) runRobotRoomRuntime(ctx context.Context, config RobotRoomConfig) {
|
||||
activity := newRobotRoomActivity(config.RobotUserIDs)
|
||||
if snapshot, err := s.currentSnapshot(appcode.WithContext(ctx, config.AppCode), config.RoomID); err == nil {
|
||||
for _, user := range snapshot.GetOnlineUsers() {
|
||||
if robotRoomHasUser(config.RobotUserIDs, user.GetUserId()) {
|
||||
activity.markActive(user.GetUserId())
|
||||
}
|
||||
}
|
||||
}
|
||||
giftSlots := make(chan struct{}, robotRoomMaxGiftSenders(config))
|
||||
for _, senderID := range config.RobotUserIDs {
|
||||
senderID := senderID
|
||||
go s.runRobotNormalGiftLoop(ctx, config, senderID)
|
||||
go s.runRobotLuckyGiftLoop(ctx, config, senderID)
|
||||
go s.runRobotPresenceLoop(ctx, config, activity, senderID)
|
||||
go s.runRobotNormalGiftLoop(ctx, config, activity, giftSlots, senderID)
|
||||
go s.runRobotLuckyGiftLoop(ctx, config, activity, giftSlots, senderID)
|
||||
}
|
||||
<-ctx.Done()
|
||||
}
|
||||
|
||||
func (s *Service) runRobotNormalGiftLoop(ctx context.Context, config RobotRoomConfig, senderID int64) {
|
||||
func (s *Service) runRobotPresenceLoop(ctx context.Context, config RobotRoomConfig, activity *robotRoomActivity, userID int64) {
|
||||
if userID <= 0 {
|
||||
return
|
||||
}
|
||||
rng := rand.New(rand.NewSource(time.Now().UnixNano() + userID*31))
|
||||
for {
|
||||
if !activity.isActive(userID) {
|
||||
if !waitRobotRuntimeDelay(ctx, time.Duration(200+rng.Intn(600))*time.Millisecond) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
stay := time.Duration(randomInt64Range(rng, config.GiftRule.RobotStayMinMS, config.GiftRule.RobotStayMaxMS)) * time.Millisecond
|
||||
if stay <= 0 {
|
||||
stay = time.Duration(defaultRobotStayMinMS) * time.Millisecond
|
||||
}
|
||||
if !waitRobotRuntimeDelay(ctx, stay) {
|
||||
return
|
||||
}
|
||||
if !activity.markInactive(userID) {
|
||||
continue
|
||||
}
|
||||
seatNo := s.robotRoomSeatNo(ctx, config, userID)
|
||||
if err := s.leaveRobotRoomUser(ctx, config, userID); err != nil {
|
||||
logx.Warn(ctx, "robot_room_leave_failed", slog.String("room_id", config.RoomID), slog.Int64("robot_user_id", userID), slog.String("error", err.Error()))
|
||||
activity.markActive(userID)
|
||||
continue
|
||||
}
|
||||
delay := time.Duration(randomInt64Range(rng, config.GiftRule.RobotReplaceMinMS, config.GiftRule.RobotReplaceMaxMS)) * time.Millisecond
|
||||
if !waitRobotRuntimeDelay(ctx, delay) {
|
||||
return
|
||||
}
|
||||
replacementID := activity.pickReplacement(rng, userID)
|
||||
if replacementID <= 0 {
|
||||
replacementID = userID
|
||||
}
|
||||
if err := s.joinRobotRoomUser(ctx, config, replacementID, seatNo, fmt.Sprintf("replace:%d:%d", replacementID, time.Now().UTC().UnixNano())); err != nil {
|
||||
logx.Warn(ctx, "robot_room_replace_join_failed", slog.String("room_id", config.RoomID), slog.Int64("leaving_user_id", userID), slog.Int64("replacement_user_id", replacementID), slog.String("error", err.Error()))
|
||||
if restoreErr := s.joinRobotRoomUser(ctx, config, userID, seatNo, fmt.Sprintf("restore:%d:%d", userID, time.Now().UTC().UnixNano())); restoreErr != nil {
|
||||
logx.Warn(ctx, "robot_room_replace_restore_failed", slog.String("room_id", config.RoomID), slog.Int64("robot_user_id", userID), slog.String("error", restoreErr.Error()))
|
||||
continue
|
||||
}
|
||||
activity.markActive(userID)
|
||||
continue
|
||||
}
|
||||
activity.markActive(replacementID)
|
||||
logx.Info(ctx, "robot_room_replaced_user",
|
||||
slog.String("room_id", config.RoomID),
|
||||
slog.Int64("left_robot_user_id", userID),
|
||||
slog.Int64("joined_robot_user_id", replacementID),
|
||||
slog.Int64("stay_ms", stay.Milliseconds()),
|
||||
slog.Int64("replace_delay_ms", delay.Milliseconds()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) runRobotNormalGiftLoop(ctx context.Context, config RobotRoomConfig, activity *robotRoomActivity, giftSlots chan struct{}, senderID int64) {
|
||||
interval := time.Duration(config.GiftRule.NormalGiftIntervalMS) * time.Millisecond
|
||||
if interval <= 0 || len(config.GiftRule.GiftIDs) == 0 {
|
||||
return
|
||||
@ -324,33 +530,46 @@ func (s *Service) runRobotNormalGiftLoop(ctx context.Context, config RobotRoomCo
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-timer.C:
|
||||
targetID := randomRobotTarget(rng, config.RobotUserIDs, senderID)
|
||||
if !activity.isActive(senderID) {
|
||||
timer.Reset(interval)
|
||||
continue
|
||||
}
|
||||
targetID := randomRobotTarget(rng, activity.activeIDs(), senderID)
|
||||
giftID := randomString(rng, config.GiftRule.GiftIDs)
|
||||
if targetID > 0 && giftID != "" {
|
||||
s.sendRobotGiftBestEffort(ctx, config, senderID, targetID, giftID, "", "normal")
|
||||
s.sendRobotGiftBestEffort(ctx, config, activity, giftSlots, senderID, targetID, giftID, "", "normal")
|
||||
}
|
||||
timer.Reset(interval)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) runRobotLuckyGiftLoop(ctx context.Context, config RobotRoomConfig, senderID int64) {
|
||||
func (s *Service) runRobotLuckyGiftLoop(ctx context.Context, config RobotRoomConfig, activity *robotRoomActivity, giftSlots chan struct{}, senderID int64) {
|
||||
if len(config.GiftRule.LuckyGiftIDs) == 0 || config.GiftRule.LuckyComboMax <= 0 {
|
||||
return
|
||||
}
|
||||
comboMin := clampRobotLuckyCombo(config.GiftRule.LuckyComboMin)
|
||||
comboMax := clampRobotLuckyCombo(config.GiftRule.LuckyComboMax)
|
||||
if comboMin <= 0 || comboMax < comboMin {
|
||||
return
|
||||
}
|
||||
rng := rand.New(rand.NewSource(time.Now().UnixNano() + senderID*17))
|
||||
for {
|
||||
combo := randomInt64Range(rng, config.GiftRule.LuckyComboMin, config.GiftRule.LuckyComboMax)
|
||||
if !activity.isActive(senderID) {
|
||||
if !waitRobotRuntimeDelay(ctx, time.Duration(300+rng.Intn(700))*time.Millisecond) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
combo := randomInt64Range(rng, comboMin, comboMax)
|
||||
for i := int64(0); i < combo; i++ {
|
||||
giftID := randomString(rng, config.GiftRule.LuckyGiftIDs)
|
||||
for _, targetID := range config.RobotUserIDs {
|
||||
if targetID == senderID {
|
||||
continue
|
||||
}
|
||||
if err := ctx.Err(); err != nil {
|
||||
return
|
||||
}
|
||||
s.sendRobotGiftBestEffort(ctx, config, senderID, targetID, giftID, robotRoomLuckyPoolID, "lucky")
|
||||
targetID := randomRobotTarget(rng, activity.activeIDs(), senderID)
|
||||
if targetID > 0 && giftID != "" {
|
||||
s.sendRobotGiftBestEffort(ctx, config, activity, giftSlots, senderID, targetID, giftID, robotRoomLuckyPoolID, "lucky")
|
||||
}
|
||||
if !waitRobotGiftPace(ctx, rng) {
|
||||
return
|
||||
}
|
||||
}
|
||||
pause := time.Duration(randomInt64Range(rng, config.GiftRule.LuckyPauseMinMS, config.GiftRule.LuckyPauseMaxMS)) * time.Millisecond
|
||||
@ -367,7 +586,16 @@ func (s *Service) runRobotLuckyGiftLoop(ctx context.Context, config RobotRoomCon
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) sendRobotGiftBestEffort(ctx context.Context, config RobotRoomConfig, senderID int64, targetID int64, giftID string, poolID string, kind string) {
|
||||
func (s *Service) sendRobotGiftBestEffort(ctx context.Context, config RobotRoomConfig, activity *robotRoomActivity, giftSlots chan struct{}, senderID int64, targetID int64, giftID string, poolID string, kind string) {
|
||||
if !activity.isActive(senderID) || !activity.isActive(targetID) {
|
||||
return
|
||||
}
|
||||
select {
|
||||
case giftSlots <- struct{}{}:
|
||||
defer func() { <-giftSlots }()
|
||||
default:
|
||||
return
|
||||
}
|
||||
_, err := s.RobotSendGift(ctx, RobotSendGiftInput{
|
||||
Meta: robotRoomCommandMeta(config, senderID, fmt.Sprintf("gift:%s:%d:%d", kind, targetID, time.Now().UTC().UnixNano())),
|
||||
TargetUserID: targetID,
|
||||
@ -383,6 +611,56 @@ func (s *Service) sendRobotGiftBestEffort(ctx context.Context, config RobotRoomC
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) leaveRobotRoomUser(ctx context.Context, config RobotRoomConfig, userID int64) error {
|
||||
_, err := s.LeaveRoom(ctx, &roomv1.LeaveRoomRequest{
|
||||
Meta: robotRoomCommandMeta(config, userID, fmt.Sprintf("leave:%d:%d", userID, time.Now().UTC().UnixNano())),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Service) joinRobotRoomUser(ctx context.Context, config RobotRoomConfig, userID int64, seatNo int32, suffix string) error {
|
||||
role := "audience"
|
||||
if userID == config.OwnerRobotUserID {
|
||||
role = "owner"
|
||||
}
|
||||
if _, err := s.JoinRoom(ctx, &roomv1.JoinRoomRequest{
|
||||
Meta: robotRoomCommandMeta(config, userID, suffix),
|
||||
Role: role,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if seatNo <= 0 {
|
||||
seatNo = preferredRobotSeatNo(config, userID)
|
||||
}
|
||||
if seatNo <= 0 {
|
||||
seatNo = 1
|
||||
}
|
||||
if _, err := s.RobotVirtualMicUp(ctx, RobotMicUpInput{
|
||||
Meta: robotRoomCommandMeta(config, config.OwnerRobotUserID, fmt.Sprintf("mic:%d:%d", userID, time.Now().UTC().UnixNano())),
|
||||
TargetUserID: userID,
|
||||
SeatNo: seatNo,
|
||||
}); err != nil {
|
||||
if xerr.CodeOf(err) == xerr.Conflict && strings.Contains(xerr.MessageOf(err), "already on seat") {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) robotRoomSeatNo(ctx context.Context, config RobotRoomConfig, userID int64) int32 {
|
||||
snapshot, err := s.currentSnapshot(appcode.WithContext(ctx, config.AppCode), config.RoomID)
|
||||
if err != nil {
|
||||
return preferredRobotSeatNo(config, userID)
|
||||
}
|
||||
for _, seat := range snapshot.GetMicSeats() {
|
||||
if seat.GetUserId() == userID {
|
||||
return seat.GetSeatNo()
|
||||
}
|
||||
}
|
||||
return firstFreeRobotSeatNo(snapshot.GetMicSeats(), robotRoomActiveTarget(config))
|
||||
}
|
||||
|
||||
func robotRoomCommandMeta(config RobotRoomConfig, actorUserID int64, suffix string) *roomv1.RequestMeta {
|
||||
commandID := fmt.Sprintf("robot-room:%s:%s", config.RoomID, strings.TrimSpace(suffix))
|
||||
if len(commandID) > 128 {
|
||||
@ -406,11 +684,17 @@ func normalizeRobotRoomGiftRule(input *roomv1.AdminRobotRoomGiftRule) (RobotRoom
|
||||
GiftIDs: normalizeStringSet(input.GetGiftIds()),
|
||||
LuckyGiftIDs: normalizeStringSet(input.GetLuckyGiftIds()),
|
||||
NormalGiftIntervalMS: input.GetNormalGiftIntervalMs(),
|
||||
LuckyComboMin: input.GetLuckyComboMin(),
|
||||
LuckyComboMax: input.GetLuckyComboMax(),
|
||||
LuckyComboMin: clampRobotLuckyCombo(input.GetLuckyComboMin()),
|
||||
LuckyComboMax: clampRobotLuckyCombo(input.GetLuckyComboMax()),
|
||||
LuckyPauseMinMS: input.GetLuckyPauseMinMs(),
|
||||
LuckyPauseMaxMS: input.GetLuckyPauseMaxMs(),
|
||||
RobotStayMinMS: input.GetRobotStayMinMs(),
|
||||
RobotStayMaxMS: input.GetRobotStayMaxMs(),
|
||||
RobotReplaceMinMS: input.GetRobotReplaceMinMs(),
|
||||
RobotReplaceMaxMS: input.GetRobotReplaceMaxMs(),
|
||||
MaxGiftSenders: input.GetMaxGiftSenders(),
|
||||
}
|
||||
rule = withRobotRoomGiftRuleDefaults(rule)
|
||||
if len(rule.GiftIDs) == 0 {
|
||||
return RobotRoomGiftRule{}, xerr.New(xerr.InvalidArgument, "gift_ids is required")
|
||||
}
|
||||
@ -426,9 +710,49 @@ func normalizeRobotRoomGiftRule(input *roomv1.AdminRobotRoomGiftRule) (RobotRoom
|
||||
if rule.LuckyPauseMinMS <= 0 || rule.LuckyPauseMaxMS < rule.LuckyPauseMinMS {
|
||||
return RobotRoomGiftRule{}, xerr.New(xerr.InvalidArgument, "lucky pause range is invalid")
|
||||
}
|
||||
if rule.RobotStayMinMS <= 0 || rule.RobotStayMaxMS < rule.RobotStayMinMS {
|
||||
return RobotRoomGiftRule{}, xerr.New(xerr.InvalidArgument, "robot stay range is invalid")
|
||||
}
|
||||
if rule.RobotReplaceMinMS < 0 || rule.RobotReplaceMaxMS < rule.RobotReplaceMinMS {
|
||||
return RobotRoomGiftRule{}, xerr.New(xerr.InvalidArgument, "robot replace range is invalid")
|
||||
}
|
||||
if rule.MaxGiftSenders <= 0 {
|
||||
return RobotRoomGiftRule{}, xerr.New(xerr.InvalidArgument, "max_gift_senders is required")
|
||||
}
|
||||
return rule, nil
|
||||
}
|
||||
|
||||
func withRobotRoomGiftRuleDefaults(rule RobotRoomGiftRule) RobotRoomGiftRule {
|
||||
if rule.RobotStayMinMS <= 0 && rule.RobotStayMaxMS <= 0 {
|
||||
rule.RobotStayMinMS = defaultRobotStayMinMS
|
||||
rule.RobotStayMaxMS = defaultRobotStayMaxMS
|
||||
}
|
||||
if rule.RobotReplaceMinMS == 0 && rule.RobotReplaceMaxMS == 0 {
|
||||
rule.RobotReplaceMinMS = defaultRobotReplaceMinMS
|
||||
rule.RobotReplaceMaxMS = defaultRobotReplaceMaxMS
|
||||
}
|
||||
if rule.MaxGiftSenders <= 0 {
|
||||
rule.MaxGiftSenders = defaultMaxGiftSenders
|
||||
}
|
||||
return rule
|
||||
}
|
||||
|
||||
// WithRobotRoomGiftRuleStorageDefaults 让 repository 恢复历史行时复用运行时默认值;
|
||||
// 默认值只补空字段,不放宽 normalizeRobotRoomGiftRule 对显式非法范围的校验。
|
||||
func WithRobotRoomGiftRuleStorageDefaults(rule RobotRoomGiftRule) RobotRoomGiftRule {
|
||||
return withRobotRoomGiftRuleDefaults(rule)
|
||||
}
|
||||
|
||||
func clampRobotLuckyCombo(value int64) int64 {
|
||||
if value <= 0 {
|
||||
return value
|
||||
}
|
||||
if value > maxRobotLuckyComboPerCycle {
|
||||
return maxRobotLuckyComboPerCycle
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func robotRoomConfigToProto(config RobotRoomConfig) *roomv1.AdminRobotRoom {
|
||||
return &roomv1.AdminRobotRoom{
|
||||
AppCode: config.AppCode,
|
||||
@ -440,6 +764,8 @@ func robotRoomConfigToProto(config RobotRoomConfig) *roomv1.AdminRobotRoom {
|
||||
Status: config.Status,
|
||||
OwnerRobotUserId: config.OwnerRobotUserID,
|
||||
RobotUserIds: append([]int64(nil), config.RobotUserIDs...),
|
||||
ActiveRobotCount: config.ActiveRobotCount,
|
||||
SeatCount: config.SeatCount,
|
||||
GiftRule: &roomv1.AdminRobotRoomGiftRule{
|
||||
GiftIds: append([]string(nil), config.GiftRule.GiftIDs...),
|
||||
LuckyGiftIds: append([]string(nil), config.GiftRule.LuckyGiftIDs...),
|
||||
@ -448,6 +774,11 @@ func robotRoomConfigToProto(config RobotRoomConfig) *roomv1.AdminRobotRoom {
|
||||
LuckyComboMax: config.GiftRule.LuckyComboMax,
|
||||
LuckyPauseMinMs: config.GiftRule.LuckyPauseMinMS,
|
||||
LuckyPauseMaxMs: config.GiftRule.LuckyPauseMaxMS,
|
||||
RobotStayMinMs: config.GiftRule.RobotStayMinMS,
|
||||
RobotStayMaxMs: config.GiftRule.RobotStayMaxMS,
|
||||
RobotReplaceMinMs: config.GiftRule.RobotReplaceMinMS,
|
||||
RobotReplaceMaxMs: config.GiftRule.RobotReplaceMaxMS,
|
||||
MaxGiftSenders: config.GiftRule.MaxGiftSenders,
|
||||
},
|
||||
CreatedByAdminId: config.CreatedByAdminID,
|
||||
CreatedAtMs: config.CreatedAtMS,
|
||||
@ -470,6 +801,17 @@ func normalizeRobotCountRange(minCount int32, maxCount int32) (int, int) {
|
||||
return minValue, maxValue
|
||||
}
|
||||
|
||||
func normalizeRobotRoomSeatCount(seatCount int32) int32 {
|
||||
switch seatCount {
|
||||
case 0:
|
||||
return defaultRobotRoomSeatCount
|
||||
case 10, 15, 20:
|
||||
return seatCount
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func selectRobotUsers(rng *rand.Rand, ownerID int64, available []int64, count int) []int64 {
|
||||
others := make([]int64, 0, len(available))
|
||||
for _, userID := range available {
|
||||
@ -489,6 +831,258 @@ func selectRobotUsers(rng *rand.Rand, ownerID int64, available []int64, count in
|
||||
return selected
|
||||
}
|
||||
|
||||
func robotRoomInitialActiveIDs(config RobotRoomConfig) []int64 {
|
||||
target := robotRoomActiveTarget(config)
|
||||
if target <= 0 {
|
||||
return nil
|
||||
}
|
||||
if target > len(config.RobotUserIDs) {
|
||||
target = len(config.RobotUserIDs)
|
||||
}
|
||||
active := make([]int64, 0, target)
|
||||
if config.OwnerRobotUserID > 0 && robotRoomHasUser(config.RobotUserIDs, config.OwnerRobotUserID) {
|
||||
active = append(active, config.OwnerRobotUserID)
|
||||
}
|
||||
for _, userID := range config.RobotUserIDs {
|
||||
if len(active) >= target {
|
||||
break
|
||||
}
|
||||
if userID <= 0 || userID == config.OwnerRobotUserID {
|
||||
continue
|
||||
}
|
||||
active = append(active, userID)
|
||||
}
|
||||
return active
|
||||
}
|
||||
|
||||
func robotRoomActiveTarget(config RobotRoomConfig) int {
|
||||
target := int(config.ActiveRobotCount)
|
||||
if target <= 0 {
|
||||
target = len(config.RobotUserIDs)
|
||||
}
|
||||
if target > len(config.RobotUserIDs) {
|
||||
target = len(config.RobotUserIDs)
|
||||
}
|
||||
if target < 0 {
|
||||
return 0
|
||||
}
|
||||
return target
|
||||
}
|
||||
|
||||
func robotRoomMaxGiftSenders(config RobotRoomConfig) int {
|
||||
maxSenders := int(config.GiftRule.MaxGiftSenders)
|
||||
if maxSenders <= 0 {
|
||||
maxSenders = int(defaultMaxGiftSenders)
|
||||
}
|
||||
if maxSenders > len(config.RobotUserIDs) {
|
||||
maxSenders = len(config.RobotUserIDs)
|
||||
}
|
||||
if maxSenders <= 0 {
|
||||
maxSenders = 1
|
||||
}
|
||||
return maxSenders
|
||||
}
|
||||
|
||||
func robotRoomHasUser(robots []int64, userID int64) bool {
|
||||
for _, robotID := range robots {
|
||||
if robotID == userID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func onlineRobotIDs(robots []int64, online map[int64]bool) []int64 {
|
||||
out := make([]int64, 0, len(robots))
|
||||
for _, userID := range robots {
|
||||
if online[userID] {
|
||||
out = append(out, userID)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func robotRoomFillCandidates(config RobotRoomConfig, online map[int64]bool, limit int) []int64 {
|
||||
if limit <= 0 {
|
||||
return nil
|
||||
}
|
||||
out := make([]int64, 0, limit)
|
||||
if config.OwnerRobotUserID > 0 && !online[config.OwnerRobotUserID] && robotRoomHasUser(config.RobotUserIDs, config.OwnerRobotUserID) {
|
||||
out = append(out, config.OwnerRobotUserID)
|
||||
}
|
||||
for _, userID := range config.RobotUserIDs {
|
||||
if len(out) >= limit {
|
||||
break
|
||||
}
|
||||
if userID <= 0 || userID == config.OwnerRobotUserID || online[userID] {
|
||||
continue
|
||||
}
|
||||
out = append(out, userID)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func preferredRobotSeatNo(config RobotRoomConfig, userID int64) int32 {
|
||||
for index, robotID := range config.RobotUserIDs {
|
||||
if robotID == userID {
|
||||
return int32(index + 1)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func firstFreeRobotSeatNo(seats []*roomv1.SeatState, activeTarget int) int32 {
|
||||
occupied := make(map[int32]bool, len(seats))
|
||||
maxSeatNo := int32(0)
|
||||
for _, seat := range seats {
|
||||
if seat.GetSeatNo() > maxSeatNo {
|
||||
maxSeatNo = seat.GetSeatNo()
|
||||
}
|
||||
if seat.GetUserId() > 0 {
|
||||
occupied[seat.GetSeatNo()] = true
|
||||
}
|
||||
}
|
||||
if maxSeatNo <= 0 {
|
||||
maxSeatNo = int32(max(10, activeTarget))
|
||||
}
|
||||
for seatNo := int32(1); seatNo <= maxSeatNo; seatNo++ {
|
||||
if !occupied[seatNo] {
|
||||
return seatNo
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func waitRobotRuntimeDelay(ctx context.Context, delay time.Duration) bool {
|
||||
if delay <= 0 {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
timer := time.NewTimer(delay)
|
||||
defer timer.Stop()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return false
|
||||
case <-timer.C:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
type robotRoomActivity struct {
|
||||
mu sync.Mutex
|
||||
active map[int64]bool
|
||||
giftSenders map[int64]bool
|
||||
pool []int64
|
||||
}
|
||||
|
||||
func newRobotRoomActivity(pool []int64) *robotRoomActivity {
|
||||
return &robotRoomActivity{
|
||||
active: make(map[int64]bool, len(pool)),
|
||||
giftSenders: make(map[int64]bool),
|
||||
pool: append([]int64(nil), pool...),
|
||||
}
|
||||
}
|
||||
|
||||
func (a *robotRoomActivity) isActive(userID int64) bool {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
return a.active[userID]
|
||||
}
|
||||
|
||||
func (a *robotRoomActivity) markActive(userID int64) {
|
||||
if userID <= 0 {
|
||||
return
|
||||
}
|
||||
a.mu.Lock()
|
||||
a.active[userID] = true
|
||||
a.mu.Unlock()
|
||||
}
|
||||
|
||||
func (a *robotRoomActivity) markInactive(userID int64) bool {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
if !a.active[userID] {
|
||||
return false
|
||||
}
|
||||
delete(a.active, userID)
|
||||
delete(a.giftSenders, userID)
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *robotRoomActivity) isGiftSender(userID int64) bool {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
return a.giftSenders[userID]
|
||||
}
|
||||
|
||||
func (a *robotRoomActivity) markGiftSender(userID int64) {
|
||||
if userID <= 0 {
|
||||
return
|
||||
}
|
||||
a.mu.Lock()
|
||||
if a.active[userID] {
|
||||
a.giftSenders[userID] = true
|
||||
}
|
||||
a.mu.Unlock()
|
||||
}
|
||||
|
||||
func (a *robotRoomActivity) markGiftSenderWithinLimit(userID int64, maxSenders int) bool {
|
||||
if userID <= 0 || maxSenders <= 0 {
|
||||
return false
|
||||
}
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
if !a.active[userID] || len(a.giftSenders) >= maxSenders {
|
||||
return false
|
||||
}
|
||||
a.giftSenders[userID] = true
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *robotRoomActivity) giftSenderCount() int {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
return len(a.giftSenders)
|
||||
}
|
||||
|
||||
func (a *robotRoomActivity) activeIDs() []int64 {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
out := make([]int64, 0, len(a.active))
|
||||
for userID := range a.active {
|
||||
out = append(out, userID)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (a *robotRoomActivity) pickReplacement(rng *rand.Rand, departingUserID int64) int64 {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
candidates := make([]int64, 0, len(a.pool))
|
||||
fallback := make([]int64, 0, 1)
|
||||
for _, userID := range a.pool {
|
||||
if a.active[userID] {
|
||||
continue
|
||||
}
|
||||
if userID == departingUserID {
|
||||
fallback = append(fallback, userID)
|
||||
continue
|
||||
}
|
||||
candidates = append(candidates, userID)
|
||||
}
|
||||
if len(candidates) == 0 {
|
||||
candidates = fallback
|
||||
}
|
||||
if len(candidates) == 0 {
|
||||
return 0
|
||||
}
|
||||
return candidates[rng.Intn(len(candidates))]
|
||||
}
|
||||
|
||||
func normalizeRobotRoomStatus(status string) string {
|
||||
switch strings.TrimSpace(status) {
|
||||
case robotRoomStatusActive:
|
||||
@ -564,3 +1158,15 @@ func randomJitter(interval time.Duration, rng *rand.Rand) time.Duration {
|
||||
}
|
||||
return time.Duration(rng.Int63n(int64(interval))) + time.Second
|
||||
}
|
||||
|
||||
func waitRobotGiftPace(ctx context.Context, rng *rand.Rand) bool {
|
||||
delay := time.Duration(300+rng.Intn(500)) * time.Millisecond
|
||||
timer := time.NewTimer(delay)
|
||||
defer timer.Stop()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return false
|
||||
case <-timer.C:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,108 @@
|
||||
package service_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
roomv1 "hyapp.local/api/proto/room/v1"
|
||||
"hyapp/pkg/appcode"
|
||||
"hyapp/services/room-service/internal/integration"
|
||||
roomservice "hyapp/services/room-service/internal/room/service"
|
||||
"hyapp/services/room-service/internal/router"
|
||||
"hyapp/services/room-service/internal/testutil/mysqltest"
|
||||
)
|
||||
|
||||
func TestRobotRoomRuntimeStartRestoresLeftRobots(t *testing.T) {
|
||||
ctx := appcode.WithContext(context.Background(), appcode.Default)
|
||||
repository := mysqltest.NewRepository(t)
|
||||
svc := roomservice.New(roomservice.Config{
|
||||
NodeID: "node-robot-runtime-restore-test",
|
||||
LeaseTTL: 10 * time.Second,
|
||||
RankLimit: 20,
|
||||
SnapshotEveryN: 1,
|
||||
}, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher())
|
||||
|
||||
created, err := svc.AdminCreateRobotRoom(ctx, &roomv1.AdminCreateRobotRoomRequest{
|
||||
Meta: roomservice.NewRequestMeta("", 9001),
|
||||
OwnerRobotUserId: 1001,
|
||||
CandidateRobotUserIds: []int64{1001, 1002},
|
||||
MinRobotCount: 2,
|
||||
MaxRobotCount: 2,
|
||||
RoomName: "Robot Runtime Restore",
|
||||
RoomAvatar: testRoomCoverURL,
|
||||
VisibleRegionId: 686,
|
||||
GiftRule: &roomv1.AdminRobotRoomGiftRule{
|
||||
GiftIds: []string{"normal_gift"},
|
||||
LuckyGiftIds: []string{"lucky_gift"},
|
||||
NormalGiftIntervalMs: 10000,
|
||||
LuckyComboMin: 1,
|
||||
LuckyComboMax: 1,
|
||||
LuckyPauseMinMs: 5000,
|
||||
LuckyPauseMaxMs: 5000,
|
||||
},
|
||||
AdminId: 9001,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("create robot room failed: %v", err)
|
||||
}
|
||||
roomID := created.GetRoom().GetRoomId()
|
||||
robotUserIDs := created.GetRoom().GetRobotUserIds()
|
||||
for _, userID := range robotUserIDs {
|
||||
if _, err := svc.LeaveRoom(ctx, &roomv1.LeaveRoomRequest{
|
||||
Meta: roomservice.NewRequestMeta(roomID, userID),
|
||||
}); err != nil {
|
||||
t.Fatalf("leave robot %d failed: %v", userID, err)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := svc.AdminSetRobotRoomStatus(ctx, &roomv1.AdminSetRobotRoomStatusRequest{
|
||||
Meta: roomservice.NewRequestMeta(roomID, 9001),
|
||||
Status: "stopped",
|
||||
AdminId: 9001,
|
||||
}); err != nil {
|
||||
t.Fatalf("stop robot room failed: %v", err)
|
||||
}
|
||||
if _, err := svc.AdminSetRobotRoomStatus(ctx, &roomv1.AdminSetRobotRoomStatusRequest{
|
||||
Meta: roomservice.NewRequestMeta(roomID, 9001),
|
||||
Status: "active",
|
||||
AdminId: 9001,
|
||||
}); err != nil {
|
||||
t.Fatalf("restart robot room failed: %v", err)
|
||||
}
|
||||
|
||||
snapshot, err := svc.GetRoomSnapshot(ctx, &roomv1.GetRoomSnapshotRequest{
|
||||
Meta: &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID},
|
||||
RoomId: roomID,
|
||||
ViewerUserId: robotUserIDs[0],
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("snapshot after runtime restore failed: %v", err)
|
||||
}
|
||||
for _, userID := range robotUserIDs {
|
||||
if !snapshotContainsUser(snapshot.GetRoom(), userID) {
|
||||
t.Fatalf("robot %d should be online after runtime restart", userID)
|
||||
}
|
||||
if !snapshotContainsSeatUser(snapshot.GetRoom(), userID) {
|
||||
t.Fatalf("robot %d should be on virtual mic after runtime restart", userID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func snapshotContainsUser(snapshot *roomv1.RoomSnapshot, userID int64) bool {
|
||||
for _, user := range snapshot.GetOnlineUsers() {
|
||||
if user.GetUserId() == userID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func snapshotContainsSeatUser(snapshot *roomv1.RoomSnapshot, userID int64) bool {
|
||||
for _, seat := range snapshot.GetMicSeats() {
|
||||
if seat.GetUserId() == userID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -0,0 +1,133 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
roomv1 "hyapp.local/api/proto/room/v1"
|
||||
"hyapp/services/room-service/internal/room/command"
|
||||
"hyapp/services/room-service/internal/room/state"
|
||||
)
|
||||
|
||||
func TestRobotRoomRuntimeClearUsesToken(t *testing.T) {
|
||||
cancelled := false
|
||||
svc := &Service{
|
||||
robotRuntimes: map[string]robotRoomRuntime{
|
||||
"robot-runtime-token-test": {
|
||||
cancel: func() { cancelled = true },
|
||||
token: "new-token",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
svc.clearRobotRoomRuntime("robot-runtime-token-test", "old-token")
|
||||
if len(svc.robotRuntimes) != 1 {
|
||||
t.Fatalf("old runtime token must not clear newer runtime")
|
||||
}
|
||||
|
||||
svc.clearRobotRoomRuntime("robot-runtime-token-test", "new-token")
|
||||
if len(svc.robotRuntimes) != 0 {
|
||||
t.Fatalf("matching runtime token should clear runtime, got %d", len(svc.robotRuntimes))
|
||||
}
|
||||
if cancelled {
|
||||
t.Fatalf("clearRobotRoomRuntime must only remove map entry, not invoke cancel")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRobotRoomStalePresenceKeepsConfiguredRobots(t *testing.T) {
|
||||
current := &state.RoomState{
|
||||
RoomExt: map[string]string{
|
||||
roomExtRobotRoomKey: "true",
|
||||
roomExtRobotUserIDsKey: "1001,1002",
|
||||
},
|
||||
OnlineUsers: map[int64]*state.RoomUserState{
|
||||
1001: {UserID: 1001, LastSeenAtMS: 10},
|
||||
1002: {UserID: 1002, LastSeenAtMS: 10},
|
||||
2001: {UserID: 2001, LastSeenAtMS: 10},
|
||||
2002: {UserID: 2002, LastSeenAtMS: 200},
|
||||
},
|
||||
}
|
||||
|
||||
stale := stalePresenceUserIDs(current, 100)
|
||||
if len(stale) != 1 || stale[0] != 2001 {
|
||||
t.Fatalf("stale sweep should keep robot users and evict only stale real users, got %+v", stale)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReplayRoomHeartbeatAfterLeaveIsIgnored(t *testing.T) {
|
||||
current := &state.RoomState{
|
||||
OnlineUsers: map[int64]*state.RoomUserState{},
|
||||
}
|
||||
|
||||
err := replay(current, &command.RoomHeartbeat{
|
||||
Base: command.Base{
|
||||
ActorID: 123456,
|
||||
Room: "robot-stale-heartbeat",
|
||||
SentAtMS: 1781675912713,
|
||||
},
|
||||
}, 1781675913212)
|
||||
if err != nil {
|
||||
t.Fatalf("stale heartbeat after leave must not break recovery: %v", err)
|
||||
}
|
||||
if len(current.OnlineUsers) != 0 {
|
||||
t.Fatalf("stale heartbeat must not recreate presence: %+v", current.OnlineUsers)
|
||||
}
|
||||
if current.Version != 0 {
|
||||
t.Fatalf("ignored heartbeat must not advance room version, got %d", current.Version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeRobotRoomGiftRuleClampsLuckyCombo(t *testing.T) {
|
||||
rule, err := normalizeRobotRoomGiftRule(&roomv1.AdminRobotRoomGiftRule{
|
||||
GiftIds: []string{"normal-gift"},
|
||||
LuckyGiftIds: []string{"lucky-gift"},
|
||||
NormalGiftIntervalMs: 10000,
|
||||
LuckyComboMin: 100,
|
||||
LuckyComboMax: 10000,
|
||||
LuckyPauseMinMs: 5000,
|
||||
LuckyPauseMaxMs: 20000,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("normalize robot room gift rule failed: %v", err)
|
||||
}
|
||||
if rule.LuckyComboMin != maxRobotLuckyComboPerCycle || rule.LuckyComboMax != maxRobotLuckyComboPerCycle {
|
||||
t.Fatalf("lucky combo should be clamped to %d, got %d-%d", maxRobotLuckyComboPerCycle, rule.LuckyComboMin, rule.LuckyComboMax)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeRobotRoomGiftRuleAppliesBehaviorDefaults(t *testing.T) {
|
||||
rule, err := normalizeRobotRoomGiftRule(&roomv1.AdminRobotRoomGiftRule{
|
||||
GiftIds: []string{"normal-gift"},
|
||||
LuckyGiftIds: []string{"lucky-gift"},
|
||||
NormalGiftIntervalMs: 10000,
|
||||
LuckyComboMin: 1,
|
||||
LuckyComboMax: 1,
|
||||
LuckyPauseMinMs: 5000,
|
||||
LuckyPauseMaxMs: 20000,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("normalize robot room gift rule failed: %v", err)
|
||||
}
|
||||
if rule.RobotStayMinMS != defaultRobotStayMinMS || rule.RobotStayMaxMS != defaultRobotStayMaxMS {
|
||||
t.Fatalf("robot stay defaults mismatch: %d-%d", rule.RobotStayMinMS, rule.RobotStayMaxMS)
|
||||
}
|
||||
if rule.RobotReplaceMinMS != defaultRobotReplaceMinMS || rule.RobotReplaceMaxMS != defaultRobotReplaceMaxMS {
|
||||
t.Fatalf("robot replace defaults mismatch: %d-%d", rule.RobotReplaceMinMS, rule.RobotReplaceMaxMS)
|
||||
}
|
||||
if rule.MaxGiftSenders != defaultMaxGiftSenders {
|
||||
t.Fatalf("max gift senders default mismatch: %d", rule.MaxGiftSenders)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRobotRoomActivityPrefersOtherReplacement(t *testing.T) {
|
||||
activity := newRobotRoomActivity([]int64{1001, 1002, 1003})
|
||||
activity.markActive(1001)
|
||||
activity.markActive(1002)
|
||||
if !activity.markInactive(1002) {
|
||||
t.Fatalf("expected active robot to become inactive")
|
||||
}
|
||||
rng := rand.New(rand.NewSource(1))
|
||||
if got := activity.pickReplacement(rng, 1002); got != 1003 {
|
||||
t.Fatalf("replacement should prefer another offline robot, got %d", got)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,135 @@
|
||||
package service_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
roomv1 "hyapp.local/api/proto/room/v1"
|
||||
"hyapp/pkg/appcode"
|
||||
"hyapp/services/room-service/internal/integration"
|
||||
roomservice "hyapp/services/room-service/internal/room/service"
|
||||
"hyapp/services/room-service/internal/router"
|
||||
"hyapp/services/room-service/internal/testutil/mysqltest"
|
||||
)
|
||||
|
||||
func TestAdminCreateRobotRoomProjectsOwnerRegionAndCountry(t *testing.T) {
|
||||
ctx := appcode.WithContext(context.Background(), appcode.Default)
|
||||
repository := mysqltest.NewRepository(t)
|
||||
svc := roomservice.New(roomservice.Config{
|
||||
NodeID: "node-admin-robot-room-owner-region-country-test",
|
||||
LeaseTTL: 10 * time.Second,
|
||||
RankLimit: 20,
|
||||
SnapshotEveryN: 1,
|
||||
}, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher())
|
||||
|
||||
resp, err := svc.AdminCreateRobotRoom(ctx, &roomv1.AdminCreateRobotRoomRequest{
|
||||
Meta: roomservice.NewRequestMeta("", 9001),
|
||||
OwnerRobotUserId: 325379237278126080,
|
||||
CandidateRobotUserIds: []int64{325379237278126080},
|
||||
MinRobotCount: 1,
|
||||
MaxRobotCount: 1,
|
||||
RoomName: "Robot Owner",
|
||||
RoomAvatar: testRoomCoverURL,
|
||||
VisibleRegionId: 686,
|
||||
OwnerCountryCode: "ae",
|
||||
GiftRule: &roomv1.AdminRobotRoomGiftRule{
|
||||
GiftIds: []string{"84"},
|
||||
LuckyGiftIds: []string{"28"},
|
||||
NormalGiftIntervalMs: 10000,
|
||||
LuckyComboMin: 100,
|
||||
LuckyComboMax: 10000,
|
||||
LuckyPauseMinMs: 5000,
|
||||
LuckyPauseMaxMs: 20000,
|
||||
},
|
||||
AdminId: 9001,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("AdminCreateRobotRoom failed: %v", err)
|
||||
}
|
||||
roomID := resp.GetRoom().GetRoomId()
|
||||
if roomID == "" {
|
||||
t.Fatalf("created robot room id is empty")
|
||||
}
|
||||
|
||||
entries, err := repository.ListRoomListEntries(ctx, roomservice.RoomListQuery{VisibleRegionID: 686, CountryCode: "AE", Tab: "new", Limit: 10})
|
||||
if err != nil {
|
||||
t.Fatalf("list robot room entries failed: %v", err)
|
||||
}
|
||||
if len(entries) != 1 || entries[0].RoomID != roomID || entries[0].VisibleRegionID != 686 || entries[0].OwnerCountryCode != "AE" {
|
||||
t.Fatalf("robot room owner region/country projection mismatch: %+v", entries)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdminCreateRobotRoomUsesCandidatePoolAndActiveCount(t *testing.T) {
|
||||
ctx := appcode.WithContext(context.Background(), appcode.Default)
|
||||
repository := mysqltest.NewRepository(t)
|
||||
svc := roomservice.New(roomservice.Config{
|
||||
NodeID: "node-admin-robot-room-pool-test",
|
||||
LeaseTTL: 10 * time.Second,
|
||||
RankLimit: 20,
|
||||
SnapshotEveryN: 1,
|
||||
}, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher())
|
||||
|
||||
resp, err := svc.AdminCreateRobotRoom(ctx, &roomv1.AdminCreateRobotRoomRequest{
|
||||
Meta: roomservice.NewRequestMeta("", 9001),
|
||||
OwnerRobotUserId: 1001,
|
||||
CandidateRobotUserIds: []int64{1001, 1002, 1003, 1004},
|
||||
MinRobotCount: 2,
|
||||
MaxRobotCount: 2,
|
||||
RoomName: "Robot Pool",
|
||||
RoomAvatar: testRoomCoverURL,
|
||||
VisibleRegionId: 686,
|
||||
OwnerCountryCode: "ae",
|
||||
GiftRule: &roomv1.AdminRobotRoomGiftRule{
|
||||
GiftIds: []string{"84"},
|
||||
LuckyGiftIds: []string{"28"},
|
||||
NormalGiftIntervalMs: 10000,
|
||||
LuckyComboMin: 1,
|
||||
LuckyComboMax: 1,
|
||||
LuckyPauseMinMs: 5000,
|
||||
LuckyPauseMaxMs: 20000,
|
||||
RobotStayMinMs: 180000,
|
||||
RobotStayMaxMs: 600000,
|
||||
RobotReplaceMinMs: 0,
|
||||
RobotReplaceMaxMs: 60000,
|
||||
MaxGiftSenders: 2,
|
||||
},
|
||||
AdminId: 9001,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("AdminCreateRobotRoom failed: %v", err)
|
||||
}
|
||||
roomID := resp.GetRoom().GetRoomId()
|
||||
if got := len(resp.GetRoom().GetRobotUserIds()); got != 4 {
|
||||
t.Fatalf("robot room should persist full candidate pool for replacement, got %d", got)
|
||||
}
|
||||
if resp.GetRoom().GetGiftRule().GetMaxGiftSenders() != 2 {
|
||||
t.Fatalf("max gift senders should round-trip through room config")
|
||||
}
|
||||
|
||||
snapshot, err := svc.GetRoomSnapshot(ctx, &roomv1.GetRoomSnapshotRequest{
|
||||
Meta: &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID},
|
||||
RoomId: roomID,
|
||||
ViewerUserId: 1001,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("snapshot failed: %v", err)
|
||||
}
|
||||
if got := len(snapshot.GetRoom().GetOnlineUsers()); got != 2 {
|
||||
t.Fatalf("robot room should only bootstrap active robot count online, got %d", got)
|
||||
}
|
||||
if got := occupiedSeatUserCount(snapshot.GetRoom()); got != 2 {
|
||||
t.Fatalf("robot room should only put active robots on virtual mic, got %d", got)
|
||||
}
|
||||
}
|
||||
|
||||
func occupiedSeatUserCount(snapshot *roomv1.RoomSnapshot) int {
|
||||
count := 0
|
||||
for _, seat := range snapshot.GetMicSeats() {
|
||||
if seat.GetUserId() > 0 {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
@ -35,6 +35,7 @@ type RobotSendGiftInput struct {
|
||||
RobotUserIDs []int64
|
||||
SyntheticRewardCoins int64
|
||||
SyntheticMultiplierPPM int64
|
||||
RealRoomHeat bool
|
||||
}
|
||||
|
||||
type robotGiftOptions struct {
|
||||
@ -42,6 +43,7 @@ type robotGiftOptions struct {
|
||||
RobotUserIDs []int64
|
||||
SyntheticRewardCoins int64
|
||||
SyntheticMultiplierPPM int64
|
||||
RealRoomHeat bool
|
||||
}
|
||||
|
||||
func (s *Service) RobotSendGift(ctx context.Context, input RobotSendGiftInput) (*roomv1.SendGiftResponse, error) {
|
||||
@ -59,6 +61,7 @@ func (s *Service) RobotSendGift(ctx context.Context, input RobotSendGiftInput) (
|
||||
RobotUserIDs: input.RobotUserIDs,
|
||||
SyntheticRewardCoins: input.SyntheticRewardCoins,
|
||||
SyntheticMultiplierPPM: input.SyntheticMultiplierPPM,
|
||||
RealRoomHeat: input.RealRoomHeat,
|
||||
})
|
||||
}
|
||||
|
||||
@ -78,7 +81,8 @@ func (s *Service) sendGift(ctx context.Context, req *roomv1.SendGiftRequest, rob
|
||||
// 工资区域由 gateway 从 user-service host profile 注入;房间 visible_region_id 只用于房间/礼物可见性。
|
||||
TargetHostRegionID: req.GetTargetHostRegionId(),
|
||||
TargetAgencyOwnerUserID: req.GetTargetAgencyOwnerUserId(),
|
||||
RobotGift: robotOptions.Enabled,
|
||||
RobotGift: robotOptions.Enabled && !robotOptions.RealRoomHeat,
|
||||
RobotWalletGift: robotOptions.Enabled,
|
||||
SyntheticLuckyGift: robotOptions.Enabled && strings.TrimSpace(req.GetPoolId()) != "",
|
||||
SyntheticLuckyRewardCoins: firstPositiveInt64(robotOptions.SyntheticRewardCoins, 0),
|
||||
SyntheticLuckyMultiplierPPM: firstPositiveInt64(robotOptions.SyntheticMultiplierPPM, 1000000),
|
||||
@ -109,8 +113,8 @@ func (s *Service) sendGift(ctx context.Context, req *roomv1.SendGiftRequest, rob
|
||||
return mutationResult{}, nil, xerr.New(xerr.NotFound, "target not in room")
|
||||
}
|
||||
}
|
||||
if cmd.RobotGift {
|
||||
if err := requireRobotGiftParticipants(current, cmd.ActorUserID(), cmd.TargetUserIDs, robotOptions.RobotUserIDs); err != nil {
|
||||
if robotOptions.Enabled {
|
||||
if err := requireRobotGiftParticipants(current, cmd.ActorUserID(), cmd.TargetUserIDs, robotOptions.RobotUserIDs, !robotOptions.RealRoomHeat); err != nil {
|
||||
return mutationResult{}, nil, err
|
||||
}
|
||||
}
|
||||
@ -261,8 +265,9 @@ func (s *Service) sendGift(ctx context.Context, req *roomv1.SendGiftRequest, rob
|
||||
TargetGiftValue: targetCurrentGiftValues[targetBilling.TargetUserID],
|
||||
// effect_types 来自后台礼物配置,房间事件必须原样带出,后续 activity-service 才能识别全服广播标识。
|
||||
GiftEffectTypes: targetBilling.Billing.GetGiftEffectTypes(),
|
||||
IsRobotGift: cmd.RobotGift,
|
||||
IsRobotGift: cmd.RobotWalletGift,
|
||||
SyntheticLuckyGift: cmd.SyntheticLuckyGift,
|
||||
RealRoomRobotGift: cmd.RobotWalletGift && !cmd.RobotGift,
|
||||
})
|
||||
if err != nil {
|
||||
return mutationResult{}, nil, err
|
||||
@ -270,6 +275,14 @@ func (s *Service) sendGift(ctx context.Context, req *roomv1.SendGiftRequest, rob
|
||||
giftEvents = append(giftEvents, giftEvent)
|
||||
}
|
||||
|
||||
records := make([]outbox.Record, 0, len(giftEvents)+4)
|
||||
robotRecords := make([]outbox.Record, 0, len(giftEvents)+3)
|
||||
if cmd.RobotGift {
|
||||
// 机器人送礼只保留客户端展示所需事实,并写入 robot outbox,由独立 worker/topic 补偿投递。
|
||||
robotRecords = append(robotRecords, giftEvents...)
|
||||
} else {
|
||||
records = append(records, giftEvents...)
|
||||
}
|
||||
heatEvent, err := outbox.Build(current.RoomID, "RoomHeatChanged", current.Version, now, &roomeventsv1.RoomHeatChanged{
|
||||
Delta: heatValue,
|
||||
CurrentHeat: current.Heat,
|
||||
@ -287,23 +300,28 @@ func (s *Service) sendGift(ctx context.Context, req *roomv1.SendGiftRequest, rob
|
||||
if err != nil {
|
||||
return mutationResult{}, nil, err
|
||||
}
|
||||
|
||||
records := make([]outbox.Record, 0, len(giftEvents)+4)
|
||||
records = append(records, giftEvents...)
|
||||
records = append(records, heatEvent, rankEvent)
|
||||
if rocketApply.progressEvent != nil {
|
||||
progressEvent, err := outbox.Build(current.RoomID, "RoomRocketFuelChanged", current.Version, now, rocketApply.progressEvent)
|
||||
if err != nil {
|
||||
return mutationResult{}, nil, err
|
||||
}
|
||||
records = append(records, progressEvent)
|
||||
if cmd.RobotGift {
|
||||
// 房间热度和麦位收礼热度仍要给客户端展示,但走机器人 outbox,不能占用真人房间主流程。
|
||||
robotRecords = append(robotRecords, heatEvent, rankEvent)
|
||||
} else {
|
||||
records = append(records, heatEvent, rankEvent)
|
||||
}
|
||||
if rocketApply.ignited != nil {
|
||||
ignitedEvent, err := outbox.Build(current.RoomID, "RoomRocketIgnited", current.Version, now, rocketApply.ignited)
|
||||
if err != nil {
|
||||
return mutationResult{}, nil, err
|
||||
if !cmd.RobotGift && !cmd.RobotWalletGift {
|
||||
// 火箭只属于真人礼物主业务链路,机器人展示礼物不能触发火箭燃料 outbox。
|
||||
if rocketApply.progressEvent != nil {
|
||||
progressEvent, err := outbox.Build(current.RoomID, "RoomRocketFuelChanged", current.Version, now, rocketApply.progressEvent)
|
||||
if err != nil {
|
||||
return mutationResult{}, nil, err
|
||||
}
|
||||
records = append(records, progressEvent)
|
||||
}
|
||||
if rocketApply.ignited != nil {
|
||||
ignitedEvent, err := outbox.Build(current.RoomID, "RoomRocketIgnited", current.Version, now, rocketApply.ignited)
|
||||
if err != nil {
|
||||
return mutationResult{}, nil, err
|
||||
}
|
||||
records = append(records, ignitedEvent)
|
||||
}
|
||||
records = append(records, ignitedEvent)
|
||||
}
|
||||
if cmd.SyntheticLuckyGift && luckyGift != nil {
|
||||
drawEvent, err := outbox.Build(current.RoomID, "RoomRobotLuckyGiftDrawn", current.Version, now, &roomeventsv1.RoomRobotLuckyGiftDrawn{
|
||||
@ -327,18 +345,23 @@ func (s *Service) sendGift(ctx context.Context, req *roomv1.SendGiftRequest, rob
|
||||
if err != nil {
|
||||
return mutationResult{}, nil, err
|
||||
}
|
||||
records = append(records, drawEvent)
|
||||
if cmd.RobotGift {
|
||||
robotRecords = append(robotRecords, drawEvent)
|
||||
} else {
|
||||
records = append(records, drawEvent)
|
||||
}
|
||||
}
|
||||
|
||||
result := mutationResult{
|
||||
snapshot: current.ToProto(),
|
||||
billingReceiptID: billing.GetBillingReceiptId(),
|
||||
roomHeat: current.Heat,
|
||||
giftRank: cloneProtoRank(current.GiftRank),
|
||||
luckyGift: luckyGift,
|
||||
luckyGifts: luckyGifts,
|
||||
commandPayload: commandPayload,
|
||||
walletDebitMS: walletDebitMS,
|
||||
snapshot: current.ToProto(),
|
||||
billingReceiptID: billing.GetBillingReceiptId(),
|
||||
roomHeat: current.Heat,
|
||||
giftRank: cloneProtoRank(current.GiftRank),
|
||||
luckyGift: luckyGift,
|
||||
luckyGifts: luckyGifts,
|
||||
commandPayload: commandPayload,
|
||||
walletDebitMS: walletDebitMS,
|
||||
robotOutboxRecords: robotRecords,
|
||||
roomGiftLeaderboard: &RoomGiftLeaderboardIncrement{
|
||||
AppCode: appcode.FromContext(ctx),
|
||||
RoomID: current.RoomID,
|
||||
@ -387,7 +410,7 @@ func (s *Service) sendGift(ctx context.Context, req *roomv1.SendGiftRequest, rob
|
||||
"gift_icon_url": billing.GetGiftIconUrl(),
|
||||
"gift_animation_url": billing.GetGiftAnimationUrl(),
|
||||
"target_gift_value": fmt.Sprintf("%d", targetCurrentGiftValues[cmd.TargetUserID]),
|
||||
"is_robot_gift": fmt.Sprintf("%t", cmd.RobotGift),
|
||||
"is_robot_gift": fmt.Sprintf("%t", cmd.RobotWalletGift),
|
||||
"synthetic_lucky_gift": fmt.Sprintf("%t", cmd.SyntheticLuckyGift),
|
||||
},
|
||||
},
|
||||
@ -423,7 +446,7 @@ type giftTargetBilling struct {
|
||||
}
|
||||
|
||||
func (s *Service) debitGiftTargets(ctx context.Context, cmd command.SendGift, roomMeta RoomMeta) (*walletv1.DebitGiftResponse, []giftTargetBilling, error) {
|
||||
if cmd.RobotGift {
|
||||
if cmd.RobotWalletGift {
|
||||
if len(cmd.TargetUserIDs) != 1 {
|
||||
return nil, nil, xerr.New(xerr.InvalidArgument, "robot gift only supports one target")
|
||||
}
|
||||
@ -773,8 +796,11 @@ func findRankItem(items []state.RankItem, userID int64) state.RankItem {
|
||||
return state.RankItem{UserID: userID}
|
||||
}
|
||||
|
||||
func requireRobotGiftParticipants(current *state.RoomState, senderUserID int64, targetUserIDs []int64, runtimeRobotUserIDs []int64) error {
|
||||
if current == nil || current.RoomExt[roomExtRobotRoomKey] != "true" {
|
||||
func requireRobotGiftParticipants(current *state.RoomState, senderUserID int64, targetUserIDs []int64, runtimeRobotUserIDs []int64, requireRobotRoom bool) error {
|
||||
if current == nil {
|
||||
return xerr.New(xerr.PermissionDenied, "robot gift requires room state")
|
||||
}
|
||||
if requireRobotRoom && (current == nil || current.RoomExt[roomExtRobotRoomKey] != "true") {
|
||||
return xerr.New(xerr.PermissionDenied, "robot gift requires robot room")
|
||||
}
|
||||
allowed := parseInt64CSV(current.RoomExt[roomExtRobotUserIDsKey])
|
||||
|
||||
839
services/room-service/internal/room/service/human_room_robot.go
Normal file
839
services/room-service/internal/room/service/human_room_robot.go
Normal file
@ -0,0 +1,839 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
roomv1 "hyapp.local/api/proto/room/v1"
|
||||
"hyapp/pkg/appcode"
|
||||
"hyapp/pkg/logx"
|
||||
"hyapp/pkg/xerr"
|
||||
)
|
||||
|
||||
const (
|
||||
humanRobotLuckyPoolID = "human_robot_lucky_display"
|
||||
humanRobotSuperLuckyPoolID = "human_robot_super_lucky_display"
|
||||
|
||||
defaultHumanRobotCandidateRoomMaxOnline = int32(5)
|
||||
defaultHumanRobotRoomFullStopOnline = int32(10)
|
||||
defaultHumanRobotRoomTargetMinOnline = int32(8)
|
||||
defaultHumanRobotRoomTargetMaxOnline = int32(10)
|
||||
defaultHumanRobotStayMinMS = int64(60 * 1000)
|
||||
defaultHumanRobotStayMaxMS = int64(10 * 60 * 1000)
|
||||
defaultHumanRobotReplaceMinMS = int64(60 * 1000)
|
||||
defaultHumanRobotReplaceMaxMS = int64(3 * 60 * 1000)
|
||||
defaultHumanRobotNormalGiftIntervalMS = int64(10 * 1000)
|
||||
defaultHumanRobotNormalGiftIntervalMinMS = int64(1 * 1000)
|
||||
defaultHumanRobotNormalGiftIntervalMaxMS = int64(20 * 1000)
|
||||
defaultHumanRobotLuckyPauseMinMS = int64(5 * 1000)
|
||||
defaultHumanRobotLuckyPauseMaxMS = int64(20 * 1000)
|
||||
defaultHumanRobotLuckyComboMin = int64(1)
|
||||
defaultHumanRobotLuckyComboMax = int64(3)
|
||||
defaultHumanRobotMaxGiftSenders = int64(1)
|
||||
)
|
||||
|
||||
func (s *Service) AdminGetHumanRoomRobotConfig(ctx context.Context, req *roomv1.AdminGetHumanRoomRobotConfigRequest) (*roomv1.AdminGetHumanRoomRobotConfigResponse, error) {
|
||||
ctx = contextFromMeta(ctx, req.GetMeta())
|
||||
config, exists, err := s.repository.GetHumanRoomRobotConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
config = defaultHumanRoomRobotConfig(appcode.FromContext(ctx), s.clock.Now().UnixMilli())
|
||||
}
|
||||
return &roomv1.AdminGetHumanRoomRobotConfigResponse{Config: humanRoomRobotConfigToProto(config), ServerTimeMs: s.clock.Now().UnixMilli()}, nil
|
||||
}
|
||||
|
||||
func (s *Service) AdminUpdateHumanRoomRobotConfig(ctx context.Context, req *roomv1.AdminUpdateHumanRoomRobotConfigRequest) (*roomv1.AdminUpdateHumanRoomRobotConfigResponse, error) {
|
||||
ctx = contextFromMeta(ctx, req.GetMeta())
|
||||
config, err := normalizeHumanRoomRobotConfig(appcode.FromContext(ctx), req.GetConfig(), req.GetAdminId(), s.clock.Now().UnixMilli())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
saved, err := s.repository.UpsertHumanRoomRobotConfig(ctx, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !saved.Enabled {
|
||||
s.stopAllHumanRoomRobotRuntimes()
|
||||
}
|
||||
return &roomv1.AdminUpdateHumanRoomRobotConfigResponse{Config: humanRoomRobotConfigToProto(saved), ServerTimeMs: s.clock.Now().UnixMilli()}, nil
|
||||
}
|
||||
|
||||
// RunHumanRoomRobotRuntimeManager 定期把各国家空闲机器人补进低人数真人房间。
|
||||
func (s *Service) RunHumanRoomRobotRuntimeManager(ctx context.Context, interval time.Duration) {
|
||||
if interval <= 0 {
|
||||
interval = 15 * time.Second
|
||||
}
|
||||
logx.Info(ctx, "human_room_robot_runtime_manager_started", slog.Int64("interval_ms", interval.Milliseconds()))
|
||||
ticker := time.NewTicker(interval)
|
||||
defer ticker.Stop()
|
||||
s.scanHumanRoomRobotRuntimes(ctx)
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
s.stopAllHumanRoomRobotRuntimes()
|
||||
return
|
||||
case <-ticker.C:
|
||||
s.scanHumanRoomRobotRuntimes(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) scanHumanRoomRobotRuntimes(ctx context.Context) {
|
||||
config, exists, err := s.repository.GetHumanRoomRobotConfig(ctx)
|
||||
if err != nil {
|
||||
logx.Warn(ctx, "human_room_robot_config_load_failed", slog.String("error", err.Error()))
|
||||
return
|
||||
}
|
||||
if !exists {
|
||||
return
|
||||
}
|
||||
config = withHumanRoomRobotDefaults(config)
|
||||
if !config.Enabled {
|
||||
s.stopAllHumanRoomRobotRuntimes()
|
||||
return
|
||||
}
|
||||
pools, err := s.loadHumanRoomRobotPools(ctx, config.AppCode)
|
||||
if err != nil {
|
||||
logx.Warn(ctx, "human_room_robot_pool_load_failed", slog.String("error", err.Error()))
|
||||
return
|
||||
}
|
||||
config.CountryPools = pools
|
||||
for _, pool := range config.CountryPools {
|
||||
countryCode := normalizeRoomCountryCode(pool.CountryCode)
|
||||
if countryCode == "" || len(pool.RobotUserIDs) == 0 {
|
||||
continue
|
||||
}
|
||||
rooms, err := s.repository.ListHumanRobotCandidateRooms(ctx, config.AppCode, countryCode, config.CandidateRoomMaxOnline, config.RoomTargetMaxOnline, 50)
|
||||
if err != nil {
|
||||
logx.Warn(ctx, "human_room_robot_candidate_rooms_failed", slog.String("country_code", countryCode), slog.String("error", err.Error()))
|
||||
continue
|
||||
}
|
||||
for _, room := range rooms {
|
||||
if s.humanRoomRobotRuntimeConfigChanged(room.RoomID, config.UpdatedAtMS) {
|
||||
s.stopHumanRoomRobotRuntime(room.RoomID)
|
||||
}
|
||||
if s.humanRoomRobotRuntimeExists(room.RoomID) {
|
||||
continue
|
||||
}
|
||||
s.startHumanRoomRobotRuntime(ctx, config, countryCode, room.RoomID, pool.RobotUserIDs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) loadHumanRoomRobotPools(ctx context.Context, appCode string) ([]HumanRoomRobotCountryPool, error) {
|
||||
if s.humanRobotPoolProvider == nil {
|
||||
return nil, xerr.New(xerr.Unavailable, "human room robot pool provider is not configured")
|
||||
}
|
||||
items, err := s.humanRobotPoolProvider.ListHumanRoomRobotPools(ctx, appCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pools := make([]HumanRoomRobotCountryPool, 0, len(items))
|
||||
for _, item := range items {
|
||||
countryCode := normalizeRoomCountryCode(item.CountryCode)
|
||||
ids := normalizeRobotUserIDs(item.RobotUserIDs)
|
||||
if countryCode == "" || len(ids) == 0 {
|
||||
continue
|
||||
}
|
||||
pools = append(pools, HumanRoomRobotCountryPool{CountryCode: countryCode, RobotUserIDs: ids})
|
||||
}
|
||||
return pools, nil
|
||||
}
|
||||
|
||||
func (s *Service) startHumanRoomRobotRuntime(parent context.Context, config HumanRoomRobotConfig, countryCode string, roomID string, pool []int64) {
|
||||
if parent.Err() != nil || roomID == "" || len(pool) == 0 {
|
||||
return
|
||||
}
|
||||
s.humanRobotRuntimeMu.Lock()
|
||||
if s.humanRobotRuntimes == nil {
|
||||
s.humanRobotRuntimes = make(map[string]robotRoomRuntime)
|
||||
}
|
||||
if _, exists := s.humanRobotRuntimes[roomID]; exists {
|
||||
s.humanRobotRuntimeMu.Unlock()
|
||||
return
|
||||
}
|
||||
s.humanRobotRuntimeMu.Unlock()
|
||||
|
||||
roomCtx := appcode.WithContext(parent, config.AppCode)
|
||||
targetOnline := randomHumanRoomTargetOnline(config)
|
||||
selected, err := s.prepareHumanRoomRobots(roomCtx, config, roomID, pool, targetOnline)
|
||||
if err != nil {
|
||||
logx.Warn(roomCtx, "human_room_robot_prepare_failed", slog.String("room_id", roomID), slog.String("country_code", countryCode), slog.String("error", err.Error()))
|
||||
return
|
||||
}
|
||||
if len(selected) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
s.humanRobotRuntimeMu.Lock()
|
||||
if _, exists := s.humanRobotRuntimes[roomID]; exists {
|
||||
s.humanRobotRuntimeMu.Unlock()
|
||||
return
|
||||
}
|
||||
ctx, cancel := context.WithCancel(roomCtx)
|
||||
token := fmt.Sprintf("%s:%d", roomID, time.Now().UTC().UnixNano())
|
||||
s.humanRobotRuntimes[roomID] = robotRoomRuntime{cancel: cancel, token: token, configUpdatedAtMS: config.UpdatedAtMS}
|
||||
s.humanRobotRuntimeMu.Unlock()
|
||||
|
||||
logx.Info(ctx, "human_room_robot_runtime_started",
|
||||
slog.String("room_id", roomID),
|
||||
slog.String("country_code", countryCode),
|
||||
slog.Int("target_online", targetOnline),
|
||||
slog.Int("active_robot_count", len(selected)),
|
||||
)
|
||||
go func() {
|
||||
defer s.clearHumanRoomRobotRuntime(roomID, token)
|
||||
s.runHumanRoomRobotRuntime(ctx, config, roomID, pool, selected, targetOnline)
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *Service) prepareHumanRoomRobots(ctx context.Context, config HumanRoomRobotConfig, roomID string, pool []int64, targetOnline int) ([]int64, error) {
|
||||
snapshot, err := s.currentSnapshot(ctx, roomID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if snapshot.GetStatus() != "active" {
|
||||
return nil, nil
|
||||
}
|
||||
online := make(map[int64]bool, len(snapshot.GetOnlineUsers()))
|
||||
for _, user := range snapshot.GetOnlineUsers() {
|
||||
online[user.GetUserId()] = true
|
||||
}
|
||||
humanOnline := humanRoomRealOnlineCount(snapshot.GetOnlineUsers(), allHumanRoomRobotIDs(config))
|
||||
if humanOnline >= int(config.CandidateRoomMaxOnline) || len(online) >= targetOnline {
|
||||
return nil, nil
|
||||
}
|
||||
limit := targetOnline - len(online)
|
||||
if limit <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
freeSeats := freeSeatNumbers(snapshot.GetMicSeats())
|
||||
if len(freeSeats) < limit {
|
||||
limit = len(freeSeats)
|
||||
}
|
||||
if limit <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
candidates := append([]int64(nil), pool...)
|
||||
rng.Shuffle(len(candidates), func(i, j int) { candidates[i], candidates[j] = candidates[j], candidates[i] })
|
||||
selected := make([]int64, 0, limit)
|
||||
for _, userID := range candidates {
|
||||
if len(selected) >= limit {
|
||||
break
|
||||
}
|
||||
if userID <= 0 || online[userID] || s.robotHasActiveRoomPresence(ctx, userID, roomID) {
|
||||
continue
|
||||
}
|
||||
seatNo := freeSeats[len(selected)]
|
||||
if err := s.joinHumanRoomRobot(ctx, roomID, userID, seatNo, fmt.Sprintf("initial:%d:%d", userID, time.Now().UTC().UnixNano())); err != nil {
|
||||
logx.Warn(ctx, "human_room_robot_initial_join_failed", slog.String("room_id", roomID), slog.Int64("robot_user_id", userID), slog.String("error", err.Error()))
|
||||
continue
|
||||
}
|
||||
selected = append(selected, userID)
|
||||
}
|
||||
return selected, nil
|
||||
}
|
||||
|
||||
func (s *Service) runHumanRoomRobotRuntime(ctx context.Context, config HumanRoomRobotConfig, roomID string, pool []int64, initialActive []int64, targetOnline int) {
|
||||
activity := newRobotRoomActivity(pool)
|
||||
for _, userID := range initialActive {
|
||||
activity.markActive(userID)
|
||||
}
|
||||
markInitialHumanRoomGiftSenders(activity, initialActive, int(config.MaxGiftSenders))
|
||||
giftSlots := make(chan struct{}, int(max(1, int(config.MaxGiftSenders))))
|
||||
for _, userID := range pool {
|
||||
userID := userID
|
||||
go s.runHumanRobotPresenceLoop(ctx, config, roomID, pool, activity, userID, targetOnline)
|
||||
go s.runHumanRobotNormalGiftLoop(ctx, config, roomID, activity, giftSlots, userID)
|
||||
go s.runHumanRobotLuckyGiftLoop(ctx, config, roomID, activity, giftSlots, userID, config.LuckyGiftIDs, humanRobotLuckyPoolID, "lucky", 5_000_000)
|
||||
go s.runHumanRobotLuckyGiftLoop(ctx, config, roomID, activity, giftSlots, userID, config.SuperLuckyGiftIDs, humanRobotSuperLuckyPoolID, "super_lucky", 20_000_000)
|
||||
}
|
||||
go s.runHumanRobotFillLoop(ctx, config, roomID, pool, activity, targetOnline)
|
||||
<-ctx.Done()
|
||||
}
|
||||
|
||||
func (s *Service) runHumanRobotFillLoop(ctx context.Context, config HumanRoomRobotConfig, roomID string, pool []int64, activity *robotRoomActivity, targetOnline int) {
|
||||
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
timer := time.NewTimer(time.Duration(1+rng.Intn(3)) * time.Second)
|
||||
defer timer.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-timer.C:
|
||||
s.fillHumanRoomRobotsOnce(ctx, config, roomID, pool, activity, rng, targetOnline)
|
||||
timer.Reset(time.Duration(5+rng.Intn(5)) * time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) fillHumanRoomRobotsOnce(ctx context.Context, config HumanRoomRobotConfig, roomID string, pool []int64, activity *robotRoomActivity, rng *rand.Rand, targetOnline int) {
|
||||
snapshot, err := s.currentSnapshot(ctx, roomID)
|
||||
if err != nil || snapshot.GetStatus() != "active" {
|
||||
return
|
||||
}
|
||||
humanOnline := humanRoomRealOnlineCount(snapshot.GetOnlineUsers(), allHumanRoomRobotIDs(config))
|
||||
if humanOnline >= int(config.CandidateRoomMaxOnline) || len(snapshot.GetOnlineUsers()) >= targetOnline {
|
||||
return
|
||||
}
|
||||
limit := targetOnline - len(snapshot.GetOnlineUsers())
|
||||
freeSeats := freeSeatNumbers(snapshot.GetMicSeats())
|
||||
if len(freeSeats) < limit {
|
||||
limit = len(freeSeats)
|
||||
}
|
||||
if limit <= 0 {
|
||||
return
|
||||
}
|
||||
online := make(map[int64]bool, len(snapshot.GetOnlineUsers()))
|
||||
for _, user := range snapshot.GetOnlineUsers() {
|
||||
online[user.GetUserId()] = true
|
||||
}
|
||||
candidates := append([]int64(nil), pool...)
|
||||
rng.Shuffle(len(candidates), func(i, j int) { candidates[i], candidates[j] = candidates[j], candidates[i] })
|
||||
joined := 0
|
||||
for _, userID := range candidates {
|
||||
if joined >= limit {
|
||||
return
|
||||
}
|
||||
if userID <= 0 || online[userID] || activity.isActive(userID) || s.robotHasActiveRoomPresence(ctx, userID, roomID) {
|
||||
continue
|
||||
}
|
||||
seatNo := freeSeats[joined]
|
||||
if err := s.joinHumanRoomRobot(ctx, roomID, userID, seatNo, fmt.Sprintf("fill:%d:%d", userID, time.Now().UTC().UnixNano())); err != nil {
|
||||
logx.Warn(ctx, "human_room_robot_fill_join_failed", slog.String("room_id", roomID), slog.Int64("robot_user_id", userID), slog.String("error", err.Error()))
|
||||
continue
|
||||
}
|
||||
activity.markActive(userID)
|
||||
activity.markGiftSenderWithinLimit(userID, int(config.MaxGiftSenders))
|
||||
online[userID] = true
|
||||
joined++
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) runHumanRobotPresenceLoop(ctx context.Context, config HumanRoomRobotConfig, roomID string, pool []int64, activity *robotRoomActivity, userID int64, targetOnline int) {
|
||||
if userID <= 0 {
|
||||
return
|
||||
}
|
||||
rng := rand.New(rand.NewSource(time.Now().UnixNano() + userID*43))
|
||||
for {
|
||||
if !activity.isActive(userID) {
|
||||
if !waitRobotRuntimeDelay(ctx, time.Duration(300+rng.Intn(700))*time.Millisecond) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
stay := time.Duration(randomInt64Range(rng, config.RobotStayMinMS, config.RobotStayMaxMS)) * time.Millisecond
|
||||
if !waitRobotRuntimeDelay(ctx, stay) {
|
||||
return
|
||||
}
|
||||
// 送礼名额绑定在房间内的少数机器人身上;送礼机器人离开时,补位机器人接替这个名额,保证房间内送礼者数量稳定且不会扩散到所有机器人。
|
||||
wasGiftSender := activity.isGiftSender(userID)
|
||||
if !activity.markInactive(userID) {
|
||||
continue
|
||||
}
|
||||
seatNo := s.humanRoomRobotSeatNo(ctx, roomID, userID)
|
||||
if err := s.leaveHumanRoomRobot(ctx, roomID, userID); err != nil {
|
||||
logx.Warn(ctx, "human_room_robot_leave_failed", slog.String("room_id", roomID), slog.Int64("robot_user_id", userID), slog.String("error", err.Error()))
|
||||
activity.markActive(userID)
|
||||
if wasGiftSender {
|
||||
activity.markGiftSender(userID)
|
||||
}
|
||||
continue
|
||||
}
|
||||
delay := time.Duration(randomInt64Range(rng, config.RobotReplaceMinMS, config.RobotReplaceMaxMS)) * time.Millisecond
|
||||
if !waitRobotRuntimeDelay(ctx, delay) {
|
||||
return
|
||||
}
|
||||
replacementID := s.pickHumanRoomReplacement(ctx, config, roomID, pool, activity, userID)
|
||||
if replacementID <= 0 {
|
||||
continue
|
||||
}
|
||||
if seatNo <= 0 {
|
||||
seatNo = s.firstHumanRoomFreeSeatNo(ctx, roomID)
|
||||
}
|
||||
if seatNo <= 0 || !s.humanRoomNeedsRobot(ctx, config, roomID, targetOnline) {
|
||||
continue
|
||||
}
|
||||
if err := s.joinHumanRoomRobot(ctx, roomID, replacementID, seatNo, fmt.Sprintf("replace:%d:%d", replacementID, time.Now().UTC().UnixNano())); err != nil {
|
||||
logx.Warn(ctx, "human_room_robot_replace_join_failed", slog.String("room_id", roomID), slog.Int64("replacement_user_id", replacementID), slog.String("error", err.Error()))
|
||||
continue
|
||||
}
|
||||
activity.markActive(replacementID)
|
||||
if wasGiftSender || activity.giftSenderCount() < int(config.MaxGiftSenders) {
|
||||
activity.markGiftSenderWithinLimit(replacementID, int(config.MaxGiftSenders))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) runHumanRobotNormalGiftLoop(ctx context.Context, config HumanRoomRobotConfig, roomID string, activity *robotRoomActivity, giftSlots chan struct{}, senderID int64) {
|
||||
if config.NormalGiftIntervalMinMS <= 0 || config.NormalGiftIntervalMaxMS <= 0 || len(config.GiftIDs) == 0 {
|
||||
return
|
||||
}
|
||||
rng := rand.New(rand.NewSource(time.Now().UnixNano() + senderID*59))
|
||||
timer := time.NewTimer(humanRoomRobotNormalGiftDelay(config, rng))
|
||||
defer timer.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-timer.C:
|
||||
if activity.isActive(senderID) && activity.isGiftSender(senderID) {
|
||||
targetID := randomRobotTarget(rng, activity.activeIDs(), senderID)
|
||||
giftID := randomString(rng, config.GiftIDs)
|
||||
s.sendHumanRoomRobotGiftBestEffort(ctx, config, roomID, activity, giftSlots, senderID, targetID, giftID, "", "normal", 0)
|
||||
}
|
||||
timer.Reset(humanRoomRobotNormalGiftDelay(config, rng))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) runHumanRobotLuckyGiftLoop(ctx context.Context, config HumanRoomRobotConfig, roomID string, activity *robotRoomActivity, giftSlots chan struct{}, senderID int64, giftIDs []string, poolID string, kind string, multiplierPPM int64) {
|
||||
if len(giftIDs) == 0 || config.LuckyComboMax <= 0 {
|
||||
return
|
||||
}
|
||||
rng := rand.New(rand.NewSource(time.Now().UnixNano() + senderID*71))
|
||||
for {
|
||||
if !activity.isActive(senderID) || !activity.isGiftSender(senderID) {
|
||||
if !waitRobotRuntimeDelay(ctx, time.Duration(300+rng.Intn(700))*time.Millisecond) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
combo := randomInt64Range(rng, config.LuckyComboMin, config.LuckyComboMax)
|
||||
for i := int64(0); i < combo; i++ {
|
||||
if !activity.isActive(senderID) || !activity.isGiftSender(senderID) {
|
||||
break
|
||||
}
|
||||
targetID := randomRobotTarget(rng, activity.activeIDs(), senderID)
|
||||
giftID := randomString(rng, giftIDs)
|
||||
s.sendHumanRoomRobotGiftBestEffort(ctx, config, roomID, activity, giftSlots, senderID, targetID, giftID, poolID, kind, multiplierPPM)
|
||||
if !waitRobotGiftPace(ctx, rng) {
|
||||
return
|
||||
}
|
||||
}
|
||||
pause := time.Duration(randomInt64Range(rng, config.LuckyPauseMinMS, config.LuckyPauseMaxMS)) * time.Millisecond
|
||||
if !waitRobotRuntimeDelay(ctx, pause) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) sendHumanRoomRobotGiftBestEffort(ctx context.Context, config HumanRoomRobotConfig, roomID string, activity *robotRoomActivity, giftSlots chan struct{}, senderID int64, targetID int64, giftID string, poolID string, kind string, multiplierPPM int64) {
|
||||
if !activity.isActive(senderID) || !activity.isGiftSender(senderID) || !activity.isActive(targetID) || giftID == "" {
|
||||
return
|
||||
}
|
||||
select {
|
||||
case giftSlots <- struct{}{}:
|
||||
defer func() { <-giftSlots }()
|
||||
default:
|
||||
return
|
||||
}
|
||||
_, err := s.RobotSendGift(ctx, RobotSendGiftInput{
|
||||
Meta: humanRoomRobotCommandMeta(config, roomID, senderID, fmt.Sprintf("gift:%s:%d:%d", kind, targetID, time.Now().UTC().UnixNano())),
|
||||
TargetUserID: targetID,
|
||||
GiftID: giftID,
|
||||
GiftCount: 1,
|
||||
PoolID: poolID,
|
||||
RobotUserIDs: activity.pool,
|
||||
SyntheticMultiplierPPM: multiplierPPM,
|
||||
RealRoomHeat: true,
|
||||
})
|
||||
if err != nil {
|
||||
logx.Warn(ctx, "human_room_robot_send_gift_failed", slog.String("room_id", roomID), slog.String("kind", kind), slog.Int64("sender_user_id", senderID), slog.Int64("target_user_id", targetID), slog.String("gift_id", giftID), slog.String("error", err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
func markInitialHumanRoomGiftSenders(activity *robotRoomActivity, initialActive []int64, maxSenders int) {
|
||||
if activity == nil || maxSenders <= 0 || len(initialActive) == 0 {
|
||||
return
|
||||
}
|
||||
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
candidates := append([]int64(nil), initialActive...)
|
||||
rng.Shuffle(len(candidates), func(i int, j int) {
|
||||
candidates[i], candidates[j] = candidates[j], candidates[i]
|
||||
})
|
||||
for _, userID := range candidates {
|
||||
if activity.giftSenderCount() >= maxSenders {
|
||||
return
|
||||
}
|
||||
activity.markGiftSenderWithinLimit(userID, maxSenders)
|
||||
}
|
||||
}
|
||||
|
||||
func humanRoomRobotNormalGiftDelay(config HumanRoomRobotConfig, rng *rand.Rand) time.Duration {
|
||||
minMS := config.NormalGiftIntervalMinMS
|
||||
maxMS := config.NormalGiftIntervalMaxMS
|
||||
if minMS <= 0 && maxMS <= 0 && config.NormalGiftIntervalMS > 0 {
|
||||
minMS = config.NormalGiftIntervalMS
|
||||
maxMS = config.NormalGiftIntervalMS
|
||||
}
|
||||
if minMS <= 0 {
|
||||
minMS = defaultHumanRobotNormalGiftIntervalMinMS
|
||||
}
|
||||
if maxMS < minMS {
|
||||
maxMS = minMS
|
||||
}
|
||||
return time.Duration(randomInt64Range(rng, minMS, maxMS)) * time.Millisecond
|
||||
}
|
||||
|
||||
func randomHumanRoomTargetOnline(config HumanRoomRobotConfig) int {
|
||||
minOnline := config.RoomTargetMinOnline
|
||||
maxOnline := config.RoomTargetMaxOnline
|
||||
if minOnline <= 0 && maxOnline <= 0 && config.RoomFullStopOnline > 0 {
|
||||
minOnline = config.RoomFullStopOnline
|
||||
maxOnline = config.RoomFullStopOnline
|
||||
}
|
||||
if minOnline <= 0 {
|
||||
minOnline = defaultHumanRobotRoomTargetMinOnline
|
||||
}
|
||||
if maxOnline < minOnline {
|
||||
maxOnline = minOnline
|
||||
}
|
||||
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
return int(randomInt64Range(rng, int64(minOnline), int64(maxOnline)))
|
||||
}
|
||||
|
||||
func (s *Service) joinHumanRoomRobot(ctx context.Context, roomID string, userID int64, seatNo int32, suffix string) error {
|
||||
if _, err := s.JoinRoom(ctx, &roomv1.JoinRoomRequest{
|
||||
Meta: humanRoomRobotCommandMeta(HumanRoomRobotConfig{AppCode: appcode.FromContext(ctx)}, roomID, userID, "join:"+suffix),
|
||||
Role: "audience",
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := s.RobotVirtualMicUp(ctx, RobotMicUpInput{
|
||||
Meta: humanRoomRobotCommandMeta(HumanRoomRobotConfig{AppCode: appcode.FromContext(ctx)}, roomID, userID, "mic:"+suffix),
|
||||
TargetUserID: userID,
|
||||
SeatNo: seatNo,
|
||||
}); err != nil {
|
||||
if xerr.CodeOf(err) == xerr.Conflict && strings.Contains(xerr.MessageOf(err), "already on seat") {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) leaveHumanRoomRobot(ctx context.Context, roomID string, userID int64) error {
|
||||
_, err := s.LeaveRoom(ctx, &roomv1.LeaveRoomRequest{
|
||||
Meta: humanRoomRobotCommandMeta(HumanRoomRobotConfig{AppCode: appcode.FromContext(ctx)}, roomID, userID, fmt.Sprintf("leave:%d:%d", userID, time.Now().UTC().UnixNano())),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Service) pickHumanRoomReplacement(ctx context.Context, config HumanRoomRobotConfig, roomID string, pool []int64, activity *robotRoomActivity, departingUserID int64) int64 {
|
||||
active := make(map[int64]bool, len(activity.activeIDs()))
|
||||
for _, id := range activity.activeIDs() {
|
||||
active[id] = true
|
||||
}
|
||||
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
candidates := append([]int64(nil), pool...)
|
||||
rng.Shuffle(len(candidates), func(i, j int) { candidates[i], candidates[j] = candidates[j], candidates[i] })
|
||||
for _, userID := range candidates {
|
||||
if userID <= 0 || active[userID] || userID == departingUserID || s.robotHasActiveRoomPresence(ctx, userID, roomID) {
|
||||
continue
|
||||
}
|
||||
return userID
|
||||
}
|
||||
if !s.robotHasActiveRoomPresence(ctx, departingUserID, roomID) {
|
||||
return departingUserID
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (s *Service) humanRoomNeedsRobot(ctx context.Context, config HumanRoomRobotConfig, roomID string, targetOnline int) bool {
|
||||
snapshot, err := s.currentSnapshot(ctx, roomID)
|
||||
if err != nil || snapshot.GetStatus() != "active" {
|
||||
return false
|
||||
}
|
||||
humanOnline := humanRoomRealOnlineCount(snapshot.GetOnlineUsers(), allHumanRoomRobotIDs(config))
|
||||
return humanOnline < int(config.CandidateRoomMaxOnline) && len(snapshot.GetOnlineUsers()) < targetOnline
|
||||
}
|
||||
|
||||
func (s *Service) robotHasActiveRoomPresence(ctx context.Context, userID int64, allowedRoomID string) bool {
|
||||
presence, exists, err := s.repository.GetCurrentRoomPresence(ctx, userID)
|
||||
if err != nil || !exists {
|
||||
return false
|
||||
}
|
||||
return presence.RoomID != "" && presence.RoomID != allowedRoomID
|
||||
}
|
||||
|
||||
func (s *Service) humanRoomRobotSeatNo(ctx context.Context, roomID string, userID int64) int32 {
|
||||
snapshot, err := s.currentSnapshot(ctx, roomID)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
for _, seat := range snapshot.GetMicSeats() {
|
||||
if seat.GetUserId() == userID {
|
||||
return seat.GetSeatNo()
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (s *Service) firstHumanRoomFreeSeatNo(ctx context.Context, roomID string) int32 {
|
||||
snapshot, err := s.currentSnapshot(ctx, roomID)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
seats := freeSeatNumbers(snapshot.GetMicSeats())
|
||||
if len(seats) == 0 {
|
||||
return 0
|
||||
}
|
||||
return seats[0]
|
||||
}
|
||||
|
||||
func (s *Service) humanRoomRobotRuntimeExists(roomID string) bool {
|
||||
s.humanRobotRuntimeMu.Lock()
|
||||
defer s.humanRobotRuntimeMu.Unlock()
|
||||
_, exists := s.humanRobotRuntimes[roomID]
|
||||
return exists
|
||||
}
|
||||
|
||||
func (s *Service) humanRoomRobotRuntimeConfigChanged(roomID string, updatedAtMS int64) bool {
|
||||
if updatedAtMS <= 0 {
|
||||
return false
|
||||
}
|
||||
s.humanRobotRuntimeMu.Lock()
|
||||
defer s.humanRobotRuntimeMu.Unlock()
|
||||
runtime, exists := s.humanRobotRuntimes[roomID]
|
||||
return exists && runtime.configUpdatedAtMS > 0 && runtime.configUpdatedAtMS != updatedAtMS
|
||||
}
|
||||
|
||||
func (s *Service) stopHumanRoomRobotRuntime(roomID string) {
|
||||
s.humanRobotRuntimeMu.Lock()
|
||||
runtime := s.humanRobotRuntimes[roomID]
|
||||
delete(s.humanRobotRuntimes, roomID)
|
||||
s.humanRobotRuntimeMu.Unlock()
|
||||
if runtime.cancel != nil {
|
||||
runtime.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) clearHumanRoomRobotRuntime(roomID string, token string) {
|
||||
s.humanRobotRuntimeMu.Lock()
|
||||
defer s.humanRobotRuntimeMu.Unlock()
|
||||
runtime, exists := s.humanRobotRuntimes[roomID]
|
||||
if !exists || runtime.token != token {
|
||||
return
|
||||
}
|
||||
delete(s.humanRobotRuntimes, roomID)
|
||||
}
|
||||
|
||||
func (s *Service) stopAllHumanRoomRobotRuntimes() {
|
||||
s.humanRobotRuntimeMu.Lock()
|
||||
cancels := make([]context.CancelFunc, 0, len(s.humanRobotRuntimes))
|
||||
for roomID, runtime := range s.humanRobotRuntimes {
|
||||
if runtime.cancel != nil {
|
||||
cancels = append(cancels, runtime.cancel)
|
||||
}
|
||||
delete(s.humanRobotRuntimes, roomID)
|
||||
}
|
||||
s.humanRobotRuntimeMu.Unlock()
|
||||
for _, cancel := range cancels {
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeHumanRoomRobotConfig(appCode string, input *roomv1.AdminHumanRoomRobotConfig, adminID uint64, nowMS int64) (HumanRoomRobotConfig, error) {
|
||||
if input == nil {
|
||||
return HumanRoomRobotConfig{}, xerr.New(xerr.InvalidArgument, "human room robot config is required")
|
||||
}
|
||||
config := HumanRoomRobotConfig{
|
||||
AppCode: appcode.Normalize(appCode),
|
||||
Enabled: input.GetEnabled(),
|
||||
CandidateRoomMaxOnline: input.GetCandidateRoomMaxOnline(),
|
||||
RoomFullStopOnline: input.GetRoomFullStopOnline(),
|
||||
RoomTargetMinOnline: input.GetRoomTargetMinOnline(),
|
||||
RoomTargetMaxOnline: input.GetRoomTargetMaxOnline(),
|
||||
RobotStayMinMS: input.GetRobotStayMinMs(),
|
||||
RobotStayMaxMS: input.GetRobotStayMaxMs(),
|
||||
RobotReplaceMinMS: input.GetRobotReplaceMinMs(),
|
||||
RobotReplaceMaxMS: input.GetRobotReplaceMaxMs(),
|
||||
NormalGiftIntervalMS: input.GetNormalGiftIntervalMs(),
|
||||
NormalGiftIntervalMinMS: input.GetNormalGiftIntervalMinMs(),
|
||||
NormalGiftIntervalMaxMS: input.GetNormalGiftIntervalMaxMs(),
|
||||
GiftIDs: normalizeStringSet(input.GetGiftIds()),
|
||||
LuckyGiftIDs: normalizeStringSet(input.GetLuckyGiftIds()),
|
||||
SuperLuckyGiftIDs: normalizeStringSet(input.GetSuperLuckyGiftIds()),
|
||||
LuckyComboMin: input.GetLuckyComboMin(),
|
||||
LuckyComboMax: input.GetLuckyComboMax(),
|
||||
LuckyPauseMinMS: input.GetLuckyPauseMinMs(),
|
||||
LuckyPauseMaxMS: input.GetLuckyPauseMaxMs(),
|
||||
MaxGiftSenders: input.GetMaxGiftSenders(),
|
||||
UpdatedByAdminID: adminID,
|
||||
CreatedAtMS: input.GetCreatedAtMs(),
|
||||
UpdatedAtMS: nowMS,
|
||||
}
|
||||
config = withHumanRoomRobotDefaults(config)
|
||||
if config.CandidateRoomMaxOnline <= 0 || config.RoomTargetMinOnline <= 0 || config.RoomTargetMaxOnline < config.RoomTargetMinOnline {
|
||||
return HumanRoomRobotConfig{}, xerr.New(xerr.InvalidArgument, "room online thresholds are invalid")
|
||||
}
|
||||
if config.RobotStayMinMS <= 0 || config.RobotStayMaxMS < config.RobotStayMinMS {
|
||||
return HumanRoomRobotConfig{}, xerr.New(xerr.InvalidArgument, "robot stay range is invalid")
|
||||
}
|
||||
if config.RobotReplaceMinMS < 0 || config.RobotReplaceMaxMS < config.RobotReplaceMinMS {
|
||||
return HumanRoomRobotConfig{}, xerr.New(xerr.InvalidArgument, "robot replace range is invalid")
|
||||
}
|
||||
if config.NormalGiftIntervalMinMS <= 0 || config.NormalGiftIntervalMaxMS < config.NormalGiftIntervalMinMS {
|
||||
return HumanRoomRobotConfig{}, xerr.New(xerr.InvalidArgument, "normal gift interval range is invalid")
|
||||
}
|
||||
if config.Enabled && len(config.GiftIDs) == 0 {
|
||||
return HumanRoomRobotConfig{}, xerr.New(xerr.InvalidArgument, "gift_ids is required")
|
||||
}
|
||||
if config.Enabled && len(config.LuckyGiftIDs) == 0 && len(config.SuperLuckyGiftIDs) == 0 {
|
||||
return HumanRoomRobotConfig{}, xerr.New(xerr.InvalidArgument, "lucky gift ids are required")
|
||||
}
|
||||
if config.LuckyComboMin <= 0 || config.LuckyComboMax < config.LuckyComboMin {
|
||||
return HumanRoomRobotConfig{}, xerr.New(xerr.InvalidArgument, "lucky combo range is invalid")
|
||||
}
|
||||
if config.LuckyPauseMinMS <= 0 || config.LuckyPauseMaxMS < config.LuckyPauseMinMS {
|
||||
return HumanRoomRobotConfig{}, xerr.New(xerr.InvalidArgument, "lucky pause range is invalid")
|
||||
}
|
||||
if config.MaxGiftSenders <= 0 {
|
||||
return HumanRoomRobotConfig{}, xerr.New(xerr.InvalidArgument, "max_gift_senders is required")
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func withHumanRoomRobotDefaults(config HumanRoomRobotConfig) HumanRoomRobotConfig {
|
||||
if config.AppCode == "" {
|
||||
config.AppCode = appcode.Default
|
||||
}
|
||||
if config.CandidateRoomMaxOnline <= 0 {
|
||||
config.CandidateRoomMaxOnline = defaultHumanRobotCandidateRoomMaxOnline
|
||||
}
|
||||
if config.RoomTargetMinOnline <= 0 && config.RoomTargetMaxOnline <= 0 {
|
||||
if config.RoomFullStopOnline > 0 {
|
||||
config.RoomTargetMinOnline = config.RoomFullStopOnline
|
||||
config.RoomTargetMaxOnline = config.RoomFullStopOnline
|
||||
} else {
|
||||
config.RoomTargetMinOnline = defaultHumanRobotRoomTargetMinOnline
|
||||
config.RoomTargetMaxOnline = defaultHumanRobotRoomTargetMaxOnline
|
||||
}
|
||||
}
|
||||
if config.RoomFullStopOnline <= 0 {
|
||||
config.RoomFullStopOnline = config.RoomTargetMaxOnline
|
||||
}
|
||||
if config.RobotStayMinMS <= 0 && config.RobotStayMaxMS <= 0 {
|
||||
config.RobotStayMinMS = defaultHumanRobotStayMinMS
|
||||
config.RobotStayMaxMS = defaultHumanRobotStayMaxMS
|
||||
}
|
||||
if config.RobotReplaceMinMS == 0 && config.RobotReplaceMaxMS == 0 {
|
||||
config.RobotReplaceMinMS = defaultHumanRobotReplaceMinMS
|
||||
config.RobotReplaceMaxMS = defaultHumanRobotReplaceMaxMS
|
||||
}
|
||||
if config.NormalGiftIntervalMinMS <= 0 && config.NormalGiftIntervalMaxMS <= 0 {
|
||||
if config.NormalGiftIntervalMS > 0 {
|
||||
config.NormalGiftIntervalMinMS = config.NormalGiftIntervalMS
|
||||
config.NormalGiftIntervalMaxMS = config.NormalGiftIntervalMS
|
||||
} else {
|
||||
config.NormalGiftIntervalMinMS = defaultHumanRobotNormalGiftIntervalMinMS
|
||||
config.NormalGiftIntervalMaxMS = defaultHumanRobotNormalGiftIntervalMaxMS
|
||||
}
|
||||
}
|
||||
if config.NormalGiftIntervalMS <= 0 {
|
||||
config.NormalGiftIntervalMS = config.NormalGiftIntervalMaxMS
|
||||
}
|
||||
if config.LuckyComboMin <= 0 && config.LuckyComboMax <= 0 {
|
||||
config.LuckyComboMin = defaultHumanRobotLuckyComboMin
|
||||
config.LuckyComboMax = defaultHumanRobotLuckyComboMax
|
||||
}
|
||||
if config.LuckyPauseMinMS <= 0 && config.LuckyPauseMaxMS <= 0 {
|
||||
config.LuckyPauseMinMS = defaultHumanRobotLuckyPauseMinMS
|
||||
config.LuckyPauseMaxMS = defaultHumanRobotLuckyPauseMaxMS
|
||||
}
|
||||
if config.MaxGiftSenders <= 0 {
|
||||
config.MaxGiftSenders = defaultHumanRobotMaxGiftSenders
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
func defaultHumanRoomRobotConfig(appCode string, nowMS int64) HumanRoomRobotConfig {
|
||||
return withHumanRoomRobotDefaults(HumanRoomRobotConfig{AppCode: appcode.Normalize(appCode), CreatedAtMS: nowMS, UpdatedAtMS: nowMS})
|
||||
}
|
||||
|
||||
func humanRoomRobotConfigToProto(config HumanRoomRobotConfig) *roomv1.AdminHumanRoomRobotConfig {
|
||||
config = withHumanRoomRobotDefaults(config)
|
||||
out := &roomv1.AdminHumanRoomRobotConfig{
|
||||
AppCode: config.AppCode,
|
||||
Enabled: config.Enabled,
|
||||
CandidateRoomMaxOnline: config.CandidateRoomMaxOnline,
|
||||
RoomFullStopOnline: config.RoomFullStopOnline,
|
||||
RoomTargetMinOnline: config.RoomTargetMinOnline,
|
||||
RoomTargetMaxOnline: config.RoomTargetMaxOnline,
|
||||
RobotStayMinMs: config.RobotStayMinMS,
|
||||
RobotStayMaxMs: config.RobotStayMaxMS,
|
||||
RobotReplaceMinMs: config.RobotReplaceMinMS,
|
||||
RobotReplaceMaxMs: config.RobotReplaceMaxMS,
|
||||
NormalGiftIntervalMs: config.NormalGiftIntervalMS,
|
||||
NormalGiftIntervalMinMs: config.NormalGiftIntervalMinMS,
|
||||
NormalGiftIntervalMaxMs: config.NormalGiftIntervalMaxMS,
|
||||
GiftIds: append([]string(nil), config.GiftIDs...),
|
||||
LuckyGiftIds: append([]string(nil), config.LuckyGiftIDs...),
|
||||
SuperLuckyGiftIds: append([]string(nil), config.SuperLuckyGiftIDs...),
|
||||
LuckyComboMin: config.LuckyComboMin,
|
||||
LuckyComboMax: config.LuckyComboMax,
|
||||
LuckyPauseMinMs: config.LuckyPauseMinMS,
|
||||
LuckyPauseMaxMs: config.LuckyPauseMaxMS,
|
||||
MaxGiftSenders: config.MaxGiftSenders,
|
||||
UpdatedByAdminId: config.UpdatedByAdminID,
|
||||
CreatedAtMs: config.CreatedAtMS,
|
||||
UpdatedAtMs: config.UpdatedAtMS,
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func humanRoomRobotCommandMeta(config HumanRoomRobotConfig, roomID string, actorUserID int64, suffix string) *roomv1.RequestMeta {
|
||||
commandID := fmt.Sprintf("human-room-robot:%s:%s", roomID, strings.TrimSpace(suffix))
|
||||
if len(commandID) > 128 {
|
||||
commandID = commandID[:128]
|
||||
}
|
||||
return &roomv1.RequestMeta{
|
||||
RequestId: commandID,
|
||||
CommandId: commandID,
|
||||
ActorUserId: actorUserID,
|
||||
RoomId: roomID,
|
||||
AppCode: config.AppCode,
|
||||
SentAtMs: time.Now().UTC().UnixMilli(),
|
||||
}
|
||||
}
|
||||
|
||||
func humanRoomRealOnlineCount(users []*roomv1.RoomUser, robotIDs map[int64]bool) int {
|
||||
count := 0
|
||||
for _, user := range users {
|
||||
if user.GetUserId() <= 0 || robotIDs[user.GetUserId()] {
|
||||
continue
|
||||
}
|
||||
count++
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func allHumanRoomRobotIDs(config HumanRoomRobotConfig) map[int64]bool {
|
||||
out := make(map[int64]bool)
|
||||
for _, pool := range config.CountryPools {
|
||||
for _, id := range pool.RobotUserIDs {
|
||||
if id > 0 {
|
||||
out[id] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func freeSeatNumbers(seats []*roomv1.SeatState) []int32 {
|
||||
out := make([]int32, 0, len(seats))
|
||||
for _, seat := range seats {
|
||||
if seat.GetSeatNo() > 0 && seat.GetUserId() == 0 && !seat.GetLocked() {
|
||||
out = append(out, seat.GetSeatNo())
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestHumanRoomRobotGiftSenderLimit(t *testing.T) {
|
||||
activity := newRobotRoomActivity([]int64{101, 102, 103, 104})
|
||||
for _, userID := range []int64{101, 102, 103, 104} {
|
||||
activity.markActive(userID)
|
||||
}
|
||||
|
||||
markInitialHumanRoomGiftSenders(activity, []int64{101, 102, 103, 104}, 2)
|
||||
if got := activity.giftSenderCount(); got != 2 {
|
||||
t.Fatalf("gift sender count mismatch: got %d want 2", got)
|
||||
}
|
||||
if activity.markGiftSenderWithinLimit(104, 2) {
|
||||
t.Fatalf("gift sender limit allowed one more sender")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHumanRoomRobotNormalGiftDelayRange(t *testing.T) {
|
||||
rng := rand.New(rand.NewSource(1))
|
||||
config := HumanRoomRobotConfig{NormalGiftIntervalMinMS: 1000, NormalGiftIntervalMaxMS: 20000}
|
||||
for i := 0; i < 100; i++ {
|
||||
delay := humanRoomRobotNormalGiftDelay(config, rng)
|
||||
if delay < time.Second || delay > 20*time.Second {
|
||||
t.Fatalf("gift delay out of range: %s", delay)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandomHumanRoomTargetOnlineRange(t *testing.T) {
|
||||
config := HumanRoomRobotConfig{RoomTargetMinOnline: 8, RoomTargetMaxOnline: 10}
|
||||
for i := 0; i < 100; i++ {
|
||||
target := randomHumanRoomTargetOnline(config)
|
||||
if target < 8 || target > 10 {
|
||||
t.Fatalf("target online out of range: %d", target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandomHumanRoomTargetOnlineLegacyFixedValue(t *testing.T) {
|
||||
config := HumanRoomRobotConfig{RoomFullStopOnline: 10}
|
||||
for i := 0; i < 20; i++ {
|
||||
if target := randomHumanRoomTargetOnline(config); target != 10 {
|
||||
t.Fatalf("legacy target online mismatch: got %d want 10", target)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -38,6 +38,7 @@ type roomListCursor struct {
|
||||
Query string `json:"query,omitempty"`
|
||||
CountryCode string `json:"country_code,omitempty"`
|
||||
ViewerCountry string `json:"viewer_country,omitempty"`
|
||||
AllRegions bool `json:"all_regions,omitempty"`
|
||||
SortScore int64 `json:"sort_score,omitempty"`
|
||||
CreatedAtMS int64 `json:"created_at_ms,omitempty"`
|
||||
UpdatedAtMS int64 `json:"updated_at_ms,omitempty"`
|
||||
@ -70,7 +71,8 @@ func (s *Service) ListRooms(ctx context.Context, req *roomv1.ListRoomsRequest) (
|
||||
}
|
||||
countryCode := normalizeRoomCountryCode(req.GetCountryCode())
|
||||
viewerCountryCode := normalizeRoomCountryCode(req.GetViewerCountryCode())
|
||||
cursor, err := decodeRoomListCursor(tab, query, countryCode, viewerCountryCode, req.GetCursor())
|
||||
allVisibleRegions := req.GetAllVisibleRegions()
|
||||
cursor, err := decodeRoomListCursor(tab, query, countryCode, viewerCountryCode, allVisibleRegions, req.GetCursor())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -78,6 +80,7 @@ func (s *Service) ListRooms(ctx context.Context, req *roomv1.ListRoomsRequest) (
|
||||
entries, err := s.repository.ListRoomListEntries(ctx, RoomListQuery{
|
||||
AppCode: appcode.FromContext(ctx),
|
||||
VisibleRegionID: normalizeVisibleRegionID(req.GetVisibleRegionId()),
|
||||
AllVisibleRegions: allVisibleRegions,
|
||||
Tab: tab,
|
||||
Query: query,
|
||||
CountryCode: countryCode,
|
||||
@ -96,7 +99,7 @@ func (s *Service) ListRooms(ctx context.Context, req *roomv1.ListRoomsRequest) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return roomListResponseFromEntries(tab, query, countryCode, viewerCountryCode, entries, limit), nil
|
||||
return roomListResponseFromEntries(tab, query, countryCode, viewerCountryCode, allVisibleRegions, entries, limit), nil
|
||||
}
|
||||
|
||||
// ListRoomFeeds 查询 Mine 页 visited/friend/following/followed 房间流。
|
||||
@ -118,7 +121,7 @@ func (s *Service) ListRoomFeeds(ctx context.Context, req *roomv1.ListRoomFeedsRe
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cursor, err := decodeRoomListCursor(tab, query, "", "", req.GetCursor())
|
||||
cursor, err := decodeRoomListCursor(tab, query, "", "", false, req.GetCursor())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -166,7 +169,7 @@ func (s *Service) ListRoomFeeds(ctx context.Context, req *roomv1.ListRoomFeedsRe
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return roomListResponseFromEntries(tab, query, "", "", entries, limit), nil
|
||||
return roomListResponseFromEntries(tab, query, "", "", false, entries, limit), nil
|
||||
}
|
||||
|
||||
// GetMyRoom 查询当前用户自己创建的房间,不依赖 room_list_entries 投影命中。
|
||||
@ -199,12 +202,12 @@ func (s *Service) GetMyRoom(ctx context.Context, req *roomv1.GetMyRoomRequest) (
|
||||
}, nil
|
||||
}
|
||||
|
||||
func roomListResponseFromEntries(tab string, query string, countryCode string, viewerCountryCode string, entries []RoomListEntry, limit int) *roomv1.ListRoomsResponse {
|
||||
func roomListResponseFromEntries(tab string, query string, countryCode string, viewerCountryCode string, allRegions bool, entries []RoomListEntry, limit int) *roomv1.ListRoomsResponse {
|
||||
nextCursor := ""
|
||||
if len(entries) > limit {
|
||||
// 多查一条用于判断是否存在下一页;返回数据只包含请求的 limit 条。
|
||||
last := entries[limit-1]
|
||||
nextCursor = encodeRoomListCursor(tab, query, countryCode, viewerCountryCode, last)
|
||||
nextCursor = encodeRoomListCursor(tab, query, countryCode, viewerCountryCode, allRegions, last)
|
||||
entries = entries[:limit]
|
||||
}
|
||||
|
||||
@ -409,10 +412,10 @@ func normalizeRoomCountryCode(countryCode string) string {
|
||||
}
|
||||
|
||||
// decodeRoomListCursor 校验不透明 cursor 和当前 tab 一致,禁止客户端跨排序维度复用游标。
|
||||
func decodeRoomListCursor(tab string, query string, countryCode string, viewerCountryCode string, encoded string) (roomListCursor, error) {
|
||||
func decodeRoomListCursor(tab string, query string, countryCode string, viewerCountryCode string, allRegions bool, encoded string) (roomListCursor, error) {
|
||||
encoded = strings.TrimSpace(encoded)
|
||||
if encoded == "" {
|
||||
return roomListCursor{Tab: tab, Query: query, CountryCode: countryCode, ViewerCountry: viewerCountryCode}, nil
|
||||
return roomListCursor{Tab: tab, Query: query, CountryCode: countryCode, ViewerCountry: viewerCountryCode, AllRegions: allRegions}, nil
|
||||
}
|
||||
|
||||
payload, err := base64.RawURLEncoding.DecodeString(encoded)
|
||||
@ -424,7 +427,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.RoomID == "" {
|
||||
if cursor.Tab != tab || cursor.Query != query || cursor.CountryCode != countryCode || cursor.ViewerCountry != viewerCountryCode || cursor.AllRegions != allRegions || cursor.RoomID == "" {
|
||||
return roomListCursor{}, xerr.New(xerr.InvalidArgument, "cursor is invalid")
|
||||
}
|
||||
|
||||
@ -433,12 +436,13 @@ func decodeRoomListCursor(tab string, query string, countryCode string, viewerCo
|
||||
|
||||
// encodeRoomListCursor 把最后一条列表记录编码成下一页边界。
|
||||
// cursor 不暴露契约语义,后续调整排序字段时可以只兼容服务端解析逻辑。
|
||||
func encodeRoomListCursor(tab string, query string, countryCode string, viewerCountryCode string, entry RoomListEntry) string {
|
||||
func encodeRoomListCursor(tab string, query string, countryCode string, viewerCountryCode string, allRegions bool, entry RoomListEntry) string {
|
||||
cursor := roomListCursor{
|
||||
Tab: tab,
|
||||
Query: query,
|
||||
CountryCode: countryCode,
|
||||
ViewerCountry: viewerCountryCode,
|
||||
AllRegions: allRegions,
|
||||
SortScore: entry.SortScore,
|
||||
CreatedAtMS: entry.CreatedAtMS,
|
||||
UpdatedAtMS: entry.UpdatedAtMS,
|
||||
|
||||
@ -17,6 +17,8 @@ const (
|
||||
outboxRetryExponentialBackoff = "exponential_backoff"
|
||||
// outboxWorkerName 固定写入日志,便于后续按 worker 聚合检索。
|
||||
outboxWorkerName = "room_outbox"
|
||||
// robotOutboxWorkerName 固定标识机器人展示事件通道,避免和主 room_outbox 监控混淆。
|
||||
robotOutboxWorkerName = "room_robot_outbox"
|
||||
)
|
||||
|
||||
// OutboxWorkerOptions 控制 room_outbox pending 事件的持续补偿循环。
|
||||
@ -88,16 +90,25 @@ func normalizeOutboxWorkerOptions(options OutboxWorkerOptions) OutboxWorkerOptio
|
||||
|
||||
// RunOutboxWorker 持续扫描 pending outbox;它不执行房间命令,只投递已持久化事件。
|
||||
func (s *Service) RunOutboxWorker(ctx context.Context, options OutboxWorkerOptions) {
|
||||
s.runOutboxWorker(ctx, options, outboxWorkerName, s.ProcessPendingOutbox)
|
||||
}
|
||||
|
||||
// RunRobotOutboxWorker 持续扫描机器人房间展示 outbox;它和主 room_outbox 完全分开抢占。
|
||||
func (s *Service) RunRobotOutboxWorker(ctx context.Context, options OutboxWorkerOptions) {
|
||||
s.runOutboxWorker(ctx, options, robotOutboxWorkerName, s.ProcessPendingRobotOutbox)
|
||||
}
|
||||
|
||||
func (s *Service) runOutboxWorker(ctx context.Context, options OutboxWorkerOptions, workerName string, process func(context.Context, OutboxWorkerOptions) error) {
|
||||
options = normalizeOutboxWorkerOptions(options)
|
||||
if options.RetryStrategy != outboxRetryExponentialBackoff {
|
||||
// 配置层会拒绝未知策略;这里兜底避免测试或手写构造静默改变语义。
|
||||
logx.Error(ctx, "worker_stopped", fmt.Errorf("unsupported retry_strategy"), slog.String("worker", outboxWorkerName), slog.String("node_id", s.nodeID))
|
||||
logx.Error(ctx, "worker_stopped", fmt.Errorf("unsupported retry_strategy"), slog.String("worker", workerName), slog.String("node_id", s.nodeID))
|
||||
return
|
||||
}
|
||||
|
||||
// 启动后先执行一轮,避免服务刚恢复时还要等一个 poll interval 才补偿历史事件。
|
||||
if err := s.ProcessPendingOutbox(ctx, options); err != nil && ctx.Err() == nil {
|
||||
logx.Error(ctx, "worker_batch_failed", err, slog.String("worker", outboxWorkerName), slog.String("node_id", s.nodeID), slog.Int("batch_size", options.BatchSize))
|
||||
if err := process(ctx, options); err != nil && ctx.Err() == nil {
|
||||
logx.Error(ctx, "worker_batch_failed", err, slog.String("worker", workerName), slog.String("node_id", s.nodeID), slog.Int("batch_size", options.BatchSize))
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(options.PollInterval)
|
||||
@ -108,8 +119,8 @@ func (s *Service) RunOutboxWorker(ctx context.Context, options OutboxWorkerOptio
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
if err := s.ProcessPendingOutbox(ctx, options); err != nil && ctx.Err() == nil {
|
||||
logx.Error(ctx, "worker_batch_failed", err, slog.String("worker", outboxWorkerName), slog.String("node_id", s.nodeID), slog.Int("batch_size", options.BatchSize))
|
||||
if err := process(ctx, options); err != nil && ctx.Err() == nil {
|
||||
logx.Error(ctx, "worker_batch_failed", err, slog.String("worker", workerName), slog.String("node_id", s.nodeID), slog.Int("batch_size", options.BatchSize))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -117,13 +128,22 @@ func (s *Service) RunOutboxWorker(ctx context.Context, options OutboxWorkerOptio
|
||||
|
||||
// ProcessPendingOutbox 把待投递事件补偿性地推送给异步消费者。
|
||||
func (s *Service) ProcessPendingOutbox(ctx context.Context, options OutboxWorkerOptions) error {
|
||||
return s.processPendingOutbox(ctx, options, outboxWorkerName, false)
|
||||
}
|
||||
|
||||
// ProcessPendingRobotOutbox 把机器人展示事件补偿性地推送给独立机器人异步消费者。
|
||||
func (s *Service) ProcessPendingRobotOutbox(ctx context.Context, options OutboxWorkerOptions) error {
|
||||
return s.processPendingOutbox(ctx, options, robotOutboxWorkerName, true)
|
||||
}
|
||||
|
||||
func (s *Service) processPendingOutbox(ctx context.Context, options OutboxWorkerOptions, workerName string, robotLane bool) error {
|
||||
options = normalizeOutboxWorkerOptions(options)
|
||||
if options.RetryStrategy != outboxRetryExponentialBackoff {
|
||||
return fmt.Errorf("unsupported outbox retry_strategy %q", options.RetryStrategy)
|
||||
}
|
||||
|
||||
// 补偿 worker 先抢占 pending/retryable 事件,再投递,避免多机同时处理同一批。
|
||||
records, err := s.repository.ClaimPendingOutbox(ctx, s.nodeID, options.BatchSize, time.Now().UTC().Add(options.PublishTimeout).UnixMilli())
|
||||
records, err := s.claimPendingOutbox(ctx, robotLane, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -138,13 +158,13 @@ func (s *Service) ProcessPendingOutbox(ctx context.Context, options OutboxWorker
|
||||
if record.RetryCount >= options.MaxRetryCount {
|
||||
// 已达到最大失败次数的历史事件直接转死信,防止每轮 worker 继续打外部系统。
|
||||
markCtx, markCancel := context.WithTimeout(appcode.WithContext(context.Background(), record.AppCode), options.PublishTimeout)
|
||||
markErr := s.repository.MarkOutboxDead(markCtx, record.EventID, deadLetterReason(record))
|
||||
markErr := s.markOutboxDead(markCtx, robotLane, record.EventID, deadLetterReason(record))
|
||||
markCancel()
|
||||
if markErr != nil {
|
||||
return markErr
|
||||
}
|
||||
logx.Error(ctx, "outbox_dead_letter", nil,
|
||||
slog.String("worker", outboxWorkerName),
|
||||
slog.String("worker", workerName),
|
||||
slog.String("node_id", s.nodeID),
|
||||
slog.String("event_id", record.EventID),
|
||||
slog.String("event_type", record.EventType),
|
||||
@ -157,20 +177,20 @@ func (s *Service) ProcessPendingOutbox(ctx context.Context, options OutboxWorker
|
||||
|
||||
publishCtx, cancel := context.WithTimeout(appcode.WithContext(context.Background(), record.AppCode), options.PublishTimeout)
|
||||
// 发布上下文不继承 worker ctx,避免 shutdown 取消导致已开始的单条外部投递无界处于未知状态。
|
||||
err := s.publishOutboxRecord(publishCtx, record)
|
||||
err := s.publishOutboxRecord(publishCtx, record, robotLane)
|
||||
cancel()
|
||||
if err != nil {
|
||||
// 投递失败转为 retryable,并写入指数退避时间,等待下一轮 worker 到期后再抢占。
|
||||
nextRetryAtMS := time.Now().UTC().Add(outboxBackoff(record.RetryCount+1, options)).UnixMilli()
|
||||
markCtx, markCancel := context.WithTimeout(appcode.WithContext(context.Background(), record.AppCode), options.PublishTimeout)
|
||||
markErr := s.repository.MarkOutboxRetryable(markCtx, record.EventID, trimOutboxError(err.Error()), nextRetryAtMS)
|
||||
markErr := s.markOutboxRetryable(markCtx, robotLane, record.EventID, trimOutboxError(err.Error()), nextRetryAtMS)
|
||||
markCancel()
|
||||
if markErr != nil {
|
||||
return markErr
|
||||
}
|
||||
|
||||
logx.Warn(ctx, "outbox_publish_retryable",
|
||||
slog.String("worker", outboxWorkerName),
|
||||
slog.String("worker", workerName),
|
||||
slog.String("node_id", s.nodeID),
|
||||
slog.String("event_id", record.EventID),
|
||||
slog.String("event_type", record.EventType),
|
||||
@ -184,14 +204,14 @@ func (s *Service) ProcessPendingOutbox(ctx context.Context, options OutboxWorker
|
||||
|
||||
// 只有外部发布成功后才能标记 delivered。
|
||||
markCtx, markCancel := context.WithTimeout(appcode.WithContext(context.Background(), record.AppCode), options.PublishTimeout)
|
||||
markErr := s.repository.MarkOutboxDelivered(markCtx, record.EventID)
|
||||
markErr := s.markOutboxDelivered(markCtx, robotLane, record.EventID)
|
||||
markCancel()
|
||||
if markErr != nil {
|
||||
return markErr
|
||||
}
|
||||
|
||||
logx.Info(ctx, "outbox_delivered",
|
||||
slog.String("worker", outboxWorkerName),
|
||||
slog.String("worker", workerName),
|
||||
slog.String("node_id", s.nodeID),
|
||||
slog.String("event_id", record.EventID),
|
||||
slog.String("event_type", record.EventType),
|
||||
@ -203,11 +223,46 @@ func (s *Service) ProcessPendingOutbox(ctx context.Context, options OutboxWorker
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) publishOutboxRecord(ctx context.Context, record outbox.Record) error {
|
||||
func (s *Service) claimPendingOutbox(ctx context.Context, robotLane bool, options OutboxWorkerOptions) ([]outbox.Record, error) {
|
||||
lockUntilMS := time.Now().UTC().Add(options.PublishTimeout).UnixMilli()
|
||||
if robotLane {
|
||||
return s.repository.ClaimPendingRobotOutbox(ctx, s.nodeID, options.BatchSize, lockUntilMS)
|
||||
}
|
||||
return s.repository.ClaimPendingOutbox(ctx, s.nodeID, options.BatchSize, lockUntilMS)
|
||||
}
|
||||
|
||||
func (s *Service) markOutboxDelivered(ctx context.Context, robotLane bool, eventID string) error {
|
||||
if robotLane {
|
||||
return s.repository.MarkRobotOutboxDelivered(ctx, eventID)
|
||||
}
|
||||
return s.repository.MarkOutboxDelivered(ctx, eventID)
|
||||
}
|
||||
|
||||
func (s *Service) markOutboxRetryable(ctx context.Context, robotLane bool, eventID string, lastErr string, nextRetryAtMS int64) error {
|
||||
if robotLane {
|
||||
return s.repository.MarkRobotOutboxRetryable(ctx, eventID, lastErr, nextRetryAtMS)
|
||||
}
|
||||
return s.repository.MarkOutboxRetryable(ctx, eventID, lastErr, nextRetryAtMS)
|
||||
}
|
||||
|
||||
func (s *Service) markOutboxDead(ctx context.Context, robotLane bool, eventID string, lastErr string) error {
|
||||
if robotLane {
|
||||
return s.repository.MarkRobotOutboxDead(ctx, eventID, lastErr)
|
||||
}
|
||||
return s.repository.MarkOutboxDead(ctx, eventID, lastErr)
|
||||
}
|
||||
|
||||
func (s *Service) publishOutboxRecord(ctx context.Context, record outbox.Record, robotLane bool) error {
|
||||
// Ignited 先安排延迟发射,再对外广播事件;如果 MQ 延迟调度不可用,本条 outbox 保持 retryable。
|
||||
if err := s.scheduleRoomRocketLaunchFromEnvelope(ctx, record.Envelope); err != nil {
|
||||
return err
|
||||
}
|
||||
if robotLane {
|
||||
if s.robotOutboxPublisher == nil {
|
||||
return nil
|
||||
}
|
||||
return s.robotOutboxPublisher.PublishOutboxEvent(ctx, record.Envelope)
|
||||
}
|
||||
if s.outboxPublisher == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -92,6 +92,7 @@ func (s *Service) mutateRoom(ctx context.Context, cmd command.Command, replayabl
|
||||
CreatedAtMS: now.UnixMilli(),
|
||||
},
|
||||
OutboxRecords: outboxRecords,
|
||||
RobotOutboxRecords: result.robotOutboxRecords,
|
||||
RoomStatus: result.roomStatus,
|
||||
RoomSeatCount: result.roomSeatCount,
|
||||
RoomPasswordHash: result.roomPasswordHash,
|
||||
|
||||
@ -414,8 +414,18 @@ func stalePresenceUserIDs(current *state.RoomState, cutoffMs int64) []int64 {
|
||||
return nil
|
||||
}
|
||||
|
||||
robotUserIDs := map[int64]bool(nil)
|
||||
if current.RoomExt[roomExtRobotRoomKey] == "true" {
|
||||
// 机器人房的内部机器人没有客户端心跳;它们的生命周期由机器人房配置和运行时管理,
|
||||
// 不能被普通用户 stale worker 清掉,否则送礼循环会因为 sender/target 不在房间而失败。
|
||||
robotUserIDs = parseInt64CSV(current.RoomExt[roomExtRobotUserIDsKey])
|
||||
}
|
||||
|
||||
userIDs := make([]int64, 0)
|
||||
for userID, userState := range current.OnlineUsers {
|
||||
if robotUserIDs[userID] {
|
||||
continue
|
||||
}
|
||||
if userState != nil && userState.LastSeenAtMS <= cutoffMs {
|
||||
userIDs = append(userIDs, userID)
|
||||
}
|
||||
|
||||
@ -163,7 +163,9 @@ func replay(current *state.RoomState, cmd command.Command, committedAtMS int64)
|
||||
case *command.RoomHeartbeat:
|
||||
existing, exists := current.OnlineUsers[typed.ActorUserID()]
|
||||
if !exists {
|
||||
return fmt.Errorf("room_heartbeat replay actor is not in room: %d", typed.ActorUserID())
|
||||
// 心跳和离房可能在同一房间版本附近并发落库;如果离房先被重放,随后到达的旧心跳
|
||||
// 不能重新创建 presence,也不能让整个 Room Cell 恢复失败。
|
||||
return nil
|
||||
}
|
||||
// 心跳只刷新 last_seen,不产生用户进房事件。
|
||||
existing.LastSeenAtMS = typed.SentAtMS
|
||||
|
||||
@ -59,6 +59,8 @@ type MutationCommit struct {
|
||||
Command CommandRecord
|
||||
// OutboxRecords 是本次命令产生的房间外事件。
|
||||
OutboxRecords []outbox.Record
|
||||
// RobotOutboxRecords 是机器人房间必要展示事件,必须和命令日志同事务写入独立 robot outbox。
|
||||
RobotOutboxRecords []outbox.Record
|
||||
// RoomStatus 非空时同步更新 rooms 和 room_list_entries 的生命周期状态。
|
||||
RoomStatus string
|
||||
// RoomSeatCount 非 nil 时同步更新 rooms 元数据中的麦位总数。
|
||||
@ -258,6 +260,39 @@ type AdminCreateRoomPinInput struct {
|
||||
NowMS int64
|
||||
}
|
||||
|
||||
type HumanRoomRobotCountryPool struct {
|
||||
CountryCode string
|
||||
RobotUserIDs []int64
|
||||
}
|
||||
|
||||
type HumanRoomRobotConfig struct {
|
||||
AppCode string
|
||||
Enabled bool
|
||||
CandidateRoomMaxOnline int32
|
||||
RoomFullStopOnline int32
|
||||
RoomTargetMinOnline int32
|
||||
RoomTargetMaxOnline int32
|
||||
RobotStayMinMS int64
|
||||
RobotStayMaxMS int64
|
||||
RobotReplaceMinMS int64
|
||||
RobotReplaceMaxMS int64
|
||||
NormalGiftIntervalMS int64
|
||||
NormalGiftIntervalMinMS int64
|
||||
NormalGiftIntervalMaxMS int64
|
||||
GiftIDs []string
|
||||
LuckyGiftIDs []string
|
||||
SuperLuckyGiftIDs []string
|
||||
LuckyComboMin int64
|
||||
LuckyComboMax int64
|
||||
LuckyPauseMinMS int64
|
||||
LuckyPauseMaxMS int64
|
||||
MaxGiftSenders int64
|
||||
CountryPools []HumanRoomRobotCountryPool
|
||||
UpdatedByAdminID uint64
|
||||
CreatedAtMS int64
|
||||
UpdatedAtMS int64
|
||||
}
|
||||
|
||||
// RoomSeatConfig 是后台房间配置里控制创建/修改房间座位数的低频配置。
|
||||
type RoomSeatConfig struct {
|
||||
// AppCode 是配置所属 App。
|
||||
@ -330,6 +365,11 @@ type RobotRoomGiftRule struct {
|
||||
LuckyComboMax int64
|
||||
LuckyPauseMinMS int64
|
||||
LuckyPauseMaxMS int64
|
||||
RobotStayMinMS int64
|
||||
RobotStayMaxMS int64
|
||||
RobotReplaceMinMS int64
|
||||
RobotReplaceMaxMS int64
|
||||
MaxGiftSenders int64
|
||||
}
|
||||
|
||||
// RobotRoomConfig 是 room-service 持久化的机器人房间配置和账号占用事实。
|
||||
@ -340,9 +380,12 @@ type RobotRoomConfig struct {
|
||||
Title string
|
||||
CoverURL string
|
||||
VisibleRegionID int64
|
||||
OwnerCountryCode string
|
||||
Status string
|
||||
OwnerRobotUserID int64
|
||||
RobotUserIDs []int64
|
||||
ActiveRobotCount int32
|
||||
SeatCount int32
|
||||
GiftRule RobotRoomGiftRule
|
||||
CreatedByAdminID uint64
|
||||
CreatedAtMS int64
|
||||
@ -415,6 +458,8 @@ type RoomListQuery struct {
|
||||
AppCode string
|
||||
// VisibleRegionID 是服务端解析出的用户区域,客户端不能伪造。
|
||||
VisibleRegionID int64
|
||||
// AllVisibleRegions 只服务后台白名单用户;为 true 时列表读模型不再按 VisibleRegionID 收敛。
|
||||
AllVisibleRegions bool
|
||||
// Tab 只允许 hot/new,决定公共发现列表排序字段。
|
||||
Tab string
|
||||
// OwnerUserID 保留给内部定向读模型;公开 Mine 顶部卡片走 GetMyRoom。
|
||||
@ -594,14 +639,24 @@ type Repository interface {
|
||||
SaveOutbox(ctx context.Context, records []outbox.Record) error
|
||||
// ListPendingOutbox 扫描待补偿投递事件。
|
||||
ListPendingOutbox(ctx context.Context, limit int) ([]outbox.Record, error)
|
||||
// ListPendingRobotOutbox 扫描机器人房间待补偿展示事件。
|
||||
ListPendingRobotOutbox(ctx context.Context, limit int) ([]outbox.Record, error)
|
||||
// ClaimPendingOutbox 抢占一批待投递事件,避免多 worker 同时投递同一批。
|
||||
ClaimPendingOutbox(ctx context.Context, workerID string, limit int, lockUntilMS int64) ([]outbox.Record, error)
|
||||
// ClaimPendingRobotOutbox 抢占机器人房间展示事件,避免机器人流量占用主 room_outbox worker。
|
||||
ClaimPendingRobotOutbox(ctx context.Context, workerID string, limit int, lockUntilMS int64) ([]outbox.Record, error)
|
||||
// MarkOutboxDelivered 标记事件已经投递成功。
|
||||
MarkOutboxDelivered(ctx context.Context, eventID string) error
|
||||
// MarkRobotOutboxDelivered 标记机器人展示事件已经投递成功。
|
||||
MarkRobotOutboxDelivered(ctx context.Context, eventID string) error
|
||||
// MarkOutboxRetryable 记录一次投递失败,并写入下一次允许抢占的退避时间。
|
||||
MarkOutboxRetryable(ctx context.Context, eventID string, lastErr string, nextRetryAtMS int64) error
|
||||
// MarkRobotOutboxRetryable 记录机器人展示事件投递失败,并写入独立重试退避。
|
||||
MarkRobotOutboxRetryable(ctx context.Context, eventID string, lastErr string, nextRetryAtMS int64) error
|
||||
// MarkOutboxDead 把超过最大重试次数的事件转入 failed,避免固定污染日志和外部依赖。
|
||||
MarkOutboxDead(ctx context.Context, eventID string, lastErr string) error
|
||||
// MarkRobotOutboxDead 把超过最大重试次数的机器人展示事件转入 failed。
|
||||
MarkRobotOutboxDead(ctx context.Context, eventID string, lastErr string) error
|
||||
// UpsertRoomListEntry 写入或更新房间列表读模型;失败不应破坏 Room Cell 已提交状态。
|
||||
UpsertRoomListEntry(ctx context.Context, entry RoomListEntry) error
|
||||
// ListRoomListEntries 按区域和 tab 查询房间列表,不访问 Room Cell 内存。
|
||||
@ -639,6 +694,9 @@ type Repository interface {
|
||||
UpdateRobotRoomStatus(ctx context.Context, roomID string, status string, nowMS int64) (RobotRoomConfig, bool, error)
|
||||
OccupiedRobotUserIDs(ctx context.Context, userIDs []int64) (map[int64]bool, error)
|
||||
ListActiveRobotRooms(ctx context.Context) ([]RobotRoomConfig, error)
|
||||
GetHumanRoomRobotConfig(ctx context.Context) (HumanRoomRobotConfig, bool, error)
|
||||
UpsertHumanRoomRobotConfig(ctx context.Context, config HumanRoomRobotConfig) (HumanRoomRobotConfig, error)
|
||||
ListHumanRobotCandidateRooms(ctx context.Context, appCode string, countryCode string, maxOnline int32, fullStopOnline int32, limit int) ([]RoomListEntry, error)
|
||||
}
|
||||
|
||||
// RoomPresenceSnapshot 是 repository 投影接口的稳定入参,避免存储层反向依赖 protobuf。
|
||||
|
||||
@ -35,6 +35,10 @@ type Config struct {
|
||||
RTCUserRemover integration.RTCUserRemover
|
||||
// RoomRocketLaunchScheduler 把倒计时发射唤醒交给外部延迟消息,避免只靠已加载 Cell 扫描。
|
||||
RoomRocketLaunchScheduler integration.RoomRocketLaunchScheduler
|
||||
// RobotOutboxPublisher 专门投递机器人房间展示事件,避免机器人流量进入真人房间 room_outbox 通道。
|
||||
RobotOutboxPublisher integration.OutboxPublisher
|
||||
// HumanRobotPoolProvider 自动读取全站机器人账号和用户国家,用于真人房间机器人运行时按国家分组。
|
||||
HumanRobotPoolProvider integration.HumanRoomRobotPoolProvider
|
||||
// RoomGiftLeaderboard 是跨房间贡献榜读模型,SendGift 提交后 best-effort 写入。
|
||||
RoomGiftLeaderboard RoomGiftLeaderboardStore
|
||||
// LuckyGiftSendLocker 串行化同一用户的幸运礼物扣费、抽奖和同步返奖链路。
|
||||
@ -73,6 +77,10 @@ type Service struct {
|
||||
syncPublisher integration.RoomEventPublisher
|
||||
// outboxPublisher 是补偿 worker 对外部消费者的异步投递抽象。
|
||||
outboxPublisher integration.OutboxPublisher
|
||||
// robotOutboxPublisher 只服务机器人房间必要展示事件,和主 room_outbox 发布器隔离。
|
||||
robotOutboxPublisher integration.OutboxPublisher
|
||||
// humanRobotPoolProvider 运行时自动获取全站机器人池,避免后台手工维护国家机器人池。
|
||||
humanRobotPoolProvider integration.HumanRoomRobotPoolProvider
|
||||
// roomRocketLaunchScheduler 在 ignited outbox 投递成功后安排 launch_at_ms 唤醒。
|
||||
roomRocketLaunchScheduler integration.RoomRocketLaunchScheduler
|
||||
// roomGiftLeaderboard 只保存房间维度贡献值 zset,不承载 Room Cell 核心状态。
|
||||
@ -93,8 +101,21 @@ type Service struct {
|
||||
|
||||
// robotRuntimeMu 保护后台机器人房间运行循环;配置变更时要取消旧循环后重建。
|
||||
robotRuntimeMu sync.Mutex
|
||||
// robotRuntimes 保存 room_id -> cancel,避免同一房间被重复启动多个送礼循环。
|
||||
robotRuntimes map[string]context.CancelFunc
|
||||
// robotRuntimes 保存 room_id -> runtime,避免同一房间被重复启动多个送礼循环。
|
||||
robotRuntimes map[string]robotRoomRuntime
|
||||
// humanRobotRuntimeMu 保护真人房间机器人运行循环,和机器人房间 runtime 分开避免互相取消。
|
||||
humanRobotRuntimeMu sync.Mutex
|
||||
// humanRobotRuntimes 保存 room_id -> runtime,避免同一真人房间被重复补机器人。
|
||||
humanRobotRuntimes map[string]robotRoomRuntime
|
||||
}
|
||||
|
||||
type robotRoomRuntime struct {
|
||||
// cancel 停止当前房间的所有机器人送礼 goroutine。
|
||||
cancel context.CancelFunc
|
||||
// token 区分同一房间的前后两次启动,旧 goroutine 退出时不能误删新 runtime。
|
||||
token string
|
||||
// configUpdatedAtMS 记录启动 runtime 时采用的配置版本;后台改配置后扫描器据此重启真人房间机器人 runtime。
|
||||
configUpdatedAtMS int64
|
||||
}
|
||||
|
||||
// mutationResult 是命令在 Room Cell 内执行后的统一结果包。
|
||||
@ -131,6 +152,8 @@ type mutationResult struct {
|
||||
syncEvent *tencentim.RoomEvent
|
||||
// outboxRecords 是本次命令已经持久化的房间事实,提交后可投给 activity 等外部消费者。
|
||||
outboxRecords []outbox.Record
|
||||
// robotOutboxRecords 是机器人房间必要展示事实,只进入 robot outbox/worker,不占主 room_outbox。
|
||||
robotOutboxRecords []outbox.Record
|
||||
// roomStatus 非空时代表命令提交时需要同步更新 rooms 和列表投影生命周期状态。
|
||||
roomStatus string
|
||||
// roomSeatCount 非 nil 时代表命令提交时需要同步更新 rooms 元数据座位数。
|
||||
@ -205,13 +228,16 @@ func New(cfg Config, directory router.Directory, repository Repository, wallet i
|
||||
luckyGift: luckyGiftClient,
|
||||
syncPublisher: syncPublisher,
|
||||
outboxPublisher: outboxPublisher,
|
||||
robotOutboxPublisher: cfg.RobotOutboxPublisher,
|
||||
humanRobotPoolProvider: cfg.HumanRobotPoolProvider,
|
||||
roomRocketLaunchScheduler: cfg.RoomRocketLaunchScheduler,
|
||||
roomGiftLeaderboard: cfg.RoomGiftLeaderboard,
|
||||
luckyGiftSendLocker: cfg.LuckyGiftSendLocker,
|
||||
luckyGiftSendLockTTL: luckyGiftSendLockTTL,
|
||||
rtcUserRemover: cfg.RTCUserRemover,
|
||||
cells: make(map[string]*cell.RoomCell),
|
||||
robotRuntimes: make(map[string]context.CancelFunc),
|
||||
robotRuntimes: make(map[string]robotRoomRuntime),
|
||||
humanRobotRuntimes: make(map[string]robotRoomRuntime),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -98,6 +98,61 @@ func TestRoomUserGiftValueFollowsMicChangeAndResetsAfterLeave(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRobotGiftSkipsMainHeatAndRankOutbox(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
repository := mysqltest.NewRepository(t)
|
||||
now := &fixedRoomRocketClock{now: time.Date(2026, 6, 8, 11, 0, 0, 0, time.UTC)}
|
||||
wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{{
|
||||
BillingReceiptId: "receipt-robot-display-only",
|
||||
CoinSpent: 100,
|
||||
ChargeAmount: 100,
|
||||
HeatValue: 100,
|
||||
ChargeAssetType: "ROBOT_COIN",
|
||||
GiftTypeCode: "robot",
|
||||
}}}
|
||||
svc := newUserGiftValueTestService(repository, wallet, now, "node-robot-gift-outbox-boundary")
|
||||
|
||||
roomID := "robot-room-outbox-boundary"
|
||||
senderID := int64(63001)
|
||||
targetID := int64(63002)
|
||||
createRocketRoom(t, ctx, svc, roomID, senderID, 9001)
|
||||
joinRocketRoom(t, ctx, svc, roomID, targetID)
|
||||
beforeMain := outboxEventCounts(t, ctx, repository)
|
||||
beforeRobot := robotOutboxEventCounts(t, ctx, repository)
|
||||
|
||||
if _, err := svc.RobotSendGift(ctx, roomservice.RobotSendGiftInput{
|
||||
Meta: rocketMeta(roomID, senderID, "robot-display-only"),
|
||||
TargetUserID: targetID,
|
||||
GiftID: "robot-display-gift",
|
||||
GiftCount: 1,
|
||||
RobotUserIDs: []int64{senderID, targetID},
|
||||
}); err != nil {
|
||||
t.Fatalf("robot send gift failed: %v", err)
|
||||
}
|
||||
|
||||
afterMain := outboxEventCounts(t, ctx, repository)
|
||||
if delta := afterMain["RoomGiftSent"] - beforeMain["RoomGiftSent"]; delta != 0 {
|
||||
t.Fatalf("robot gift must not create main gift outbox, delta=%d counts=%+v", delta, afterMain)
|
||||
}
|
||||
if delta := afterMain["RoomHeatChanged"] - beforeMain["RoomHeatChanged"]; delta != 0 {
|
||||
t.Fatalf("robot gift must not create main heat outbox, delta=%d counts=%+v", delta, afterMain)
|
||||
}
|
||||
if delta := afterMain["RoomRankChanged"] - beforeMain["RoomRankChanged"]; delta != 0 {
|
||||
t.Fatalf("robot gift must not create main rank outbox, delta=%d counts=%+v", delta, afterMain)
|
||||
}
|
||||
|
||||
afterRobot := robotOutboxEventCounts(t, ctx, repository)
|
||||
if delta := afterRobot["RoomGiftSent"] - beforeRobot["RoomGiftSent"]; delta != 1 {
|
||||
t.Fatalf("robot gift must keep one robot gift display outbox, delta=%d counts=%+v", delta, afterRobot)
|
||||
}
|
||||
if delta := afterRobot["RoomHeatChanged"] - beforeRobot["RoomHeatChanged"]; delta != 1 {
|
||||
t.Fatalf("robot gift must keep robot heat display outbox, delta=%d counts=%+v", delta, afterRobot)
|
||||
}
|
||||
if delta := afterRobot["RoomRankChanged"] - beforeRobot["RoomRankChanged"]; delta != 1 {
|
||||
t.Fatalf("robot gift must keep robot rank display outbox, delta=%d counts=%+v", delta, afterRobot)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoomUserGiftValueRecoversFromCommandLog(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
repository := mysqltest.NewRepository(t)
|
||||
@ -159,6 +214,32 @@ func TestRoomUserGiftValueRecoversFromCommandLog(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func outboxEventCounts(t *testing.T, ctx context.Context, repository *mysqltest.Repository) map[string]int {
|
||||
t.Helper()
|
||||
records, err := repository.ListPendingOutbox(ctx, 200)
|
||||
if err != nil {
|
||||
t.Fatalf("list pending outbox failed: %v", err)
|
||||
}
|
||||
counts := make(map[string]int, len(records))
|
||||
for _, record := range records {
|
||||
counts[record.EventType]++
|
||||
}
|
||||
return counts
|
||||
}
|
||||
|
||||
func robotOutboxEventCounts(t *testing.T, ctx context.Context, repository *mysqltest.Repository) map[string]int {
|
||||
t.Helper()
|
||||
records, err := repository.ListPendingRobotOutbox(ctx, 200)
|
||||
if err != nil {
|
||||
t.Fatalf("list pending robot outbox failed: %v", err)
|
||||
}
|
||||
counts := make(map[string]int, len(records))
|
||||
for _, record := range records {
|
||||
counts[record.EventType]++
|
||||
}
|
||||
return counts
|
||||
}
|
||||
|
||||
func newUserGiftValueTestService(repository *mysqltest.Repository, wallet *rocketTestWallet, clock *fixedRoomRocketClock, nodeID string) *roomservice.Service {
|
||||
return roomservice.New(roomservice.Config{
|
||||
NodeID: nodeID,
|
||||
|
||||
@ -20,6 +20,11 @@ import (
|
||||
roomservice "hyapp/services/room-service/internal/room/service"
|
||||
)
|
||||
|
||||
const (
|
||||
roomOutboxTable = "room_outbox"
|
||||
roomRobotOutboxTable = "room_robot_outbox"
|
||||
)
|
||||
|
||||
// Repository 把 room-service 的权威状态持久化到 MySQL。
|
||||
type Repository struct {
|
||||
// db 是标准库连接池,所有 repository 方法都通过它访问 MySQL。
|
||||
@ -211,6 +216,26 @@ func (r *Repository) Migrate(ctx context.Context) error {
|
||||
KEY idx_room_outbox_event_created (app_code, event_type, created_at_ms, event_id),
|
||||
KEY idx_room_outbox_retention (app_code, status, updated_at_ms, event_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`,
|
||||
`CREATE TABLE IF NOT EXISTS room_robot_outbox (
|
||||
app_code VARCHAR(32) NOT NULL,
|
||||
event_id VARCHAR(128) NOT NULL,
|
||||
event_type VARCHAR(64) NOT NULL,
|
||||
room_id VARCHAR(64) NOT NULL,
|
||||
status VARCHAR(32) NOT NULL,
|
||||
worker_id VARCHAR(128) NOT NULL DEFAULT '',
|
||||
lock_until_ms BIGINT NULL,
|
||||
envelope LONGBLOB NOT NULL,
|
||||
created_at_ms BIGINT NOT NULL,
|
||||
retry_count INT NOT NULL DEFAULT 0,
|
||||
next_retry_at_ms BIGINT NOT NULL DEFAULT 0,
|
||||
last_error TEXT NULL,
|
||||
updated_at_ms BIGINT NOT NULL,
|
||||
PRIMARY KEY (app_code, event_id),
|
||||
KEY idx_room_robot_outbox_pending (app_code, status, next_retry_at_ms, created_at_ms, event_id),
|
||||
KEY idx_room_robot_outbox_claim (app_code, status, lock_until_ms, created_at_ms, event_id),
|
||||
KEY idx_room_robot_outbox_event_created (app_code, event_type, created_at_ms, event_id),
|
||||
KEY idx_room_robot_outbox_retention (app_code, status, updated_at_ms, event_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`,
|
||||
`CREATE TABLE IF NOT EXISTS room_user_feed_entries (
|
||||
app_code VARCHAR(32) NOT NULL,
|
||||
user_id BIGINT NOT NULL,
|
||||
@ -288,6 +313,8 @@ func (r *Repository) Migrate(ctx context.Context) error {
|
||||
status VARCHAR(32) NOT NULL,
|
||||
owner_robot_user_id BIGINT NOT NULL,
|
||||
robot_user_ids_json JSON NOT NULL,
|
||||
active_robot_count INT NOT NULL DEFAULT 0,
|
||||
seat_count INT NOT NULL DEFAULT 10,
|
||||
gift_ids_json JSON NOT NULL,
|
||||
lucky_gift_ids_json JSON NOT NULL,
|
||||
normal_gift_interval_ms BIGINT NOT NULL,
|
||||
@ -295,6 +322,11 @@ func (r *Repository) Migrate(ctx context.Context) error {
|
||||
lucky_combo_max BIGINT NOT NULL,
|
||||
lucky_pause_min_ms BIGINT NOT NULL,
|
||||
lucky_pause_max_ms BIGINT NOT NULL,
|
||||
robot_stay_min_ms BIGINT NOT NULL DEFAULT 180000,
|
||||
robot_stay_max_ms BIGINT NOT NULL DEFAULT 600000,
|
||||
robot_replace_min_ms BIGINT NOT NULL DEFAULT 0,
|
||||
robot_replace_max_ms BIGINT NOT NULL DEFAULT 60000,
|
||||
max_gift_senders BIGINT NOT NULL DEFAULT 1,
|
||||
created_by_admin_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
created_at_ms BIGINT NOT NULL,
|
||||
updated_at_ms BIGINT NOT NULL,
|
||||
@ -302,6 +334,35 @@ func (r *Repository) Migrate(ctx context.Context) error {
|
||||
KEY idx_room_robot_rooms_status (app_code, status, updated_at_ms, room_id),
|
||||
KEY idx_room_robot_rooms_owner (app_code, owner_robot_user_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`,
|
||||
`CREATE TABLE IF NOT EXISTS room_human_robot_configs (
|
||||
app_code VARCHAR(32) NOT NULL,
|
||||
enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
candidate_room_max_online INT NOT NULL DEFAULT 5,
|
||||
room_full_stop_online INT NOT NULL DEFAULT 10,
|
||||
room_target_min_online INT NOT NULL DEFAULT 8,
|
||||
room_target_max_online INT NOT NULL DEFAULT 10,
|
||||
robot_stay_min_ms BIGINT NOT NULL DEFAULT 60000,
|
||||
robot_stay_max_ms BIGINT NOT NULL DEFAULT 600000,
|
||||
robot_replace_min_ms BIGINT NOT NULL DEFAULT 60000,
|
||||
robot_replace_max_ms BIGINT NOT NULL DEFAULT 180000,
|
||||
normal_gift_interval_ms BIGINT NOT NULL DEFAULT 10000,
|
||||
normal_gift_interval_min_ms BIGINT NOT NULL DEFAULT 1000,
|
||||
normal_gift_interval_max_ms BIGINT NOT NULL DEFAULT 20000,
|
||||
gift_ids_json JSON NOT NULL,
|
||||
lucky_gift_ids_json JSON NOT NULL,
|
||||
super_lucky_gift_ids_json JSON NOT NULL,
|
||||
lucky_combo_min BIGINT NOT NULL DEFAULT 1,
|
||||
lucky_combo_max BIGINT NOT NULL DEFAULT 3,
|
||||
lucky_pause_min_ms BIGINT NOT NULL DEFAULT 5000,
|
||||
lucky_pause_max_ms BIGINT NOT NULL DEFAULT 20000,
|
||||
max_gift_senders BIGINT NOT NULL DEFAULT 1,
|
||||
country_pools_json JSON NOT NULL,
|
||||
updated_by_admin_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
created_at_ms BIGINT NOT NULL,
|
||||
updated_at_ms BIGINT NOT NULL,
|
||||
PRIMARY KEY (app_code),
|
||||
KEY idx_room_human_robot_enabled (app_code, enabled)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`,
|
||||
`INSERT IGNORE INTO room_seat_configs (app_code, allowed_seat_counts, default_seat_count, created_at_ms, updated_at_ms)
|
||||
VALUES ('lalu', '[10,15,20,25,30]', 15, 0, 0)`,
|
||||
`INSERT IGNORE INTO room_rocket_configs (
|
||||
@ -383,10 +444,69 @@ func (r *Repository) Migrate(ctx context.Context) error {
|
||||
if err := r.ensureRoomPinSchema(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := r.ensureRobotRoomBehaviorSchema(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := r.ensureHumanRobotConfigBehaviorSchema(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return r.ensureOutboxRetrySchema(ctx)
|
||||
}
|
||||
|
||||
func (r *Repository) ensureHumanRobotConfigBehaviorSchema(ctx context.Context) error {
|
||||
columns := []struct {
|
||||
name string
|
||||
statement string
|
||||
}{
|
||||
{name: "normal_gift_interval_min_ms", statement: `ALTER TABLE room_human_robot_configs ADD COLUMN normal_gift_interval_min_ms BIGINT NOT NULL DEFAULT 1000 AFTER normal_gift_interval_ms`},
|
||||
{name: "normal_gift_interval_max_ms", statement: `ALTER TABLE room_human_robot_configs ADD COLUMN normal_gift_interval_max_ms BIGINT NOT NULL DEFAULT 20000 AFTER normal_gift_interval_min_ms`},
|
||||
{name: "room_target_min_online", statement: `ALTER TABLE room_human_robot_configs ADD COLUMN room_target_min_online INT NOT NULL DEFAULT 8 AFTER room_full_stop_online`},
|
||||
{name: "room_target_max_online", statement: `ALTER TABLE room_human_robot_configs ADD COLUMN room_target_max_online INT NOT NULL DEFAULT 10 AFTER room_target_min_online`},
|
||||
}
|
||||
for _, column := range columns {
|
||||
exists, err := r.columnExists(ctx, "room_human_robot_configs", column.name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exists {
|
||||
continue
|
||||
}
|
||||
if _, err := r.db.ExecContext(ctx, column.statement); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Repository) ensureRobotRoomBehaviorSchema(ctx context.Context) error {
|
||||
columns := []struct {
|
||||
name string
|
||||
statement string
|
||||
}{
|
||||
{name: "active_robot_count", statement: `ALTER TABLE room_robot_rooms ADD COLUMN active_robot_count INT NOT NULL DEFAULT 0 AFTER robot_user_ids_json`},
|
||||
{name: "seat_count", statement: `ALTER TABLE room_robot_rooms ADD COLUMN seat_count INT NOT NULL DEFAULT 10 AFTER active_robot_count`},
|
||||
{name: "robot_stay_min_ms", statement: `ALTER TABLE room_robot_rooms ADD COLUMN robot_stay_min_ms BIGINT NOT NULL DEFAULT 180000 AFTER lucky_pause_max_ms`},
|
||||
{name: "robot_stay_max_ms", statement: `ALTER TABLE room_robot_rooms ADD COLUMN robot_stay_max_ms BIGINT NOT NULL DEFAULT 600000 AFTER robot_stay_min_ms`},
|
||||
{name: "robot_replace_min_ms", statement: `ALTER TABLE room_robot_rooms ADD COLUMN robot_replace_min_ms BIGINT NOT NULL DEFAULT 0 AFTER robot_stay_max_ms`},
|
||||
{name: "robot_replace_max_ms", statement: `ALTER TABLE room_robot_rooms ADD COLUMN robot_replace_max_ms BIGINT NOT NULL DEFAULT 60000 AFTER robot_replace_min_ms`},
|
||||
{name: "max_gift_senders", statement: `ALTER TABLE room_robot_rooms ADD COLUMN max_gift_senders BIGINT NOT NULL DEFAULT 1 AFTER robot_replace_max_ms`},
|
||||
}
|
||||
for _, column := range columns {
|
||||
exists, err := r.columnExists(ctx, "room_robot_rooms", column.name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exists {
|
||||
continue
|
||||
}
|
||||
if _, err := r.db.ExecContext(ctx, column.statement); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Repository) ensureRoomWeeklyContributionSchema(ctx context.Context) error {
|
||||
columns := []struct {
|
||||
column string
|
||||
@ -863,35 +983,15 @@ func (r *Repository) SaveMutation(ctx context.Context, commit roomservice.Mutati
|
||||
return err
|
||||
}
|
||||
|
||||
for _, record := range commit.OutboxRecords {
|
||||
record.AppCode = normalizedRecordAppCode(ctx, record.AppCode)
|
||||
if record.Envelope != nil {
|
||||
record.Envelope.AppCode = record.AppCode
|
||||
}
|
||||
envelopeBytes, err := proto.Marshal(record.Envelope)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
return err
|
||||
}
|
||||
if _, err := tx.ExecContext(ctx,
|
||||
`INSERT INTO room_outbox (app_code, event_id, event_type, room_id, status, envelope, created_at_ms, retry_count, next_retry_at_ms, last_error, updated_at_ms)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE event_id = event_id`,
|
||||
record.AppCode,
|
||||
record.EventID,
|
||||
record.EventType,
|
||||
record.RoomID,
|
||||
record.Status,
|
||||
envelopeBytes,
|
||||
record.CreatedAtMS,
|
||||
record.RetryCount,
|
||||
record.NextRetryAtMS,
|
||||
nullableString(record.LastError),
|
||||
record.CreatedAtMS,
|
||||
); err != nil {
|
||||
_ = tx.Rollback()
|
||||
return err
|
||||
}
|
||||
if err := r.insertRoomOutboxRecords(ctx, tx, roomOutboxTable, commit.OutboxRecords); err != nil {
|
||||
// 任一事件失败就回滚整批,避免 GiftSent/HeatChanged/RankChanged 部分缺失。
|
||||
_ = tx.Rollback()
|
||||
return err
|
||||
}
|
||||
if err := r.insertRoomOutboxRecords(ctx, tx, roomRobotOutboxTable, commit.RobotOutboxRecords); err != nil {
|
||||
// robot outbox 也和命令日志同事务提交,避免机器人礼物状态变了但客户端展示事件丢失。
|
||||
_ = tx.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.TrimSpace(commit.RoomStatus) != "" {
|
||||
@ -1075,6 +1175,44 @@ func (r *Repository) SaveMutation(ctx context.Context, commit roomservice.Mutati
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (r *Repository) insertRoomOutboxRecords(ctx context.Context, tx *sql.Tx, table string, records []outbox.Record) error {
|
||||
table = roomOutboxTableName(table)
|
||||
if len(records) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, record := range records {
|
||||
record.AppCode = normalizedRecordAppCode(ctx, record.AppCode)
|
||||
if record.Envelope != nil {
|
||||
record.Envelope.AppCode = record.AppCode
|
||||
}
|
||||
envelopeBytes, err := proto.Marshal(record.Envelope)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tx.ExecContext(ctx,
|
||||
`INSERT INTO `+table+` (app_code, event_id, event_type, room_id, status, envelope, created_at_ms, retry_count, next_retry_at_ms, last_error, updated_at_ms)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE event_id = event_id`,
|
||||
record.AppCode,
|
||||
record.EventID,
|
||||
record.EventType,
|
||||
record.RoomID,
|
||||
record.Status,
|
||||
envelopeBytes,
|
||||
record.CreatedAtMS,
|
||||
record.RetryCount,
|
||||
record.NextRetryAtMS,
|
||||
nullableString(record.LastError),
|
||||
record.CreatedAtMS,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetRoomSeatConfig 读取当前 App 的房间座位数配置。
|
||||
func (r *Repository) GetRoomSeatConfig(ctx context.Context) (roomservice.RoomSeatConfig, bool, error) {
|
||||
row := r.db.QueryRowContext(ctx,
|
||||
@ -1256,8 +1394,9 @@ func (r *Repository) ListRobotRooms(ctx context.Context, query roomservice.Robot
|
||||
args = append(args, pageSize, (page-1)*pageSize)
|
||||
rows, err := r.db.QueryContext(ctx,
|
||||
`SELECT app_code, room_id, room_short_id, title, cover_url, visible_region_id, status,
|
||||
owner_robot_user_id, robot_user_ids_json, gift_ids_json, lucky_gift_ids_json,
|
||||
owner_robot_user_id, robot_user_ids_json, active_robot_count, seat_count, gift_ids_json, lucky_gift_ids_json,
|
||||
normal_gift_interval_ms, lucky_combo_min, lucky_combo_max, lucky_pause_min_ms, lucky_pause_max_ms,
|
||||
robot_stay_min_ms, robot_stay_max_ms, robot_replace_min_ms, robot_replace_max_ms, max_gift_senders,
|
||||
created_by_admin_id, created_at_ms, updated_at_ms
|
||||
FROM room_robot_rooms `+where+`
|
||||
ORDER BY updated_at_ms DESC, room_id DESC
|
||||
@ -1276,8 +1415,9 @@ func (r *Repository) ListRobotRooms(ctx context.Context, query roomservice.Robot
|
||||
func (r *Repository) GetRobotRoom(ctx context.Context, roomID string) (roomservice.RobotRoomConfig, bool, error) {
|
||||
row := r.db.QueryRowContext(ctx,
|
||||
`SELECT app_code, room_id, room_short_id, title, cover_url, visible_region_id, status,
|
||||
owner_robot_user_id, robot_user_ids_json, gift_ids_json, lucky_gift_ids_json,
|
||||
owner_robot_user_id, robot_user_ids_json, active_robot_count, seat_count, gift_ids_json, lucky_gift_ids_json,
|
||||
normal_gift_interval_ms, lucky_combo_min, lucky_combo_max, lucky_pause_min_ms, lucky_pause_max_ms,
|
||||
robot_stay_min_ms, robot_stay_max_ms, robot_replace_min_ms, robot_replace_max_ms, max_gift_senders,
|
||||
created_by_admin_id, created_at_ms, updated_at_ms
|
||||
FROM room_robot_rooms
|
||||
WHERE app_code = ? AND room_id = ?`,
|
||||
@ -1324,10 +1464,11 @@ func (r *Repository) CreateRobotRoomConfig(ctx context.Context, input roomservic
|
||||
_, err = tx.ExecContext(ctx,
|
||||
`INSERT INTO room_robot_rooms (
|
||||
app_code, room_id, room_short_id, title, cover_url, visible_region_id, status,
|
||||
owner_robot_user_id, robot_user_ids_json, gift_ids_json, lucky_gift_ids_json,
|
||||
owner_robot_user_id, robot_user_ids_json, active_robot_count, seat_count, gift_ids_json, lucky_gift_ids_json,
|
||||
normal_gift_interval_ms, lucky_combo_min, lucky_combo_max, lucky_pause_min_ms, lucky_pause_max_ms,
|
||||
robot_stay_min_ms, robot_stay_max_ms, robot_replace_min_ms, robot_replace_max_ms, max_gift_senders,
|
||||
created_by_admin_id, created_at_ms, updated_at_ms
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
config.AppCode,
|
||||
config.RoomID,
|
||||
config.RoomShortID,
|
||||
@ -1337,6 +1478,8 @@ func (r *Repository) CreateRobotRoomConfig(ctx context.Context, input roomservic
|
||||
config.Status,
|
||||
config.OwnerRobotUserID,
|
||||
string(rawRobots),
|
||||
config.ActiveRobotCount,
|
||||
config.SeatCount,
|
||||
string(rawGifts),
|
||||
string(rawLuckyGifts),
|
||||
config.GiftRule.NormalGiftIntervalMS,
|
||||
@ -1344,6 +1487,11 @@ func (r *Repository) CreateRobotRoomConfig(ctx context.Context, input roomservic
|
||||
config.GiftRule.LuckyComboMax,
|
||||
config.GiftRule.LuckyPauseMinMS,
|
||||
config.GiftRule.LuckyPauseMaxMS,
|
||||
config.GiftRule.RobotStayMinMS,
|
||||
config.GiftRule.RobotStayMaxMS,
|
||||
config.GiftRule.RobotReplaceMinMS,
|
||||
config.GiftRule.RobotReplaceMaxMS,
|
||||
config.GiftRule.MaxGiftSenders,
|
||||
config.CreatedByAdminID,
|
||||
config.CreatedAtMS,
|
||||
config.UpdatedAtMS,
|
||||
@ -1392,8 +1540,9 @@ func (r *Repository) OccupiedRobotUserIDs(ctx context.Context, userIDs []int64)
|
||||
func (r *Repository) ListActiveRobotRooms(ctx context.Context) ([]roomservice.RobotRoomConfig, error) {
|
||||
rows, err := r.db.QueryContext(ctx,
|
||||
`SELECT app_code, room_id, room_short_id, title, cover_url, visible_region_id, status,
|
||||
owner_robot_user_id, robot_user_ids_json, gift_ids_json, lucky_gift_ids_json,
|
||||
owner_robot_user_id, robot_user_ids_json, active_robot_count, seat_count, gift_ids_json, lucky_gift_ids_json,
|
||||
normal_gift_interval_ms, lucky_combo_min, lucky_combo_max, lucky_pause_min_ms, lucky_pause_max_ms,
|
||||
robot_stay_min_ms, robot_stay_max_ms, robot_replace_min_ms, robot_replace_max_ms, max_gift_senders,
|
||||
created_by_admin_id, created_at_ms, updated_at_ms
|
||||
FROM room_robot_rooms
|
||||
WHERE status = 'active'
|
||||
@ -1406,6 +1555,251 @@ func (r *Repository) ListActiveRobotRooms(ctx context.Context) ([]roomservice.Ro
|
||||
return scanRobotRoomConfigs(rows)
|
||||
}
|
||||
|
||||
// GetHumanRoomRobotConfig 读取真人房间机器人行为配置;没有配置时由 service 层补默认值。
|
||||
func (r *Repository) GetHumanRoomRobotConfig(ctx context.Context) (roomservice.HumanRoomRobotConfig, bool, error) {
|
||||
row := r.db.QueryRowContext(ctx,
|
||||
`SELECT app_code, enabled, candidate_room_max_online, room_full_stop_online, room_target_min_online, room_target_max_online,
|
||||
robot_stay_min_ms, robot_stay_max_ms, robot_replace_min_ms, robot_replace_max_ms,
|
||||
normal_gift_interval_ms, normal_gift_interval_min_ms, normal_gift_interval_max_ms,
|
||||
gift_ids_json, lucky_gift_ids_json, super_lucky_gift_ids_json,
|
||||
lucky_combo_min, lucky_combo_max, lucky_pause_min_ms, lucky_pause_max_ms, max_gift_senders,
|
||||
country_pools_json, updated_by_admin_id, created_at_ms, updated_at_ms
|
||||
FROM room_human_robot_configs
|
||||
WHERE app_code = ?`,
|
||||
appcode.FromContext(ctx),
|
||||
)
|
||||
config, err := scanHumanRoomRobotConfig(row)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return roomservice.HumanRoomRobotConfig{}, false, nil
|
||||
}
|
||||
return config, err == nil, err
|
||||
}
|
||||
|
||||
// UpsertHumanRoomRobotConfig 保存真人房间机器人行为配置;运行时扫描每轮读取最新配置。
|
||||
func (r *Repository) UpsertHumanRoomRobotConfig(ctx context.Context, config roomservice.HumanRoomRobotConfig) (roomservice.HumanRoomRobotConfig, error) {
|
||||
appCode := normalizedRecordAppCode(ctx, config.AppCode)
|
||||
nowMS := config.UpdatedAtMS
|
||||
if nowMS <= 0 {
|
||||
nowMS = time.Now().UTC().UnixMilli()
|
||||
}
|
||||
config.AppCode = appCode
|
||||
config.CreatedAtMS = firstPositiveInt64(config.CreatedAtMS, nowMS)
|
||||
config.UpdatedAtMS = nowMS
|
||||
rawGifts, rawLucky, rawSuperLucky, rawPools, err := humanRoomRobotConfigJSON(config)
|
||||
if err != nil {
|
||||
return roomservice.HumanRoomRobotConfig{}, err
|
||||
}
|
||||
_, err = r.db.ExecContext(ctx,
|
||||
`INSERT INTO room_human_robot_configs (
|
||||
app_code, enabled, candidate_room_max_online, room_full_stop_online, room_target_min_online, room_target_max_online,
|
||||
robot_stay_min_ms, robot_stay_max_ms, robot_replace_min_ms, robot_replace_max_ms,
|
||||
normal_gift_interval_ms, normal_gift_interval_min_ms, normal_gift_interval_max_ms,
|
||||
gift_ids_json, lucky_gift_ids_json, super_lucky_gift_ids_json,
|
||||
lucky_combo_min, lucky_combo_max, lucky_pause_min_ms, lucky_pause_max_ms, max_gift_senders,
|
||||
country_pools_json, updated_by_admin_id, created_at_ms, updated_at_ms
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
enabled = VALUES(enabled),
|
||||
candidate_room_max_online = VALUES(candidate_room_max_online),
|
||||
room_full_stop_online = VALUES(room_full_stop_online),
|
||||
room_target_min_online = VALUES(room_target_min_online),
|
||||
room_target_max_online = VALUES(room_target_max_online),
|
||||
robot_stay_min_ms = VALUES(robot_stay_min_ms),
|
||||
robot_stay_max_ms = VALUES(robot_stay_max_ms),
|
||||
robot_replace_min_ms = VALUES(robot_replace_min_ms),
|
||||
robot_replace_max_ms = VALUES(robot_replace_max_ms),
|
||||
normal_gift_interval_ms = VALUES(normal_gift_interval_ms),
|
||||
normal_gift_interval_min_ms = VALUES(normal_gift_interval_min_ms),
|
||||
normal_gift_interval_max_ms = VALUES(normal_gift_interval_max_ms),
|
||||
gift_ids_json = VALUES(gift_ids_json),
|
||||
lucky_gift_ids_json = VALUES(lucky_gift_ids_json),
|
||||
super_lucky_gift_ids_json = VALUES(super_lucky_gift_ids_json),
|
||||
lucky_combo_min = VALUES(lucky_combo_min),
|
||||
lucky_combo_max = VALUES(lucky_combo_max),
|
||||
lucky_pause_min_ms = VALUES(lucky_pause_min_ms),
|
||||
lucky_pause_max_ms = VALUES(lucky_pause_max_ms),
|
||||
max_gift_senders = VALUES(max_gift_senders),
|
||||
country_pools_json = VALUES(country_pools_json),
|
||||
updated_by_admin_id = VALUES(updated_by_admin_id),
|
||||
updated_at_ms = VALUES(updated_at_ms)`,
|
||||
config.AppCode,
|
||||
boolToInt(config.Enabled),
|
||||
config.CandidateRoomMaxOnline,
|
||||
config.RoomFullStopOnline,
|
||||
config.RoomTargetMinOnline,
|
||||
config.RoomTargetMaxOnline,
|
||||
config.RobotStayMinMS,
|
||||
config.RobotStayMaxMS,
|
||||
config.RobotReplaceMinMS,
|
||||
config.RobotReplaceMaxMS,
|
||||
config.NormalGiftIntervalMS,
|
||||
config.NormalGiftIntervalMinMS,
|
||||
config.NormalGiftIntervalMaxMS,
|
||||
string(rawGifts),
|
||||
string(rawLucky),
|
||||
string(rawSuperLucky),
|
||||
config.LuckyComboMin,
|
||||
config.LuckyComboMax,
|
||||
config.LuckyPauseMinMS,
|
||||
config.LuckyPauseMaxMS,
|
||||
config.MaxGiftSenders,
|
||||
string(rawPools),
|
||||
config.UpdatedByAdminID,
|
||||
config.CreatedAtMS,
|
||||
config.UpdatedAtMS,
|
||||
)
|
||||
if err != nil {
|
||||
return roomservice.HumanRoomRobotConfig{}, err
|
||||
}
|
||||
saved, _, err := r.GetHumanRoomRobotConfig(ctx)
|
||||
return saved, err
|
||||
}
|
||||
|
||||
// ListHumanRobotCandidateRooms 找出同国家低人数真人房;room_id 使用 robot_ 前缀的内部机器人房不参与。
|
||||
func (r *Repository) ListHumanRobotCandidateRooms(ctx context.Context, appCode string, countryCode string, maxOnline int32, fullStopOnline int32, limit int) ([]roomservice.RoomListEntry, error) {
|
||||
appCode = normalizedRecordAppCode(ctx, appCode)
|
||||
countryCode = strings.ToUpper(strings.TrimSpace(countryCode))
|
||||
if maxOnline <= 0 {
|
||||
maxOnline = 5
|
||||
}
|
||||
if fullStopOnline <= 0 {
|
||||
fullStopOnline = 10
|
||||
}
|
||||
if maxOnline > fullStopOnline {
|
||||
maxOnline = fullStopOnline
|
||||
}
|
||||
if limit <= 0 || limit > 100 {
|
||||
limit = 50
|
||||
}
|
||||
rows, err := r.db.QueryContext(ctx,
|
||||
`SELECT app_code, room_id, room_short_id, visible_region_id, owner_country_code,
|
||||
owner_user_id, title, cover_url, mode, status, locked, heat,
|
||||
online_count, seat_count, occupied_seat_count, sort_score, created_at_ms, updated_at_ms
|
||||
FROM room_list_entries
|
||||
WHERE app_code = ?
|
||||
AND status = 'active'
|
||||
AND owner_country_code = ?
|
||||
AND online_count < ?
|
||||
AND online_count < ?
|
||||
AND room_id NOT LIKE 'robot\_%'
|
||||
ORDER BY online_count ASC, updated_at_ms DESC, room_id DESC
|
||||
LIMIT ?`,
|
||||
appCode,
|
||||
countryCode,
|
||||
maxOnline,
|
||||
fullStopOnline,
|
||||
limit,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := make([]roomservice.RoomListEntry, 0, limit)
|
||||
for rows.Next() {
|
||||
var entry roomservice.RoomListEntry
|
||||
if err := rows.Scan(
|
||||
&entry.AppCode,
|
||||
&entry.RoomID,
|
||||
&entry.RoomShortID,
|
||||
&entry.VisibleRegionID,
|
||||
&entry.OwnerCountryCode,
|
||||
&entry.OwnerUserID,
|
||||
&entry.Title,
|
||||
&entry.CoverURL,
|
||||
&entry.Mode,
|
||||
&entry.Status,
|
||||
&entry.Locked,
|
||||
&entry.Heat,
|
||||
&entry.OnlineCount,
|
||||
&entry.SeatCount,
|
||||
&entry.OccupiedSeatCount,
|
||||
&entry.SortScore,
|
||||
&entry.CreatedAtMS,
|
||||
&entry.UpdatedAtMS,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, entry)
|
||||
}
|
||||
return items, rows.Err()
|
||||
}
|
||||
|
||||
type humanRoomRobotConfigScanner interface {
|
||||
Scan(dest ...any) error
|
||||
}
|
||||
|
||||
func scanHumanRoomRobotConfig(row humanRoomRobotConfigScanner) (roomservice.HumanRoomRobotConfig, error) {
|
||||
var config roomservice.HumanRoomRobotConfig
|
||||
var enabled int
|
||||
var rawGifts string
|
||||
var rawLucky string
|
||||
var rawSuperLucky string
|
||||
var rawPools string
|
||||
if err := row.Scan(
|
||||
&config.AppCode,
|
||||
&enabled,
|
||||
&config.CandidateRoomMaxOnline,
|
||||
&config.RoomFullStopOnline,
|
||||
&config.RoomTargetMinOnline,
|
||||
&config.RoomTargetMaxOnline,
|
||||
&config.RobotStayMinMS,
|
||||
&config.RobotStayMaxMS,
|
||||
&config.RobotReplaceMinMS,
|
||||
&config.RobotReplaceMaxMS,
|
||||
&config.NormalGiftIntervalMS,
|
||||
&config.NormalGiftIntervalMinMS,
|
||||
&config.NormalGiftIntervalMaxMS,
|
||||
&rawGifts,
|
||||
&rawLucky,
|
||||
&rawSuperLucky,
|
||||
&config.LuckyComboMin,
|
||||
&config.LuckyComboMax,
|
||||
&config.LuckyPauseMinMS,
|
||||
&config.LuckyPauseMaxMS,
|
||||
&config.MaxGiftSenders,
|
||||
&rawPools,
|
||||
&config.UpdatedByAdminID,
|
||||
&config.CreatedAtMS,
|
||||
&config.UpdatedAtMS,
|
||||
); err != nil {
|
||||
return roomservice.HumanRoomRobotConfig{}, err
|
||||
}
|
||||
config.Enabled = enabled == 1
|
||||
if err := json.Unmarshal([]byte(rawGifts), &config.GiftIDs); err != nil {
|
||||
return roomservice.HumanRoomRobotConfig{}, err
|
||||
}
|
||||
if err := json.Unmarshal([]byte(rawLucky), &config.LuckyGiftIDs); err != nil {
|
||||
return roomservice.HumanRoomRobotConfig{}, err
|
||||
}
|
||||
if err := json.Unmarshal([]byte(rawSuperLucky), &config.SuperLuckyGiftIDs); err != nil {
|
||||
return roomservice.HumanRoomRobotConfig{}, err
|
||||
}
|
||||
if err := json.Unmarshal([]byte(rawPools), &config.CountryPools); err != nil {
|
||||
return roomservice.HumanRoomRobotConfig{}, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func humanRoomRobotConfigJSON(config roomservice.HumanRoomRobotConfig) ([]byte, []byte, []byte, []byte, error) {
|
||||
rawGifts, err := json.Marshal(config.GiftIDs)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
rawLucky, err := json.Marshal(config.LuckyGiftIDs)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
rawSuperLucky, err := json.Marshal(config.SuperLuckyGiftIDs)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
rawPools, err := json.Marshal(config.CountryPools)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
return rawGifts, rawLucky, rawSuperLucky, rawPools, nil
|
||||
}
|
||||
|
||||
type robotRoomScanner interface {
|
||||
Scan(dest ...any) error
|
||||
}
|
||||
@ -1437,6 +1831,8 @@ func scanRobotRoomConfig(row robotRoomScanner) (roomservice.RobotRoomConfig, err
|
||||
&item.Status,
|
||||
&item.OwnerRobotUserID,
|
||||
&rawRobots,
|
||||
&item.ActiveRobotCount,
|
||||
&item.SeatCount,
|
||||
&rawGifts,
|
||||
&rawLuckyGifts,
|
||||
&item.GiftRule.NormalGiftIntervalMS,
|
||||
@ -1444,6 +1840,11 @@ func scanRobotRoomConfig(row robotRoomScanner) (roomservice.RobotRoomConfig, err
|
||||
&item.GiftRule.LuckyComboMax,
|
||||
&item.GiftRule.LuckyPauseMinMS,
|
||||
&item.GiftRule.LuckyPauseMaxMS,
|
||||
&item.GiftRule.RobotStayMinMS,
|
||||
&item.GiftRule.RobotStayMaxMS,
|
||||
&item.GiftRule.RobotReplaceMinMS,
|
||||
&item.GiftRule.RobotReplaceMaxMS,
|
||||
&item.GiftRule.MaxGiftSenders,
|
||||
&item.CreatedByAdminID,
|
||||
&item.CreatedAtMS,
|
||||
&item.UpdatedAtMS,
|
||||
@ -1459,6 +1860,13 @@ func scanRobotRoomConfig(row robotRoomScanner) (roomservice.RobotRoomConfig, err
|
||||
if err := json.Unmarshal([]byte(rawLuckyGifts), &item.GiftRule.LuckyGiftIDs); err != nil {
|
||||
return roomservice.RobotRoomConfig{}, err
|
||||
}
|
||||
if item.ActiveRobotCount <= 0 {
|
||||
item.ActiveRobotCount = int32(len(item.RobotUserIDs))
|
||||
}
|
||||
if item.SeatCount <= 0 {
|
||||
item.SeatCount = 10
|
||||
}
|
||||
item.GiftRule = roomservice.WithRobotRoomGiftRuleStorageDefaults(item.GiftRule)
|
||||
return item, nil
|
||||
}
|
||||
|
||||
@ -1659,16 +2067,27 @@ func (r *Repository) SaveOutbox(ctx context.Context, records []outbox.Record) er
|
||||
|
||||
// ListPendingOutbox 返回待投递事件。
|
||||
func (r *Repository) ListPendingOutbox(ctx context.Context, limit int) ([]outbox.Record, error) {
|
||||
return r.listPendingOutboxFromTable(ctx, roomOutboxTable, limit)
|
||||
}
|
||||
|
||||
// ListPendingRobotOutbox 返回机器人房间待投递展示事件。
|
||||
func (r *Repository) ListPendingRobotOutbox(ctx context.Context, limit int) ([]outbox.Record, error) {
|
||||
return r.listPendingOutboxFromTable(ctx, roomRobotOutboxTable, limit)
|
||||
}
|
||||
|
||||
func (r *Repository) listPendingOutboxFromTable(ctx context.Context, table string, limit int) ([]outbox.Record, error) {
|
||||
if limit <= 0 {
|
||||
// 默认批量上限避免调用方传 0 导致全表扫描。
|
||||
limit = 100
|
||||
}
|
||||
table = roomOutboxTableName(table)
|
||||
pendingIndex, _ := roomOutboxIndexes(table)
|
||||
|
||||
// 按创建时间顺序扫描 pending,尽量保持事件投递顺序。
|
||||
nowMS := time.Now().UTC().UnixMilli()
|
||||
rows, err := r.db.QueryContext(ctx,
|
||||
`SELECT app_code, event_id, event_type, room_id, status, worker_id, lock_until_ms, envelope, created_at_ms, retry_count, next_retry_at_ms, COALESCE(last_error, '')
|
||||
FROM room_outbox FORCE INDEX (idx_room_outbox_pending)
|
||||
FROM `+table+` FORCE INDEX (`+pendingIndex+`)
|
||||
WHERE app_code = ? AND status IN (?, ?)
|
||||
AND next_retry_at_ms <= ?
|
||||
ORDER BY created_at_ms ASC
|
||||
@ -1717,12 +2136,23 @@ func (r *Repository) ListPendingOutbox(ctx context.Context, limit int) ([]outbox
|
||||
|
||||
// ClaimPendingOutbox 抢占一批待投递事件,避免多 worker 同时投递同一批。
|
||||
func (r *Repository) ClaimPendingOutbox(ctx context.Context, workerID string, limit int, lockUntilMS int64) ([]outbox.Record, error) {
|
||||
return r.claimPendingOutboxFromTable(ctx, roomOutboxTable, workerID, limit, lockUntilMS)
|
||||
}
|
||||
|
||||
// ClaimPendingRobotOutbox 抢占机器人房间展示事件,避免机器人流量占用主 room_outbox worker。
|
||||
func (r *Repository) ClaimPendingRobotOutbox(ctx context.Context, workerID string, limit int, lockUntilMS int64) ([]outbox.Record, error) {
|
||||
return r.claimPendingOutboxFromTable(ctx, roomRobotOutboxTable, workerID, limit, lockUntilMS)
|
||||
}
|
||||
|
||||
func (r *Repository) claimPendingOutboxFromTable(ctx context.Context, table string, workerID string, limit int, lockUntilMS int64) ([]outbox.Record, error) {
|
||||
if limit <= 0 {
|
||||
limit = 100
|
||||
}
|
||||
if strings.TrimSpace(workerID) == "" {
|
||||
workerID = "room-outbox-worker"
|
||||
}
|
||||
table = roomOutboxTableName(table)
|
||||
pendingIndex, claimIndex := roomOutboxIndexes(table)
|
||||
|
||||
tx, err := r.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
@ -1738,7 +2168,7 @@ func (r *Repository) ClaimPendingOutbox(ctx context.Context, workerID string, li
|
||||
}{
|
||||
{
|
||||
query: `SELECT app_code, event_id, event_type, room_id, status, worker_id, lock_until_ms, envelope, created_at_ms, retry_count, next_retry_at_ms, COALESCE(last_error, '')
|
||||
FROM room_outbox FORCE INDEX (idx_room_outbox_pending)
|
||||
FROM ` + table + ` FORCE INDEX (` + pendingIndex + `)
|
||||
WHERE app_code = ? AND status = ? AND next_retry_at_ms <= ? AND lock_until_ms IS NULL
|
||||
ORDER BY created_at_ms ASC, event_id ASC
|
||||
LIMIT ? FOR UPDATE SKIP LOCKED`,
|
||||
@ -1746,7 +2176,7 @@ func (r *Repository) ClaimPendingOutbox(ctx context.Context, workerID string, li
|
||||
},
|
||||
{
|
||||
query: `SELECT app_code, event_id, event_type, room_id, status, worker_id, lock_until_ms, envelope, created_at_ms, retry_count, next_retry_at_ms, COALESCE(last_error, '')
|
||||
FROM room_outbox FORCE INDEX (idx_room_outbox_pending)
|
||||
FROM ` + table + ` FORCE INDEX (` + pendingIndex + `)
|
||||
WHERE app_code = ? AND status = ? AND next_retry_at_ms <= ? AND lock_until_ms IS NULL
|
||||
ORDER BY created_at_ms ASC, event_id ASC
|
||||
LIMIT ? FOR UPDATE SKIP LOCKED`,
|
||||
@ -1754,7 +2184,7 @@ func (r *Repository) ClaimPendingOutbox(ctx context.Context, workerID string, li
|
||||
},
|
||||
{
|
||||
query: `SELECT app_code, event_id, event_type, room_id, status, worker_id, lock_until_ms, envelope, created_at_ms, retry_count, next_retry_at_ms, COALESCE(last_error, '')
|
||||
FROM room_outbox FORCE INDEX (idx_room_outbox_claim)
|
||||
FROM ` + table + ` FORCE INDEX (` + claimIndex + `)
|
||||
WHERE app_code = ? AND status = ? AND lock_until_ms <= ?
|
||||
ORDER BY created_at_ms ASC, event_id ASC
|
||||
LIMIT ? FOR UPDATE SKIP LOCKED`,
|
||||
@ -1777,7 +2207,7 @@ func (r *Repository) ClaimPendingOutbox(ctx context.Context, workerID string, li
|
||||
|
||||
for _, record := range records {
|
||||
if _, err := tx.ExecContext(ctx,
|
||||
`UPDATE room_outbox
|
||||
`UPDATE `+table+`
|
||||
SET status = ?, worker_id = ?, lock_until_ms = ?, updated_at_ms = ?
|
||||
WHERE app_code = ? AND event_id = ?`,
|
||||
outbox.StatusDelivering,
|
||||
@ -1841,9 +2271,19 @@ func (r *Repository) queryRoomOutboxRecords(ctx context.Context, tx *sql.Tx, que
|
||||
|
||||
// MarkOutboxDelivered 标记事件投递成功。
|
||||
func (r *Repository) MarkOutboxDelivered(ctx context.Context, eventID string) error {
|
||||
return r.markOutboxDeliveredInTable(ctx, roomOutboxTable, eventID)
|
||||
}
|
||||
|
||||
// MarkRobotOutboxDelivered 标记机器人展示事件已经投递成功。
|
||||
func (r *Repository) MarkRobotOutboxDelivered(ctx context.Context, eventID string) error {
|
||||
return r.markOutboxDeliveredInTable(ctx, roomRobotOutboxTable, eventID)
|
||||
}
|
||||
|
||||
func (r *Repository) markOutboxDeliveredInTable(ctx context.Context, table string, eventID string) error {
|
||||
table = roomOutboxTableName(table)
|
||||
// 成功后清空 last_error,后续扫描不再返回该事件。
|
||||
_, err := r.db.ExecContext(ctx,
|
||||
`UPDATE room_outbox
|
||||
`UPDATE `+table+`
|
||||
SET status = ?, worker_id = '', lock_until_ms = NULL, last_error = NULL, updated_at_ms = ?
|
||||
WHERE app_code = ? AND event_id = ?`,
|
||||
outbox.StatusDelivered,
|
||||
@ -1857,9 +2297,19 @@ func (r *Repository) MarkOutboxDelivered(ctx context.Context, eventID string) er
|
||||
|
||||
// MarkOutboxRetryable 标记事件投递失败并写入下一次重试时间。
|
||||
func (r *Repository) MarkOutboxRetryable(ctx context.Context, eventID string, lastErr string, nextRetryAtMS int64) error {
|
||||
return r.markOutboxRetryableInTable(ctx, roomOutboxTable, eventID, lastErr, nextRetryAtMS)
|
||||
}
|
||||
|
||||
// MarkRobotOutboxRetryable 记录机器人展示事件投递失败,并写入独立重试退避。
|
||||
func (r *Repository) MarkRobotOutboxRetryable(ctx context.Context, eventID string, lastErr string, nextRetryAtMS int64) error {
|
||||
return r.markOutboxRetryableInTable(ctx, roomRobotOutboxTable, eventID, lastErr, nextRetryAtMS)
|
||||
}
|
||||
|
||||
func (r *Repository) markOutboxRetryableInTable(ctx context.Context, table string, eventID string, lastErr string, nextRetryAtMS int64) error {
|
||||
table = roomOutboxTableName(table)
|
||||
// 失败转入 retryable,worker 只有到 next_retry_at_ms 后才会重新抢占。
|
||||
_, err := r.db.ExecContext(ctx,
|
||||
`UPDATE room_outbox
|
||||
`UPDATE `+table+`
|
||||
SET status = ?, worker_id = '', lock_until_ms = NULL, retry_count = retry_count + 1, next_retry_at_ms = ?, last_error = ?, updated_at_ms = ?
|
||||
WHERE app_code = ? AND event_id = ?`,
|
||||
outbox.StatusRetryable,
|
||||
@ -1875,8 +2325,18 @@ func (r *Repository) MarkOutboxRetryable(ctx context.Context, eventID string, la
|
||||
|
||||
// MarkOutboxDead 把超过最大重试次数的事件转入 failed。
|
||||
func (r *Repository) MarkOutboxDead(ctx context.Context, eventID string, lastErr string) error {
|
||||
return r.markOutboxDeadInTable(ctx, roomOutboxTable, eventID, lastErr)
|
||||
}
|
||||
|
||||
// MarkRobotOutboxDead 把超过最大重试次数的机器人展示事件转入 failed。
|
||||
func (r *Repository) MarkRobotOutboxDead(ctx context.Context, eventID string, lastErr string) error {
|
||||
return r.markOutboxDeadInTable(ctx, roomRobotOutboxTable, eventID, lastErr)
|
||||
}
|
||||
|
||||
func (r *Repository) markOutboxDeadInTable(ctx context.Context, table string, eventID string, lastErr string) error {
|
||||
table = roomOutboxTableName(table)
|
||||
_, err := r.db.ExecContext(ctx,
|
||||
`UPDATE room_outbox
|
||||
`UPDATE `+table+`
|
||||
SET status = ?, worker_id = '', lock_until_ms = NULL, last_error = ?, updated_at_ms = ?
|
||||
WHERE app_code = ? AND event_id = ?`,
|
||||
outbox.StatusFailed,
|
||||
@ -1889,6 +2349,22 @@ func (r *Repository) MarkOutboxDead(ctx context.Context, eventID string, lastErr
|
||||
return err
|
||||
}
|
||||
|
||||
func roomOutboxTableName(table string) string {
|
||||
switch table {
|
||||
case roomRobotOutboxTable:
|
||||
return roomRobotOutboxTable
|
||||
default:
|
||||
return roomOutboxTable
|
||||
}
|
||||
}
|
||||
|
||||
func roomOutboxIndexes(table string) (pending string, claim string) {
|
||||
if roomOutboxTableName(table) == roomRobotOutboxTable {
|
||||
return "idx_room_robot_outbox_pending", "idx_room_robot_outbox_claim"
|
||||
}
|
||||
return "idx_room_outbox_pending", "idx_room_outbox_claim"
|
||||
}
|
||||
|
||||
// UpsertRoomListEntry 写入房间列表读模型。
|
||||
func (r *Repository) UpsertRoomListEntry(ctx context.Context, entry roomservice.RoomListEntry) error {
|
||||
// created_at_ms 首次插入后保持不变,避免 Join/Leave/SendGift 等更新把 new tab 顺序洗掉。
|
||||
@ -2366,6 +2842,13 @@ func buildRoomListQuerySQL(query roomservice.RoomListQuery) (string, []any) {
|
||||
countryLiteral := roomListSQLStringLiteral(sortCountryCode)
|
||||
normalRankExpr = "CASE WHEN r.owner_country_code = " + countryLiteral + " AND r.online_count > 0 THEN 2 WHEN r.owner_country_code <> " + countryLiteral + " AND r.online_count > 0 THEN 3 WHEN r.owner_country_code = " + countryLiteral + " THEN 4 ELSE 5 END"
|
||||
}
|
||||
regionPinScopeSQL := "AND rp.visible_region_id = ?"
|
||||
countryPinScopeSQL := "AND cp.visible_region_id = ?"
|
||||
if query.AllVisibleRegions {
|
||||
// 白名单用户查看全区列表时,区域/国家置顶按房间自身区域命中,不能再固定到 viewer 区域。
|
||||
regionPinScopeSQL = "AND rp.visible_region_id = r.visible_region_id"
|
||||
countryPinScopeSQL = "AND cp.visible_region_id = r.visible_region_id"
|
||||
}
|
||||
pinnedExpr := "CASE WHEN gp.room_id IS NULL AND rp.room_id IS NULL AND cp.room_id IS NULL THEN 0 ELSE 1 END"
|
||||
pinRankExpr := "CASE WHEN gp.room_id IS NOT NULL THEN 0 WHEN rp.room_id IS NOT NULL THEN 0 WHEN cp.room_id IS NOT NULL THEN 1 ELSE " + normalRankExpr + " END"
|
||||
pinWeightExpr := "CASE WHEN gp.room_id IS NOT NULL THEN gp.weight WHEN rp.room_id IS NOT NULL THEN rp.weight WHEN cp.room_id IS NOT NULL THEN cp.weight ELSE 0 END"
|
||||
@ -2386,7 +2869,7 @@ func buildRoomListQuerySQL(query roomservice.RoomListQuery) (string, []any) {
|
||||
LEFT JOIN room_region_pins rp
|
||||
ON rp.app_code = r.app_code
|
||||
AND rp.pin_type = 'region'
|
||||
AND rp.visible_region_id = ?
|
||||
` + regionPinScopeSQL + `
|
||||
AND rp.room_id = r.room_id
|
||||
AND rp.status = ?
|
||||
AND rp.pinned_at_ms <= ?
|
||||
@ -2394,14 +2877,27 @@ func buildRoomListQuerySQL(query roomservice.RoomListQuery) (string, []any) {
|
||||
LEFT JOIN room_region_pins cp
|
||||
ON cp.app_code = r.app_code
|
||||
AND cp.pin_type = 'country'
|
||||
AND cp.visible_region_id = ?
|
||||
` + countryPinScopeSQL + `
|
||||
AND cp.room_id = r.room_id
|
||||
AND r.owner_country_code = ?
|
||||
AND cp.status = ?
|
||||
AND cp.pinned_at_ms <= ?
|
||||
AND cp.expires_at_ms > ?`
|
||||
where := []string{"r.app_code = ?", "r.status = ?", "r.visible_region_id = ?"}
|
||||
args := []any{"active", query.NowMS, query.NowMS, regionID, "active", query.NowMS, query.NowMS, regionID, sortCountryCode, "active", query.NowMS, query.NowMS, appcode.Normalize(query.AppCode), "active", regionID}
|
||||
where := []string{"r.app_code = ?", "r.status = ?"}
|
||||
args := []any{"active", query.NowMS, query.NowMS}
|
||||
if !query.AllVisibleRegions {
|
||||
args = append(args, regionID)
|
||||
}
|
||||
args = append(args, "active", query.NowMS, query.NowMS)
|
||||
if !query.AllVisibleRegions {
|
||||
args = append(args, regionID)
|
||||
}
|
||||
args = append(args, sortCountryCode, "active", query.NowMS, query.NowMS, appcode.Normalize(query.AppCode), "active")
|
||||
if !query.AllVisibleRegions {
|
||||
// 普通发现页必须利用区域索引隔离结果;白名单模式只保留 app/status/可选国家/关键词条件。
|
||||
where = append(where, "r.visible_region_id = ?")
|
||||
args = append(args, regionID)
|
||||
}
|
||||
if query.OwnerUserID > 0 {
|
||||
where = append(where, "r.owner_user_id = ?")
|
||||
args = append(args, query.OwnerUserID)
|
||||
|
||||
@ -177,6 +177,11 @@ func (s *Server) AdminUpdateRoomSeatConfig(ctx context.Context, req *roomv1.Admi
|
||||
return mapServiceResult(s.svc.AdminUpdateRoomSeatConfig(ctx, req))
|
||||
}
|
||||
|
||||
func (s *Server) AdminUpdateHumanRoomRobotConfig(ctx context.Context, req *roomv1.AdminUpdateHumanRoomRobotConfigRequest) (*roomv1.AdminUpdateHumanRoomRobotConfigResponse, error) {
|
||||
ctx = contextWithMetaApp(ctx, req.GetMeta())
|
||||
return mapServiceResult(s.svc.AdminUpdateHumanRoomRobotConfig(ctx, req))
|
||||
}
|
||||
|
||||
func (s *Server) AdminCreateRoomPin(ctx context.Context, req *roomv1.AdminCreateRoomPinRequest) (*roomv1.AdminCreateRoomPinResponse, error) {
|
||||
ctx = contextWithMetaApp(ctx, req.GetMeta())
|
||||
return mapServiceResult(s.svc.AdminCreateRoomPin(ctx, req))
|
||||
@ -448,6 +453,11 @@ func (s *Server) AdminGetRoomSeatConfig(ctx context.Context, req *roomv1.AdminGe
|
||||
return mapServiceResult(s.svc.AdminGetRoomSeatConfig(ctx, req))
|
||||
}
|
||||
|
||||
func (s *Server) AdminGetHumanRoomRobotConfig(ctx context.Context, req *roomv1.AdminGetHumanRoomRobotConfigRequest) (*roomv1.AdminGetHumanRoomRobotConfigResponse, error) {
|
||||
ctx = contextWithMetaApp(ctx, req.GetMeta())
|
||||
return mapServiceResult(s.svc.AdminGetHumanRoomRobotConfig(ctx, req))
|
||||
}
|
||||
|
||||
func (s *Server) AdminListRoomPins(ctx context.Context, req *roomv1.AdminListRoomPinsRequest) (*roomv1.AdminListRoomPinsResponse, error) {
|
||||
ctx = contextWithMetaApp(ctx, req.GetMeta())
|
||||
return mapServiceResult(s.svc.AdminListRoomPins(ctx, req))
|
||||
|
||||
@ -106,6 +106,21 @@ CREATE TABLE IF NOT EXISTS stat_lucky_gift_pool_day_country (
|
||||
KEY idx_stat_lucky_pool_region (app_code, stat_day, region_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物奖池国家日统计聚合表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS stat_real_room_robot_gift_day_rooms (
|
||||
app_code VARCHAR(32) NOT NULL COMMENT '应用编码',
|
||||
stat_day DATE NOT NULL COMMENT 'UTC 统计日',
|
||||
country_id BIGINT NOT NULL DEFAULT 0 COMMENT '国家维度 ID,0 表示未知或全局',
|
||||
region_id BIGINT NOT NULL DEFAULT 0 COMMENT '区域维度 ID,0 表示未知或全局',
|
||||
room_id VARCHAR(96) NOT NULL COMMENT '真人房间 ID',
|
||||
normal_gift_coin BIGINT NOT NULL DEFAULT 0 COMMENT '机器人在真人房送出的普通礼物金币价值',
|
||||
lucky_gift_coin BIGINT NOT NULL DEFAULT 0 COMMENT '机器人在真人房送出的幸运礼物金币价值',
|
||||
super_lucky_gift_coin BIGINT NOT NULL DEFAULT 0 COMMENT '机器人在真人房送出的超级幸运礼物金币价值',
|
||||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||||
PRIMARY KEY (app_code, stat_day, country_id, region_id, room_id),
|
||||
KEY idx_stat_real_room_robot_gift_region (app_code, stat_day, region_id),
|
||||
KEY idx_stat_real_room_robot_gift_country (app_code, stat_day, country_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='真人房机器人礼物房间日统计表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS stat_game_day_country (
|
||||
app_code VARCHAR(32) NOT NULL,
|
||||
stat_day DATE NOT NULL,
|
||||
|
||||
@ -371,18 +371,21 @@ func roomGiftEvent(body []byte) (mysqlstorage.RoomGiftEvent, bool, error) {
|
||||
if err := proto.Unmarshal(envelope.GetBody(), &gift); err != nil {
|
||||
return mysqlstorage.RoomGiftEvent{}, false, err
|
||||
}
|
||||
if gift.GetIsRobotGift() {
|
||||
if gift.GetIsRobotGift() && !gift.GetRealRoomRobotGift() {
|
||||
return mysqlstorage.RoomGiftEvent{}, false, nil
|
||||
}
|
||||
return mysqlstorage.RoomGiftEvent{
|
||||
AppCode: envelope.GetAppCode(),
|
||||
EventID: envelope.GetEventId(),
|
||||
RoomID: envelope.GetRoomId(),
|
||||
SenderUserID: gift.GetSenderUserId(),
|
||||
CountryID: gift.GetCountryId(),
|
||||
VisibleRegionID: firstNonZeroInt64(gift.GetRegionId(), gift.GetVisibleRegionId()),
|
||||
GiftValue: gift.GetGiftValue(),
|
||||
CoinSpent: roomGiftCoinSpent(&gift),
|
||||
PoolID: gift.GetPoolId(),
|
||||
GiftTypeCode: gift.GetGiftTypeCode(),
|
||||
RealRoomRobot: gift.GetRealRoomRobotGift(),
|
||||
OccurredAtMS: envelope.GetOccurredAtMs(),
|
||||
}, true, nil
|
||||
}
|
||||
|
||||
@ -131,6 +131,28 @@ func TestLocalStatisticsDataScreenFlow(t *testing.T) {
|
||||
if err := repo.ConsumeRoomGift(ctx, gift); err != nil {
|
||||
t.Fatalf("consume room gift failed: %v", err)
|
||||
}
|
||||
robotGiftBody := roomGiftMessage(t, appCode, "room_gift_robot_1", "room_robot_real", occurredAt, &roomeventsv1.RoomGiftSent{
|
||||
SenderUserId: 88001,
|
||||
TargetUserId: 88002,
|
||||
GiftId: "robot-super",
|
||||
GiftCount: 1,
|
||||
GiftValue: 700,
|
||||
CoinSpent: 900,
|
||||
VisibleRegionId: regionID,
|
||||
CommandId: "gift_command_robot_1",
|
||||
PoolId: "human_robot_super_lucky_display",
|
||||
GiftTypeCode: "super_lucky",
|
||||
IsRobotGift: true,
|
||||
RealRoomRobotGift: true,
|
||||
SyntheticLuckyGift: true,
|
||||
})
|
||||
robotGift, ok, err := roomGiftEvent(robotGiftBody)
|
||||
if err != nil || !ok {
|
||||
t.Fatalf("decode real room robot gift failed: ok=%v err=%v", ok, err)
|
||||
}
|
||||
if err := repo.ConsumeRoomGift(ctx, robotGift); err != nil {
|
||||
t.Fatalf("consume real room robot gift failed: %v", err)
|
||||
}
|
||||
|
||||
luckyReward := walletMessage(t, walletmq.WalletOutboxMessage{
|
||||
AppCode: appCode,
|
||||
@ -190,6 +212,9 @@ func TestLocalStatisticsDataScreenFlow(t *testing.T) {
|
||||
if overview.LuckyGiftTurnover != 1_250 || overview.LuckyGiftPayout != 300 || overview.LuckyGiftProfit != 950 || overview.LuckyGiftPayers != 1 {
|
||||
t.Fatalf("lucky gift metrics mismatch: %+v", overview)
|
||||
}
|
||||
if overview.RealRoomRobotSuperGiftCoin != 900 || overview.RealRoomRobotTotalGiftCoin != 900 || overview.RealRoomRobotGiftRoomCount != 1 || overview.RealRoomRobotAvgRoomGiftCoin != 900 {
|
||||
t.Fatalf("real room robot gift metrics mismatch: %+v", overview)
|
||||
}
|
||||
if len(overview.LuckyGiftPools) != 1 {
|
||||
t.Fatalf("lucky gift pool breakdown missing: %+v", overview.LuckyGiftPools)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user