378 lines
12 KiB
Go
378 lines
12 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, visibility *gameprovider.VisibilityPolicy) {
|
|
if registry == nil {
|
|
return
|
|
}
|
|
|
|
appGroup := engine.Group("/app/game")
|
|
appGroup.Use(authMiddleware(javaClient))
|
|
appGroup.GET("/room/shortcut", func(c *gin.Context) {
|
|
user, visible, ok := gameListAccess(c, visibility)
|
|
if !ok {
|
|
return
|
|
}
|
|
if !visible {
|
|
writeOK(c, []publicRoomGameItem{})
|
|
return
|
|
}
|
|
resp, err := registry.ListShortcutGames(c.Request.Context(), user, c.Query("roomId"))
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return
|
|
}
|
|
writeOK(c, publicRoomGameItems(resp))
|
|
})
|
|
appGroup.GET("/room/list", func(c *gin.Context) {
|
|
user, visible, ok := gameListAccess(c, visibility)
|
|
if !ok {
|
|
return
|
|
}
|
|
if !visible {
|
|
writeOK(c, publicRoomGameListResponse(&gameprovider.RoomGameListResponse{Items: []gameprovider.RoomGameListItem{}}))
|
|
return
|
|
}
|
|
resp, err := registry.ListRoomGames(c.Request.Context(), user, 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) {
|
|
_, visible, ok := gameListAccess(c, visibility)
|
|
if !ok {
|
|
return
|
|
}
|
|
if !visible {
|
|
writeOK(c, gameprovider.ProviderListResponse{Items: []gameprovider.ProviderSummary{}})
|
|
return
|
|
}
|
|
writeOK(c, registry.List())
|
|
})
|
|
providerGroup.GET("/:provider/room/shortcut", func(c *gin.Context) {
|
|
user, visible, ok := gameListAccess(c, visibility)
|
|
if !ok {
|
|
return
|
|
}
|
|
if !visible {
|
|
writeOK(c, gin.H{"items": []publicRoomGameItem{}})
|
|
return
|
|
}
|
|
provider, ok := resolveGameProvider(c, registry)
|
|
if !ok {
|
|
return
|
|
}
|
|
resp, err := provider.ListShortcutGames(c.Request.Context(), user, 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) {
|
|
user, visible, ok := gameListAccess(c, visibility)
|
|
if !ok {
|
|
return
|
|
}
|
|
if !visible {
|
|
writeOK(c, publicRoomGameListResponse(&gameprovider.RoomGameListResponse{Items: []gameprovider.RoomGameListItem{}}))
|
|
return
|
|
}
|
|
provider, ok := resolveGameProvider(c, registry)
|
|
if !ok {
|
|
return
|
|
}
|
|
resp, err := provider.ListRoomGames(c.Request.Context(), user, 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 gameListAccess(c *gin.Context, visibility *gameprovider.VisibilityPolicy) (common.AuthUser, bool, bool) {
|
|
user := mustAuthUser(c)
|
|
if gameprovider.IsEmptyGameListUser(user.UserID) {
|
|
return user, false, true
|
|
}
|
|
if visibility == nil {
|
|
return user, true, true
|
|
}
|
|
// 游戏列表只在列表入口做展示门禁,结果里的区域继续向下传给 provider SQL 做 regions 过滤。
|
|
result, err := visibility.Evaluate(c.Request.Context(), user, resolveClientIP(c))
|
|
if err != nil {
|
|
writeError(c, err)
|
|
return user, false, false
|
|
}
|
|
user.RegionID = result.RegionID
|
|
user.RegionCode = result.RegionCode
|
|
return user, result.Allow, true
|
|
}
|
|
|
|
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
|
|
}
|