package router import ( "net/http" "strings" "chatapp3-golang/internal/common" "chatapp3-golang/internal/service/gameprovider" "github.com/gin-gonic/gin" ) // registerGameProviderRoutes 注册统一游戏厂商 app 路由。 func registerGameProviderRoutes(engine *gin.Engine, javaClient authGateway, registry *gameprovider.Registry) { if registry == nil { return } appGroup := engine.Group("/app/game") appGroup.Use(authMiddleware(javaClient)) appGroup.GET("/room/shortcut", func(c *gin.Context) { resp, err := registry.ListShortcutGames(c.Request.Context(), mustAuthUser(c), c.Query("roomId")) if err != nil { writeError(c, err) return } writeOK(c, publicRoomGameItems(resp)) }) appGroup.GET("/room/list", func(c *gin.Context) { resp, err := registry.ListRoomGames(c.Request.Context(), mustAuthUser(c), c.Query("roomId"), c.Query("category")) if err != nil { writeError(c, err) return } writeOK(c, publicRoomGameListResponse(resp)) }) appGroup.GET("/state", func(c *gin.Context) { resp, err := registry.GetRoomState(c.Request.Context(), mustAuthUser(c), c.Query("roomId")) if err != nil { writeError(c, err) return } writeOK(c, publicRoomState(resp)) }) appGroup.POST("/launch", func(c *gin.Context) { var req gameprovider.LaunchRequest if err := c.ShouldBindJSON(&req); err != nil { writeError(c, common.NewAppError(http.StatusBadRequest, "bad_request", err.Error())) return } resp, err := registry.LaunchGame(c.Request.Context(), mustAuthUser(c), req, resolveClientIP(c)) if err != nil { writeError(c, err) return } writeOK(c, publicLaunch(resp)) }) appGroup.POST("/close", func(c *gin.Context) { var req gameprovider.CloseRequest if err := c.ShouldBindJSON(&req); err != nil { writeError(c, common.NewAppError(http.StatusBadRequest, "bad_request", err.Error())) return } resp, err := registry.CloseGame(c.Request.Context(), mustAuthUser(c), req) if err != nil { writeError(c, err) return } writeOK(c, publicRoomState(resp)) }) providerGroup := engine.Group("/app/game/providers") providerGroup.Use(authMiddleware(javaClient)) providerGroup.GET("", func(c *gin.Context) { writeOK(c, registry.List()) }) providerGroup.GET("/:provider/room/shortcut", func(c *gin.Context) { provider, ok := resolveGameProvider(c, registry) if !ok { return } resp, err := provider.ListShortcutGames(c.Request.Context(), mustAuthUser(c), c.Query("roomId")) if err != nil { writeError(c, err) return } writeOK(c, gin.H{"items": publicRoomGameItems(resp)}) }) providerGroup.GET("/:provider/room/list", func(c *gin.Context) { provider, ok := resolveGameProvider(c, registry) if !ok { return } resp, err := provider.ListRoomGames(c.Request.Context(), mustAuthUser(c), c.Query("roomId"), c.Query("category")) if err != nil { writeError(c, err) return } writeOK(c, publicRoomGameListResponse(resp)) }) providerGroup.GET("/:provider/state", func(c *gin.Context) { provider, ok := resolveGameProvider(c, registry) if !ok { return } resp, err := provider.GetRoomState(c.Request.Context(), mustAuthUser(c), c.Query("roomId")) if err != nil { writeError(c, err) return } writeOK(c, publicRoomState(resp)) }) providerGroup.POST("/:provider/launch", func(c *gin.Context) { provider, ok := resolveGameProvider(c, registry) if !ok { return } var req gameprovider.LaunchRequest if err := c.ShouldBindJSON(&req); err != nil { writeError(c, common.NewAppError(http.StatusBadRequest, "bad_request", err.Error())) return } resp, err := provider.LaunchGame(c.Request.Context(), mustAuthUser(c), req, resolveClientIP(c)) if err != nil { writeError(c, err) return } writeOK(c, publicLaunch(resp)) }) providerGroup.POST("/:provider/close", func(c *gin.Context) { provider, ok := resolveGameProvider(c, registry) if !ok { return } var req gameprovider.CloseRequest if err := c.ShouldBindJSON(&req); err != nil { writeError(c, common.NewAppError(http.StatusBadRequest, "bad_request", err.Error())) return } resp, err := provider.CloseGame(c.Request.Context(), mustAuthUser(c), req) if err != nil { writeError(c, err) return } writeOK(c, publicRoomState(resp)) }) } func resolveGameProvider(c *gin.Context, registry *gameprovider.Registry) (gameprovider.Provider, bool) { provider, err := registry.Resolve(c.Param("provider")) if err != nil { writeError(c, err) return nil, false } return provider, true } type publicRoomGameItem struct { ID int64 `json:"id"` GameID string `json:"gameId"` GameType string `json:"gameType,omitempty"` Provider string `json:"provider,omitempty"` VendorType string `json:"vendorType,omitempty"` ProviderGameID string `json:"providerGameId,omitempty"` VendorGameID string `json:"vendorGameId,omitempty"` Name string `json:"name"` Cover string `json:"cover"` Category string `json:"category,omitempty"` Sort int64 `json:"sort,omitempty"` LaunchMode string `json:"launchMode,omitempty"` FullScreen bool `json:"fullScreen"` GameMode int `json:"gameMode,omitempty"` SafeHeight int `json:"safeHeight,omitempty"` Orientation int `json:"orientation,omitempty"` PackageVersion string `json:"packageVersion,omitempty"` Status string `json:"status,omitempty"` LaunchParams map[string]any `json:"launchParams,omitempty"` } type publicRoomGameList struct { Items []publicRoomGameItem `json:"items"` } type publicRoomStateResponse struct { RoomID string `json:"roomId"` State string `json:"state"` Provider string `json:"provider,omitempty"` VendorType string `json:"vendorType,omitempty"` GameSessionID string `json:"gameSessionId,omitempty"` CurrentGameID string `json:"currentGameId,omitempty"` CurrentProviderGameID string `json:"currentProviderGameId,omitempty"` CurrentVendorGameID string `json:"currentVendorGameId,omitempty"` CurrentGameName string `json:"currentGameName,omitempty"` CurrentGameCover string `json:"currentGameCover,omitempty"` HostUserID int64 `json:"hostUserId,omitempty"` } type publicLaunchResponse struct { ID int64 `json:"id,omitempty"` GameSessionID string `json:"gameSessionId"` Provider string `json:"provider,omitempty"` VendorType string `json:"vendorType,omitempty"` GameID string `json:"gameId"` ProviderGameID string `json:"providerGameId,omitempty"` VendorGameID string `json:"vendorGameId,omitempty"` Entry gameprovider.LaunchEntry `json:"entry"` LaunchConfig any `json:"launchConfig,omitempty"` BridgeConfig any `json:"bridgeConfig,omitempty"` RoomState publicRoomStateResponse `json:"roomState"` } func publicRoomGameItems(items []gameprovider.RoomGameListItem) []publicRoomGameItem { if len(items) == 0 { return []publicRoomGameItem{} } result := make([]publicRoomGameItem, 0, len(items)) for _, item := range items { provider := appCompatProviderName(item.Provider) gameType := appCompatProviderName(item.GameType) result = append(result, publicRoomGameItem{ ID: item.ID, GameID: item.GameID, GameType: gameType, Provider: provider, VendorType: provider, ProviderGameID: item.ProviderGameID, VendorGameID: item.ProviderGameID, Name: item.Name, Cover: item.Cover, Category: item.Category, Sort: item.Sort, LaunchMode: item.LaunchMode, FullScreen: item.FullScreen, GameMode: item.GameMode, SafeHeight: item.SafeHeight, Orientation: item.Orientation, PackageVersion: item.PackageVersion, Status: item.Status, LaunchParams: publicLaunchParams(item.LaunchParams), }) } return result } func publicLaunchParams(params map[string]any) map[string]any { if len(params) == 0 { return nil } result := make(map[string]any, len(params)) for key, value := range params { if strings.EqualFold(strings.TrimSpace(key), "gameType") { if text, ok := value.(string); ok { result[key] = appCompatProviderName(text) continue } } result[key] = value } return result } func publicRoomGameListResponse(resp *gameprovider.RoomGameListResponse) *publicRoomGameList { if resp == nil { return &publicRoomGameList{Items: []publicRoomGameItem{}} } return &publicRoomGameList{ Items: publicRoomGameItems(resp.Items), } } func publicRoomState(resp *gameprovider.RoomStateResponse) *publicRoomStateResponse { if resp == nil { return nil } return &publicRoomStateResponse{ RoomID: resp.RoomID, State: resp.State, Provider: appCompatProviderName(resp.Provider), VendorType: appCompatProviderName(resp.Provider), GameSessionID: resp.GameSessionID, CurrentGameID: resp.CurrentGameID, CurrentProviderGameID: resp.CurrentProviderGameID, CurrentVendorGameID: resp.CurrentProviderGameID, CurrentGameName: resp.CurrentGameName, CurrentGameCover: resp.CurrentGameCover, HostUserID: resp.HostUserID, } } func publicLaunch(resp *gameprovider.LaunchResponse) *publicLaunchResponse { if resp == nil { return nil } roomState := publicRoomState(&resp.RoomState) if roomState == nil { roomState = &publicRoomStateResponse{} } return &publicLaunchResponse{ ID: resp.ID, GameSessionID: resp.GameSessionID, Provider: appCompatProviderName(resp.Provider), VendorType: appCompatProviderName(resp.Provider), GameID: resp.GameID, ProviderGameID: resp.ProviderGameID, VendorGameID: resp.ProviderGameID, Entry: resp.Entry, LaunchConfig: resp.LaunchConfig, BridgeConfig: resp.LaunchConfig, RoomState: *roomState, } } func appCompatProviderName(provider string) string { if strings.EqualFold(strings.TrimSpace(provider), "LINGXIAN") { return "LEADER" } return provider }