func SocketInit(server *wsevent.Server, noauth *wsevent.Server, so *wsevent.Client) error { chelpers.AuthenticateSocket(so.Id(), so.Request()) loggedIn := chelpers.IsLoggedInSocket(so.Id()) if loggedIn { steamid := chelpers.GetSteamId(so.Id()) broadcaster.SetSocket(steamid, so) } if loggedIn { chelpers.AfterConnect(server, so) player, err := models.GetPlayerBySteamId(chelpers.GetSteamId(so.Id())) if err != nil { helpers.Logger.Warning( "User has a cookie with but a matching player record doesn't exist: %s", chelpers.GetSteamId(so.Id())) chelpers.DeauthenticateSocket(so.Id()) so.Close() return ErrRecordNotFound } chelpers.AfterConnectLoggedIn(server, so, player) } else { chelpers.AfterConnect(noauth, so) so.EmitJSON(helpers.NewRequest("playerSettings", "{}")) so.EmitJSON(helpers.NewRequest("playerProfile", "{}")) } so.EmitJSON(helpers.NewRequest("socketInitialized", "{}")) return nil }
//SocketInit initializes the websocket connection for the provided socket func SocketInit(so *wsevent.Client) error { chelpers.AuthenticateSocket(so.ID, so.Request) loggedIn := chelpers.IsLoggedInSocket(so.ID) if loggedIn { steamid := chelpers.GetSteamId(so.ID) sessions.AddSocket(steamid, so) } if loggedIn { hooks.AfterConnect(socket.AuthServer, so) player, err := models.GetPlayerBySteamID(chelpers.GetSteamId(so.ID)) if err != nil { logrus.Warning( "User has a cookie with but a matching player record doesn't exist: %s", chelpers.GetSteamId(so.ID)) chelpers.DeauthenticateSocket(so.ID) hooks.AfterConnect(socket.UnauthServer, so) return ErrRecordNotFound } hooks.AfterConnectLoggedIn(so, player) } else { hooks.AfterConnect(socket.UnauthServer, so) so.EmitJSON(helpers.NewRequest("playerSettings", "{}")) so.EmitJSON(helpers.NewRequest("playerProfile", "{}")) } so.EmitJSON(helpers.NewRequest("socketInitialized", "{}")) return nil }
func AfterConnect(server *wsevent.Server, so *wsevent.Client) { server.AddClient(so, fmt.Sprintf("%s_public", config.GlobalChatRoom)) //room for global chat var lobbies []models.Lobby err := db.DB.Where("state = ?", models.LobbyStateWaiting).Order("id desc").Find(&lobbies).Error if err != nil { logrus.Error(err) return } so.EmitJSON(helpers.NewRequest("lobbyListData", models.DecorateLobbyListData(lobbies))) chelpers.BroadcastScrollback(so, 0) so.EmitJSON(helpers.NewRequest("subListData", models.DecorateSubstituteList())) }
func (Player) PlayerSettingsSet(so *wsevent.Client, args struct { Key *string `json:"key"` Value *string `json:"value"` }) interface{} { player, _ := models.GetPlayerBySteamID(chelpers.GetSteamId(so.ID)) err := player.SetSetting(*args.Key, *args.Value) if err != nil { return helpers.NewTPErrorFromError(err) } switch *args.Key { case "siteAlias": profile := models.DecoratePlayerProfileJson(player) so.EmitJSON(helpers.NewRequest("playerProfile", profile)) if lobbyID, _ := player.GetLobbyID(true); lobbyID != 0 { lobby, _ := models.GetLobbyByID(lobbyID) lobbyData := lobby.LobbyData(true) lobbyData.Send() } case "mumbleNick": if !reMumbleNick.MatchString(*args.Value) { return helpers.NewTPError("Invalid Mumble nick.", -1) } } return chelpers.EmptySuccessJS }
func (Player) PlayerSettingsSet(so *wsevent.Client, args struct { Key *string `json:"key"` Value *string `json:"value"` }) interface{} { player := chelpers.GetPlayer(so.Token) switch *args.Key { case "siteAlias": if len(*args.Value) > 32 { return errors.New("Site alias must be under 32 characters long.") } player.SetSetting(*args.Key, *args.Value) player.SetPlayerProfile() so.EmitJSON(helpers.NewRequest("playerProfile", player)) if lobbyID, _ := player.GetLobbyID(true); lobbyID != 0 { lob, _ := lobby.GetLobbyByID(lobbyID) slot, _ := lob.GetPlayerSlot(player) player.SetMumbleUsername(lob.Type, slot) lobby.BroadcastLobby(lob) } default: player.SetSetting(*args.Key, *args.Value) } return emptySuccess }
func SendMessage(steamid string, event string, content string) { socket, ok := GetSocket(steamid) if !ok { return } socket.EmitJSON(helpers.NewRequest(event, content)) }
func (Lobby) RequestLobbyListData(so *wsevent.Client, _ struct{}) interface{} { var lobbies []models.Lobby db.DB.Where("state = ?", models.LobbyStateWaiting).Order("id desc").Find(&lobbies) so.EmitJSON(helpers.NewRequest("lobbyListData", models.DecorateLobbyListData(lobbies))) return chelpers.EmptySuccessJS }
func BroadcastScrollback(so *wsevent.Client, room uint) { messages, err := chat.GetScrollback(int(room)) if err != nil { return } so.EmitJSON(helpers.NewRequest("chatScrollback", messages)) }
func (Lobby) RequestLobbyListData(_ *wsevent.Server, so *wsevent.Client, data []byte) []byte { var lobbies []models.Lobby db.DB.Where("state = ?", models.LobbyStateWaiting).Order("id desc").Find(&lobbies) list, _ := json.Marshal(models.DecorateLobbyListData(lobbies)) so.EmitJSON(helpers.NewRequest("lobbyListData", string(list))) return chelpers.EmptySuccessJS }
func SendMessageToRoom(room string, event string, content string) { if socketServer == nil { return } v := helpers.NewRequest(event, content) socketServer.BroadcastJSON(room, v) socketServerNoLogin.BroadcastJSON(room, v) }
func AfterConnect(server *wsevent.Server, so *wsevent.Client) { server.AddClient(so, fmt.Sprintf("%s_public", config.Constants.GlobalChatRoom)) //room for global chat var lobbies []models.Lobby err := db.DB.Where("state = ?", models.LobbyStateWaiting).Order("id desc").Find(&lobbies).Error if err != nil { helpers.Logger.Critical("%s", err.Error()) return } bytes, _ := json.Marshal(models.DecorateLobbyListData(lobbies)) if err != nil { helpers.Logger.Critical("Failed to send lobby list: %s", err.Error()) return } so.EmitJSON(helpers.NewRequest("lobbyListData", string(bytes))) BroadcastScrollback(so, 0) bytes, _ = json.Marshal(helpers.NewRequestFromObj("subListData", models.GetSubList())) so.EmitJSON(helpers.NewRequest("subListData", string(bytes))) }
func SendMessage(steamid string, event string, content interface{}) { sockets, ok := sessions.GetSockets(steamid) if !ok { return } for _, socket := range sockets { go func(so *wsevent.Client) { so.EmitJSON(helpers.NewRequest(event, content)) }(socket) } }
func SendMessageSkipIDs(skipID, steamid, event string, content interface{}) { sockets, ok := sessions.GetSockets(steamid) if !ok { return } for _, socket := range sockets { if socket.ID != skipID { socket.EmitJSON(helpers.NewRequest(event, content)) } } }
func BroadcastScrollback(so *wsevent.Client, room uint) { // bytes, _ := json.Marshal(ChatHistoryClearEvent{room}) // so.EmitJSON(helpers.NewRequest("chatHistoryClear", string(bytes))) messages, err := models.GetScrollback(int(room)) if err != nil { return } for i := len(messages) - 1; i != -1; i-- { so.EmitJSON(helpers.NewRequest("chatReceive", messages[i])) } }
//SocketInit initializes the websocket connection for the provided socket func SocketInit(so *wsevent.Client) error { loggedIn := so.Token != nil if loggedIn { hooks.AfterConnect(socket.AuthServer, so) steamid := so.Token.Claims.(*chelpers.TF2StadiumClaims).SteamID player, err := player.GetPlayerBySteamID(steamid) if err != nil { return fmt.Errorf("Couldn't find player record for %s", steamid) } hooks.AfterConnectLoggedIn(so, player) } else { hooks.AfterConnect(socket.UnauthServer, so) so.EmitJSON(helpers.NewRequest("playerSettings", "{}")) so.EmitJSON(helpers.NewRequest("playerProfile", "{}")) } so.EmitJSON(helpers.NewRequest("socketInitialized", "{}")) return nil }
func (Unauth) LobbySpectatorJoin(so *wsevent.Client, args struct { ID *uint `json:"id"` }) interface{} { lob, err := lobby.GetLobbyByID(*args.ID) if err != nil { return err } hooks.AfterLobbySpec(socket.UnauthServer, so, nil, lob) so.EmitJSON(helpers.NewRequest("lobbyData", lobby.DecorateLobbyData(lob, true))) return emptySuccess }
func (Lobby) UnAuthSpecJoin(so *wsevent.Client, args struct { ID *uint `json:"id"` }) interface{} { var lob *models.Lobby lob, tperr := models.GetLobbyByID(*args.ID) if tperr != nil { return tperr } hooks.AfterLobbySpec(socket.UnauthServer, so, lob) so.EmitJSON(helpers.NewRequest("lobbyData", models.DecorateLobbyData(lob, true))) return chelpers.EmptySuccessJS }
func SendMessageToRoom(room string, event string, content interface{}) { v := helpers.NewRequest(event, content) socket.AuthServer.BroadcastJSON(room, v) socket.UnauthServer.BroadcastJSON(room, v) }
func (Lobby) LobbyJoin(so *wsevent.Client, args struct { Id *uint `json:"id"` Class *string `json:"class"` Team *string `json:"team" valid:"red,blu"` Password *string `json:"password" empty:"-"` }) interface{} { p := chelpers.GetPlayer(so.Token) if banned, until := p.IsBannedWithTime(player.BanJoin); banned { ban, _ := p.GetActiveBan(player.BanJoin) return fmt.Errorf("You have been banned from joining lobbies till %s (%s)", until.Format(time.RFC822), ban.Reason) } //logrus.Debug("id %d class %s team %s", *args.Id, *args.Class, *args.Team) lob, tperr := lobby.GetLobbyByID(*args.Id) if tperr != nil { return tperr } if lob.Mumble { if banned, until := p.IsBannedWithTime(player.BanJoinMumble); banned { ban, _ := p.GetActiveBan(player.BanJoinMumble) return fmt.Errorf("You have been banned from joining Mumble lobbies till %s (%s)", until.Format(time.RFC822), ban.Reason) } } if lob.State == lobby.Ended { return errors.New("Cannot join a closed lobby.") } if lob.State == lobby.Initializing { return errors.New("Lobby is being setup right now.") } if lob.RegionLock { region, _ := helpers.GetRegion(chelpers.GetIPAddr(so.Request)) if region != lob.RegionCode { return errors.New("This lobby is region locked.") } } //Check if player is in the same lobby var sameLobby bool if id, err := p.GetLobbyID(false); err == nil && id == *args.Id { sameLobby = true } slot, tperr := format.GetSlot(lob.Type, *args.Team, *args.Class) if tperr != nil { return tperr } if prevId, _ := p.GetLobbyID(false); prevId != 0 && !sameLobby { lob, _ := lobby.GetLobbyByID(prevId) hooks.AfterLobbyLeave(lob, p, false, false) } tperr = lob.AddPlayer(p, slot, *args.Password) if tperr != nil { return tperr } if !sameLobby { hooks.AfterLobbyJoin(so, lob, p) } playersCnt := lob.GetPlayerNumber() lastNotif, timerExists := lobbyJoinLastNotif[lob.ID] if playersCnt >= notifThreshold[lob.Type] && !lob.IsEnoughPlayers(playersCnt) && (!timerExists || time.Since(lastNotif).Minutes() > 5) { lob.DiscordNotif(fmt.Sprintf("Almost ready [%d/%d]", playersCnt, lob.RequiredPlayers())) lobbyJoinLastNotif[lob.ID] = time.Now() } //check if lobby isn't already in progress (which happens when the player is subbing) lob.Lock() if lob.IsEnoughPlayers(playersCnt) && lob.State != lobby.InProgress && lob.State != lobby.ReadyingUp { lob.State = lobby.ReadyingUp lob.ReadyUpTimestamp = time.Now().Unix() + 30 lob.Save() helpers.GlobalWait.Add(1) time.AfterFunc(time.Second*30, func() { state := lob.CurrentState() //if all player's haven't readied up, //remove unreadied players and unready the //rest. //don't do this when: // lobby.State == Waiting (someone already unreadied up, so all players have been unreadied) // lobby.State == InProgress (all players have readied up, so the lobby has started) // lobby.State == Ended (the lobby has been closed) if state != lobby.Waiting && state != lobby.InProgress && state != lobby.Ended { lob.SetState(lobby.Waiting) removeUnreadyPlayers(lob) lob.UnreadyAllPlayers() //get updated lobby object lob, _ = lobby.GetLobbyByID(lob.ID) lobby.BroadcastLobby(lob) } helpers.GlobalWait.Done() }) room := fmt.Sprintf("%s_private", hooks.GetLobbyRoom(lob.ID)) broadcaster.SendMessageToRoom(room, "lobbyReadyUp", struct { Timeout int `json:"timeout"` }{30}) lobby.BroadcastLobbyList() } lob.Unlock() if lob.State == lobby.InProgress { //this happens when the player is a substitute db.DB.Preload("ServerInfo").First(lob, lob.ID) so.EmitJSON(helpers.NewRequest("lobbyStart", lobby.DecorateLobbyConnect(lob, p, slot))) } return emptySuccess }
func (Lobby) RequestLobbyListData(so *wsevent.Client, _ struct{}) interface{} { so.EmitJSON(helpers.NewRequest("lobbyListData", lobby.DecorateLobbyListData(lobby.GetWaitingLobbies(), false))) return emptySuccess }
func ServerInit(server *wsevent.Server, noAuthServer *wsevent.Server) { server.OnDisconnect = onDisconnect server.Extractor = getEvent noAuthServer.OnDisconnect = onDisconnect noAuthServer.Extractor = getEvent server.On("authenticationTest", func(server *wsevent.Server, so *wsevent.Client, data []byte) []byte { reqerr := chelpers.FilterRequest(so, 0, true) if reqerr != nil { bytes, _ := json.Marshal(reqerr) return bytes } bytes, _ := json.Marshal(struct { Message string `json:"message"` }{"authenticated"}) return bytes }) //Global Handlers server.Register(handler.Global{}) //Lobby Handlers server.Register(handler.Lobby{}) //server.On("lobbyCreate", handler.LobbyCreate) //Player Handlers server.Register(handler.Player{}) //Chat Handlers server.Register(handler.Chat{}) //Admin Handlers server.Register(handler.Admin{}) //Debugging handlers // if config.Constants.ServerMockUp { // server.On("debugLobbyFill", handler.DebugLobbyFill) // server.On("debugLobbyReady", handler.DebugLobbyReady) // server.On("debugUpdateStatsFilter", handler.DebugUpdateStatsFilter) // server.On("debugPlayerSub", handler.DebugPlayerSub) // } noAuthServer.On("lobbySpectatorJoin", func(s *wsevent.Server, so *wsevent.Client, data []byte) []byte { var args struct { Id *uint `json:"id"` } if err := chelpers.GetParams(data, &args); err != nil { return helpers.NewTPErrorFromError(err).Encode() } var lob *models.Lobby lob, tperr := models.GetLobbyById(*args.Id) if tperr != nil { return tperr.Encode() } chelpers.AfterLobbySpec(s, so, lob) bytes, _ := json.Marshal(models.DecorateLobbyData(lob, true)) so.EmitJSON(helpers.NewRequest("lobbyData", string(bytes))) return chelpers.EmptySuccessJS }) noAuthServer.On("getSocketInfo", (handler.Global{}).GetSocketInfo) noAuthServer.DefaultHandler = func(_ *wsevent.Server, so *wsevent.Client, data []byte) []byte { return helpers.NewTPError("Player isn't logged in.", -4).Encode() } }
func (Lobby) LobbyJoin(so *wsevent.Client, args struct { Id *uint `json:"id"` Class *string `json:"class"` Team *string `json:"team" valid:"red,blu"` Password *string `json:"password" empty:"-"` }) interface{} { player := chelpers.GetPlayerFromSocket(so.ID) if banned, until := player.IsBannedWithTime(models.PlayerBanJoin); banned { str := fmt.Sprintf("You have been banned from joining lobbies till %s", until.Format(time.RFC822)) return helpers.NewTPError(str, -1) } //logrus.Debug("id %d class %s team %s", *args.Id, *args.Class, *args.Team) lob, tperr := models.GetLobbyByID(*args.Id) if tperr != nil { return tperr } if lob.State == models.LobbyStateEnded { return helpers.NewTPError("Cannot join a closed lobby.", -1) } //Check if player is in the same lobby var sameLobby bool if id, err := player.GetLobbyID(false); err == nil && id == *args.Id { sameLobby = true } slot, tperr := models.LobbyGetPlayerSlot(lob.Type, *args.Team, *args.Class) if tperr != nil { return tperr } if prevId, _ := player.GetLobbyID(false); prevId != 0 && !sameLobby { lobby, _ := models.GetLobbyByID(prevId) hooks.AfterLobbyLeave(lobby, player) } tperr = lob.AddPlayer(player, slot, *args.Password) if tperr != nil { return tperr } if !sameLobby { hooks.AfterLobbyJoin(so, lob, player) } //check if lobby isn't already in progress (which happens when the player is subbing) if lob.IsFull() && lob.State != models.LobbyStateInProgress { lob.State = models.LobbyStateReadyingUp lob.ReadyUpTimestamp = time.Now().Unix() + 30 lob.Save() time.AfterFunc(time.Second*30, func() { lobby := &models.Lobby{} db.DB.First(lobby, lob.ID) //if all player's haven't readied up, //remove unreadied players and unready the //rest. if lobby.State != models.LobbyStateInProgress && lobby.State != models.LobbyStateEnded { removeUnreadyPlayers(lobby) lobby.State = models.LobbyStateWaiting lobby.Save() } }) room := fmt.Sprintf("%s_private", hooks.GetLobbyRoom(lob.ID)) broadcaster.SendMessageToRoom(room, "lobbyReadyUp", struct { Timeout int `json:"timeout"` }{30}) models.BroadcastLobbyList() } if lob.State == models.LobbyStateInProgress { //this happens when the player is a substitute db.DB.Preload("ServerInfo").First(lob, lob.ID) so.EmitJSON(helpers.NewRequest("lobbyStart", models.DecorateLobbyConnect(lob, player.Name, slot))) } return chelpers.EmptySuccessJS }