You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
5.2 KiB
Go
205 lines
5.2 KiB
Go
package controller
|
|
|
|
import (
|
|
"errors"
|
|
socketio "github.com/googollee/go-socket.io"
|
|
"github.com/hyperzlib/isekai-remote-playback/context"
|
|
"github.com/hyperzlib/isekai-remote-playback/events"
|
|
"github.com/hyperzlib/isekai-remote-playback/store"
|
|
"github.com/hyperzlib/isekai-remote-playback/utils"
|
|
"log"
|
|
)
|
|
|
|
type ServerSocketContext struct {
|
|
IsAuth bool
|
|
}
|
|
|
|
type ServerSocketController struct {
|
|
SocketController
|
|
appsConfig utils.ApplicationsConfig
|
|
}
|
|
|
|
func NewServerSocketController(basePath string, ctx *context.ServerContext) (*ServerSocketController, error) {
|
|
appConfig, err := utils.GetApplicationsConfig()
|
|
if err != nil {
|
|
panic("Cannot load applications config: " + err.Error())
|
|
}
|
|
|
|
instance := &ServerSocketController{
|
|
SocketController: SocketController{
|
|
basePath: basePath,
|
|
sockets: ctx.Sockets,
|
|
events: ctx.EventSource,
|
|
context: ctx,
|
|
storeModel: store.NewStoreModel(),
|
|
},
|
|
appsConfig: appConfig,
|
|
}
|
|
|
|
err = instance.Initialize()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return instance, nil
|
|
}
|
|
|
|
func (c *ServerSocketController) Initialize() error {
|
|
server := c.sockets
|
|
|
|
server.OnConnect(c.basePath, func(s socketio.Conn) error {
|
|
s.SetContext(&ServerSocketContext{})
|
|
|
|
log.Println("Server connected: " + s.RemoteAddr().String())
|
|
|
|
/*time.AfterFunc(5*time.Second, func() { // 关闭5秒内为登录成功的链接
|
|
ctx := GetContext[ServerSocketContext](s)
|
|
if !ctx.IsAuth {
|
|
log.Println("Server auth timeout: " + s.RemoteAddr().String())
|
|
s.Emit("error", "ERR::AUTH_TIMEOUT")
|
|
time.AfterFunc(1000, func() {
|
|
s.Close()
|
|
})
|
|
}
|
|
})*/
|
|
return nil
|
|
})
|
|
|
|
server.OnEvent(c.basePath, "auth:login", c.AppLogin)
|
|
|
|
server.OnEvent(c.basePath, "user:update", c.UpdateUser)
|
|
|
|
server.OnEvent(c.basePath, "user:player:bind", c.UserBindPlayer)
|
|
|
|
server.OnError(c.basePath, func(s socketio.Conn, e error) {
|
|
log.Println("Socket error:", e)
|
|
})
|
|
|
|
c.events.AddListener("bindUser", c.OnBindUser)
|
|
|
|
return nil
|
|
}
|
|
|
|
// CheckAuth 检测登录
|
|
func (c *ServerSocketController) CheckAuth(s socketio.Conn) bool {
|
|
ctx := GetContext[ServerSocketContext](s)
|
|
if !ctx.IsAuth {
|
|
s.Emit("error", "ERR::NEED_AUTH")
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (c *ServerSocketController) AppLogin(s socketio.Conn, appId string, token string) {
|
|
if appId == "" || token == "" {
|
|
s.Emit("error", "ERR::AUTH_PARAM_INVALID")
|
|
s.Close()
|
|
return
|
|
}
|
|
appConfig, ok := c.appsConfig[appId]
|
|
if !ok {
|
|
s.Emit("error", "ERR::AUTH_APP_NOT_EXISTS")
|
|
s.Close()
|
|
return
|
|
}
|
|
if token != appConfig.Token {
|
|
s.Emit("error", "ERR::AUTH_APP_TOKEN_INVALID")
|
|
s.Close()
|
|
return
|
|
}
|
|
|
|
// 设置登录状态
|
|
ctx := GetContext[ServerSocketContext](s)
|
|
ctx.IsAuth = true
|
|
|
|
s.Emit("auth:update", true)
|
|
|
|
log.Println("Server auth success: " + s.RemoteAddr().String())
|
|
}
|
|
|
|
func (c *ServerSocketController) UpdateUser(s socketio.Conn, user string, displayName string) {
|
|
if !c.CheckAuth(s) {
|
|
return
|
|
}
|
|
|
|
if user == "" {
|
|
s.Emit("error:user:update", "ERR::PARAMS_INVALID", user)
|
|
}
|
|
userInfo := c.storeModel.GetUserInfo(user)
|
|
if userInfo == nil {
|
|
userInfo = new(store.UserInfo)
|
|
}
|
|
|
|
if displayName != "" {
|
|
userInfo.DisplayName = displayName
|
|
} else {
|
|
userInfo.DisplayName = user
|
|
}
|
|
|
|
type PlayerInfoResponse struct {
|
|
Name string `json:"name"`
|
|
Token string `json:"token"`
|
|
IsOnline bool `json:"online"`
|
|
}
|
|
|
|
newBindingPlayers := make([]string, 0)
|
|
boundPlayers := make([]*PlayerInfoResponse, 0)
|
|
for _, token := range userInfo.BoundPlayer {
|
|
playerInfo := c.storeModel.GetPlayerInfo(token)
|
|
if playerInfo != nil {
|
|
newBindingPlayers = append(newBindingPlayers, token)
|
|
resPlayerInfo := new(PlayerInfoResponse)
|
|
resPlayerInfo.Name = playerInfo.Name
|
|
resPlayerInfo.Token = utils.AddAsterisks(token, 10, 10)
|
|
resPlayerInfo.IsOnline = playerInfo.IsOnline
|
|
boundPlayers = append(boundPlayers, resPlayerInfo)
|
|
}
|
|
}
|
|
|
|
userInfo.BoundPlayer = newBindingPlayers
|
|
|
|
// 保存用户信息
|
|
c.storeModel.SetUserInfo(user, userInfo)
|
|
|
|
s.Emit("user:updated", user, boundPlayers)
|
|
}
|
|
|
|
func (c *ServerSocketController) UserBindPlayer(s socketio.Conn, user string, code string) {
|
|
if !c.CheckAuth(s) {
|
|
return
|
|
}
|
|
|
|
if user == "" || code == "" {
|
|
s.Emit("error:user:player:bind", "ERR::PARAMS_INVALID", user, code)
|
|
}
|
|
instance := clientSocketControllerInstance
|
|
_, err := instance.BindPlayer(user, code)
|
|
if err != nil {
|
|
if errors.Is(err, ErrParamsInvalid) {
|
|
s.Emit("error:user:player:bind", "ERR::PARAMS_INVALID", user, code)
|
|
} else if errors.Is(err, ErrPlayerNotExists) {
|
|
s.Emit("error:user:player:bind", "ERR::PLAYER_NOT_EXISTS", user, code)
|
|
} else {
|
|
log.Println("Cannot bind user: ", err.Error())
|
|
s.Emit("error:user:player:bind", "ERR::UNKNOWN", user, code)
|
|
}
|
|
}
|
|
}
|
|
|
|
// OnBindUser 播放器绑定用户
|
|
func (c *ServerSocketController) OnBindUser(eventObj ...interface{}) {
|
|
event, err := utils.GetEvent[events.BindUserEvent](eventObj)
|
|
if err != nil {
|
|
log.Panicln("Cannot get event in OnBindUser: ", err.Error())
|
|
}
|
|
|
|
playerInfo := c.storeModel.GetPlayerInfo(event.Token)
|
|
if playerInfo == nil {
|
|
log.Println("Cannot find player info for token '" + event.Token + "' while bind player")
|
|
return
|
|
}
|
|
|
|
// 广播客户端连接的信息
|
|
c.sockets.BroadcastToNamespace(c.basePath, "user:player:bound", event.Token, playerInfo.Name)
|
|
}
|