yumi-golang/internal/router/game_provider_routes.go
2026-04-28 18:05:13 +08:00

319 lines
10 KiB
Go

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
}