func TwitchLogoutHandler(w http.ResponseWriter, r *http.Request) { token, err := controllerhelpers.GetToken(r) if err == http.ErrNoCookie { http.Error(w, "You are not logged in.", http.StatusUnauthorized) return } else if err != nil { http.Error(w, "Invalid jwt", http.StatusBadRequest) return } id := token.Claims.(*controllerhelpers.TF2StadiumClaims).PlayerID player, _ := player.GetPlayerByID(id) player.TwitchName = "" player.TwitchAccessToken = "" player.Save() referer, ok := r.Header["Referer"] if ok { http.Redirect(w, r, referer[0], 303) return } http.Redirect(w, r, config.Constants.LoginRedirectPath, http.StatusTemporaryRedirect) }
//RemoveUnreadyPlayers removes players who haven't removed. If spec == true, move them to spectators func (lobby *Lobby) RemoveUnreadyPlayers(spec bool) error { playerids := []uint{} if spec { //get list of player ids which are not ready err := db.DB.Model(&LobbySlot{}).Where("lobby_id = ? AND ready = ?", lobby.ID, false).Pluck("player_id", &playerids).Error if err != nil { return err } } //remove players which aren't ready lobby.Lock() err := db.DB.Where("lobby_id = ? AND ready = ?", lobby.ID, false).Delete(&LobbySlot{}).Error lobby.Unlock() if spec { for _, id := range playerids { p, _ := player.GetPlayerByID(id) lobby.AddSpectator(p) } } lobby.OnChange(true) return err }
func TwitchLoginHandler(w http.ResponseWriter, r *http.Request) { token, err := controllerhelpers.GetToken(r) if err == http.ErrNoCookie { http.Error(w, "You are not logged in.", http.StatusUnauthorized) return } else if err != nil { http.Error(w, "Invalid jwt", http.StatusBadRequest) return } id := token.Claims.(*controllerhelpers.TF2StadiumClaims).PlayerID player, _ := player.GetPlayerByID(id) loginURL := url.URL{ Scheme: "https", Host: "api.twitch.tv", Path: "kraken/oauth2/authorize", } //twitchRedirectURL := config.Constants.PublicAddress + "/" + "twitchAuth" twitchRedirectURL, _ := url.Parse(config.Constants.PublicAddress) twitchRedirectURL.Path = "twitchAuth" values := loginURL.Query() values.Set("response_type", "code") values.Set("client_id", config.Constants.TwitchClientID) values.Set("redirect_uri", twitchRedirectURL.String()) values.Set("scope", "channel_check_subscription user_subscriptions channel_subscriptions user_read") values.Set("state", xsrftoken.Generate(config.Constants.CookieStoreSecret, player.SteamID, "GET")) loginURL.RawQuery = values.Encode() http.Redirect(w, r, loginURL.String(), http.StatusTemporaryRedirect) }
func decorateSlotDetails(lobby *Lobby, slot int, playerInfo bool) SlotDetails { playerId, err := lobby.GetPlayerIDBySlot(slot) needsSub := lobby.SlotNeedsSubstitute(slot) slotDetails := SlotDetails{Slot: slot, Filled: err == nil && !needsSub} if err == nil && playerInfo && !needsSub { p, _ := player.GetPlayerByID(playerId) p.SetPlayerSummary() slotDetails.Player = p ready, _ := lobby.IsPlayerReady(p) slotDetails.Ready = &ready ingame := lobby.IsPlayerInGame(p) slotDetails.InGame = &ingame inmumble := lobby.IsPlayerInMumble(p) slotDetails.InMumble = &inmumble } if lobby.HasSlotRequirement(slot) { req, _ := lobby.GetSlotRequirement(slot) if req != nil { slotDetails.Requirements = req slotDetails.Password = req.Password != "" } } return slotDetails }
// shitlord func CheckPrivilege(so *wsevent.Client, action authority.AuthAction) error { //Checks if the client has the neccesary authority to perform action player, _ := player.GetPlayerByID(so.Token.Claims.(*TF2StadiumClaims).PlayerID) if !player.Role.Can(action) { return errors.New("You are not authorized to perform this action") } return nil }
//Not really broadcast, since it sends each client a different LobbyStart JSON func BroadcastLobbyStart(lob *lobby.Lobby) { for _, slot := range lob.GetAllSlots() { player, _ := player.GetPlayerByID(slot.PlayerID) connectInfo := lobby.DecorateLobbyConnect(lob, player, slot.Slot) broadcaster.SendMessage(player.SteamID, "lobbyStart", connectInfo) } }
func mumbleLeft(playerID uint) { player, _ := playerpackage.GetPlayerByID(playerID) id, _ := player.GetLobbyID(false) if id == 0 { // player joined mumble lobby for closed channel return } lobby, _ := lobbypackage.GetLobbyByID(id) lobby.SetNotInMumble(player) }
//UpdateStats updates the PlayerStats records for all players in the lobby //(increments the relevent lobby type field by one). Used when the lobby successfully ends. func (lobby *Lobby) UpdateStats() { db.DB.Preload("Slots").First(lobby, lobby.ID) for _, slot := range lobby.Slots { p, _ := player.GetPlayerByID(slot.PlayerID) db.DB.Preload("Stats").First(p, slot.PlayerID) p.Stats.PlayedCountIncrease(lobby.Type) p.Stats.IncreaseClassCount(lobby.Type, slot.Slot) p.Save() } lobby.OnChange(false) }
// move player_settings values to player.Settings hstore func setPlayerSettings() { rows, err := db.DB.DB().Query("SELECT player_id, key, value FROM player_settings") if err != nil { logrus.Fatal(err) } for rows.Next() { var playerID uint var key, value string rows.Scan(&playerID, &key, &value) p, _ := player.GetPlayerByID(playerID) p.SetSetting(key, value) } db.DB.Exec("DROP TABLE player_settings") }
func moveReportsServers() { type oldReport struct { PlayerID uint LobbyID uint } reportTypes := []struct { table string rtype player.ReportType }{ {"ragequits_player_lobbies", player.RageQuit}, {"reports_player_lobbies", player.Vote}, {"substitutes_player_lobbies", player.Substitute}, } for _, rtype := range reportTypes { rows, _ := db.DB.DB().Query("SELECT * FROM " + rtype.table) logrus.Info("Creating entries for ", rtype.table) for rows.Next() { var report oldReport rows.Scan(&report.PlayerID, &report.LobbyID) p, _ := player.GetPlayerByID(report.PlayerID) newReport := &player.Report{ PlayerID: p.ID, LobbyID: report.LobbyID, Type: rtype.rtype, } db.DB.Create(newReport) } } db.DB.Exec("DROP TABLE ragequits_player_lobbies") db.DB.Exec("DROP TABLE reports_player_lobbies") db.DB.Exec("DROP TABLE substitutes_player_lobbies") }
//AddPlayer adds the given player to lobby, If the player occupies a slot in the lobby already, switch slots. //If the player is in another lobby, removes them from that lobby before adding them. func (lobby *Lobby) AddPlayer(p *player.Player, slot int, password string) error { /* Possible errors while joining * Slot has been filled * Player has already joined a lobby * anything else? */ //Check if player is banned if lobby.IsPlayerBanned(p) { return ErrLobbyBan } if slot >= 2*format.NumberOfClassesMap[lobby.Type] || slot < 0 { return ErrBadSlot } isSubstitution := lobby.SlotNeedsSubstitute(slot) //Check whether the slot is occupied if !isSubstitution && lobby.IsSlotOccupied(slot) { return ErrFilled } if lobby.HasSlotRequirement(slot) { //check if player fits the requirements for the slot if ok, err := lobby.FitsRequirements(p, slot); !ok { return err } req, _ := lobby.GetSlotRequirement(slot) if password != req.Password { return ErrInvalidPassword } } var slotChange bool //Check if the player is currently in another lobby if currLobbyID, err := p.GetLobbyID(false); err == nil { if currLobbyID != lobby.ID { //if the player is in a different lobby, remove them from that lobby //plus substitute them curLobby, _ := GetLobbyByID(currLobbyID) if curLobby.State == InProgress { curLobby.Substitute(p) } else { curLobby.Lock() db.DB.Where("player_id = ? AND lobby_id = ?", p.ID, curLobby.ID).Delete(&LobbySlot{}) curLobby.Unlock() } } else { //player is in the same lobby, they're changing their slots //assign the player to a new slot if isSubstitution { //the slot needs a substitute (which happens when the lobby is in progress), //so players already in the lobby cannot fill it. return ErrNeedsSub } lobby.Lock() db.DB.Where("player_id = ? AND lobby_id = ?", p.ID, lobby.ID).Delete(&LobbySlot{}) lobby.Unlock() slotChange = true } } if !slotChange { //check if the player is in the steam group whitelist url := fmt.Sprintf(`http://steamcommunity.com/groups/%s/memberslistxml/?xml=1`, lobby.PlayerWhitelist) if lobby.PlayerWhitelist != "" && !helpers.IsWhitelisted(p.SteamID, url) { return ErrNotWhitelisted } //check if player has been subbed to the twitch channel (if any) //allow channel owners if lobby.TwitchChannel != "" && p.TwitchName != lobby.TwitchChannel { //check if player has connected their twitch account if p.TwitchAccessToken == "" { return errors.New("You need to connect your Twitch Account first to join the lobby.") } if lobby.TwitchRestriction == TwitchSubscribers && !p.IsSubscribed(lobby.TwitchChannel) { return fmt.Errorf("You aren't subscribed to %s", lobby.TwitchChannel) } if lobby.TwitchRestriction == TwitchFollowers && !p.IsFollowing(lobby.TwitchChannel) { return fmt.Errorf("You aren't following %s", lobby.TwitchChannel) } } } // Check if player is a substitute (the slot needs a subtitute) if isSubstitution { //get previous slot, to kick them from game prevPlayerID, _ := lobby.GetPlayerIDBySlot(slot) prevPlayer, _ := player.GetPlayerByID(prevPlayerID) lobby.Lock() db.DB.Where("lobby_id = ? AND slot = ?", lobby.ID, slot).Delete(&LobbySlot{}) lobby.Unlock() go func() { //kicks previous slot occupant if they're in-game, resets their !rep count, removes them from the lobby rpc.DisallowPlayer(lobby.ID, prevPlayer.SteamID, prevPlayer.ID) BroadcastSubList() //since the sub slot has been deleted, broadcast the updated substitute list //notify players in game server of subtitute class, team, _ := format.GetSlotTeamClass(lobby.Type, slot) rpc.Say(lobby.ID, fmt.Sprintf("Substitute found for %s %s: %s (%s)", team, class, p.Name, p.SteamID)) }() //allow player in mumble } //try to remove them from spectators lobby.RemoveSpectator(p, true) newSlotObj := &LobbySlot{ PlayerID: p.ID, LobbyID: lobby.ID, Slot: slot, } lobby.Lock() db.DB.Create(newSlotObj) lobby.Unlock() if !slotChange { if p.TwitchName != "" { rpc.TwitchBotAnnouce(p.TwitchName, lobby.ID) } } lobby.OnChange(true) p.SetMumbleUsername(lobby.Type, slot) return nil }
func TwitchAuthHandler(w http.ResponseWriter, r *http.Request) { token, err := controllerhelpers.GetToken(r) if err == http.ErrNoCookie { http.Error(w, "You are not logged in.", http.StatusUnauthorized) return } else if err != nil { http.Error(w, "Invalid jwt", http.StatusBadRequest) return } id := token.Claims.(*controllerhelpers.TF2StadiumClaims).PlayerID player, _ := player.GetPlayerByID(id) values := r.URL.Query() code := values.Get("code") if code == "" { http.Error(w, "No code given", http.StatusBadRequest) return } state := values.Get("state") if state == "" || !xsrftoken.Valid(state, config.Constants.CookieStoreSecret, player.SteamID, "GET") { http.Error(w, "Missing or Invalid XSRF token", http.StatusBadRequest) return } twitchRedirectURL, _ := url.Parse(config.Constants.PublicAddress) twitchRedirectURL.Path = "twitchAuth" // successful login, try getting access token now tokenURL := url.URL{ Scheme: "https", Host: "api.twitch.tv", Path: "kraken/oauth2/token", } values = tokenURL.Query() values.Set("client_id", config.Constants.TwitchClientID) values.Set("client_secret", config.Constants.TwitchClientSecret) values.Set("grant_type", "authorization_code") values.Set("redirect_uri", twitchRedirectURL.String()) values.Set("code", code) values.Set("state", state) req, err := http.NewRequest("POST", tokenURL.String(), strings.NewReader(values.Encode())) if err != nil { logrus.Error(err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } resp, err := helpers.HTTPClient.Do(req) if err != nil { logrus.Error(err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } reply := reply{} dec := json.NewDecoder(resp.Body) err = dec.Decode(&reply) if err != nil { logrus.Error(err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } info, err := getUserInfo(reply.AccessToken) if err != nil { logrus.Error(err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } player.TwitchName = info.Name player.TwitchAccessToken = reply.AccessToken player.Save() http.Redirect(w, r, config.Constants.LoginRedirectPath, http.StatusTemporaryRedirect) }
func DecorateLobbyData(lobby *Lobby, playerInfo bool) LobbyData { lobbyData := LobbyData{ ID: lobby.ID, Mode: lobby.Mode, Type: format.FriendlyNamesMap[lobby.Type], Players: lobby.GetPlayerNumber(), Map: lobby.MapName, League: lobby.League, Mumble: lobby.Mumble, Discord: lobby.Discord, TwitchChannel: lobby.TwitchChannel, TwitchRestriction: lobby.TwitchRestriction.String(), RegionLock: lobby.RegionLock, RedTeamName: lobby.RedTeamName, BluTeamName: lobby.BluTeamName, SteamGroup: lobby.PlayerWhitelist, } lobbyData.Region.Name = lobby.RegionName lobbyData.Region.Code = lobby.RegionCode classList := format.GetClasses(lobby.Type) classes := make([]ClassDetails, len(classList)) lobbyData.MaxPlayers = format.NumberOfClassesMap[lobby.Type] * 2 for slot, className := range classList { class := ClassDetails{ Red: decorateSlotDetails(lobby, slot, playerInfo), Blu: decorateSlotDetails(lobby, slot+format.NumberOfClassesMap[lobby.Type], playerInfo), Class: className, } classes[slot] = class } lobbyData.Classes = classes lobbyData.WhitelistID = lobby.Whitelist if !playerInfo { return lobbyData } if lobby.CreatedBySteamID != "" { // == "" during tests leader, _ := player.GetPlayerBySteamID(lobby.CreatedBySteamID) leader.SetPlayerSummary() lobbyData.Leader = *leader } lobbyData.CreatedAt = lobby.CreatedAt.Unix() lobbyData.State = int(lobby.State) var specIDs []uint db.DB.Table("spectators_players_lobbies").Where("lobby_id = ?", lobby.ID).Pluck("player_id", &specIDs) spectators := make([]SpecDetails, len(specIDs)) for i, spectatorID := range specIDs { specPlayer, _ := player.GetPlayerByID(spectatorID) specJs := SpecDetails{ Name: specPlayer.Alias(), SteamID: specPlayer.SteamID, } spectators[i] = specJs } lobbyData.Spectators = spectators return lobbyData }
func GetPlayer(token *jwt.Token) *player.Player { player, _ := player.GetPlayerByID(token.Claims.(*TF2StadiumClaims).PlayerID) return player }