コード例 #1
0
ファイル: player.go プロジェクト: TF2Stadium/Helen
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
}
コード例 #2
0
ファイル: player.go プロジェクト: TF2Stadium/Helen
func (Player) PlayerRecentLobbies(so *wsevent.Client, args struct {
	SteamID *string `json:"steamid"`
	Lobbies *int    `json:"lobbies"`
	LobbyID int     `json:"lobbyId"` // start from this lobbyID, 0 when not specified in json
}) interface{} {
	var p *player.Player

	if *args.SteamID != "" {
		var err error
		p, err = player.GetPlayerBySteamID(*args.SteamID)
		if err != nil {
			return err
		}

	} else {
		p = chelpers.GetPlayer(so.Token)
	}

	var lobbies []*lobby.Lobby

	db.DB.Model(&lobby.Lobby{}).Joins("INNER JOIN lobby_slots ON lobbies.ID = lobby_slots.lobby_id").
		Where("lobbies.match_ended = TRUE and lobby_slots.player_id = ? AND lobby_slots.needs_sub = FALSE AND lobbies.ID >= ?", p.ID, args.LobbyID).
		Order("lobbies.id desc").
		Limit(*args.Lobbies).
		Find(&lobbies)

	return newResponse(lobby.DecorateLobbyListData(lobbies, true))
}
コード例 #3
0
ファイル: mumble.go プロジェクト: TF2Stadium/Helen
func ResetMumblePassword(w http.ResponseWriter, r *http.Request) {
	token, err := chelpers.GetToken(r)
	if err != nil {
		http.Error(w, "You aren't logged in.", http.StatusForbidden)
		return
	}

	player := chelpers.GetPlayer(token)
	player.MumbleAuthkey = player.GenAuthKey()
	player.Save()

	newToken := chelpers.NewToken(player)
	cookie := &http.Cookie{
		Name:    "auth-jwt",
		Value:   newToken,
		Path:    "/",
		Domain:  config.Constants.CookieDomain,
		Expires: time.Now().Add(30 * 24 * time.Hour),
	}
	http.SetCookie(w, cookie)

	referer, ok := r.Header["Referer"]
	if ok {
		http.Redirect(w, r, referer[0], 303)
		return
	}

	http.Redirect(w, r, config.Constants.LoginRedirectPath, 303)
}
コード例 #4
0
ファイル: lobby.go プロジェクト: TF2Stadium/Helen
func (Lobby) LobbySetTeamName(so *wsevent.Client, args struct {
	Id      uint   `json:"id"`
	Team    string `json:"team"`
	NewName string `json:"name"`
}) interface{} {
	player := chelpers.GetPlayer(so.Token)

	lob, err := lobby.GetLobbyByID(args.Id)
	if err != nil {
		return err
	}

	if player.SteamID != lob.CreatedBySteamID && (player.Role != helpers.RoleAdmin && player.Role != helpers.RoleMod) {
		return errors.New("You aren't authorized to do this.")
	}

	if len(args.NewName) == 0 || len(args.NewName) > 12 {
		return errors.New("team name must be between 1-12 characters long.")
	}

	if args.Team == "red" {
		lob.RedTeamName = args.NewName
	} else if args.Team == "blu" {
		lob.BluTeamName = args.NewName
	} else {
		return errors.New("team must be red or blu.")
	}

	lob.Save()
	lobby.BroadcastLobby(lob)
	return emptySuccess
}
コード例 #5
0
ファイル: player.go プロジェクト: TF2Stadium/Helen
func (Player) PlayerReady(so *wsevent.Client, _ struct{}) interface{} {
	player := chelpers.GetPlayer(so.Token)
	lobbyid, tperr := player.GetLobbyID(false)
	if tperr != nil {
		return tperr
	}

	lob, err := lobby.GetLobbyByIDServer(lobbyid)
	if err != nil {
		return err
	}

	if lob.State != lobby.ReadyingUp {
		return errors.New("Lobby hasn't been filled up yet.")
	}

	err = lob.ReadyPlayer(player)

	if err != nil {
		return err
	}

	if lob.IsEveryoneReady() {
		lob.Start()

		hooks.BroadcastLobbyStart(lob)
		lobby.BroadcastLobbyList()
	}

	return emptySuccess
}
コード例 #6
0
ファイル: mumble.go プロジェクト: TF2Stadium/Helen
func (Mumble) ResetMumblePassword(so *wsevent.Client, _ struct{}) interface{} {
	player := chelpers.GetPlayer(so.Token)
	player.MumbleAuthkey = player.GenAuthKey()
	player.Save()

	return emptySuccess
}
コード例 #7
0
ファイル: player.go プロジェクト: TF2Stadium/Helen
func (Player) PlayerNotReady(so *wsevent.Client, _ struct{}) interface{} {
	player := chelpers.GetPlayer(so.Token)
	lobbyid, tperr := player.GetLobbyID(false)
	if tperr != nil {
		return tperr
	}

	lob, err := lobby.GetLobbyByID(lobbyid)
	if err != nil {
		return err
	}

	if lob.State != lobby.ReadyingUp {
		return errors.New("Lobby hasn't been filled up yet.")
	}

	err = lob.UnreadyPlayer(player)
	lob.RemovePlayer(player)
	hooks.AfterLobbyLeave(lob, player, false, false)
	if spec := sessions.IsSpectating(so.ID, lob.ID); spec {
		// IsSpectating checks if the player has joined the lobby's public room
		lob.AddSpectator(player)
	}

	if tperr != nil {
		return tperr
	}

	lob.SetState(lobby.Waiting)
	lob.UnreadyAllPlayers()
	lobby.BroadcastLobby(lob)
	return emptySuccess
}
コード例 #8
0
ファイル: lobby.go プロジェクト: TF2Stadium/Helen
func (Lobby) LobbyChangeOwner(so *wsevent.Client, args struct {
	ID      *uint   `json:"id"`
	SteamID *string `json:"steamid"`
}) interface{} {
	lob, err := lobby.GetLobbyByID(*args.ID)
	if err != nil {
		return err
	}

	// current owner
	player1 := chelpers.GetPlayer(so.Token)
	if lob.CreatedBySteamID != player1.SteamID {
		return errors.New("You aren't authorized to change lobby owner.")
	}

	// to be owner
	player2, err := player.GetPlayerBySteamID(*args.SteamID)
	if err != nil {
		return err
	}

	lob.CreatedBySteamID = player2.SteamID
	lob.Save()
	lobby.BroadcastLobby(lob)
	lobby.BroadcastLobbyList()
	chat.NewBotMessage(fmt.Sprintf("Lobby leader changed to %s", player2.Alias()), int(*args.ID)).Send()

	return emptySuccess
}
コード例 #9
0
ファイル: static.go プロジェクト: TF2Stadium/Helen
func MainHandler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}

	var p *player.Player
	token, err := controllerhelpers.GetToken(r)

	if err == nil {
		p = controllerhelpers.GetPlayer(token)
	}

	errtempl := mainTempl.Execute(w, map[string]interface{}{
		"LoggedIn":  err == nil,
		"Player":    p,
		"MockLogin": config.Constants.MockupAuth,
		"BuildDate": version.BuildDate,
		"GitCommit": version.GitCommit,
		"GitBranch": version.GitBranch,
		"BuildInfo": fmt.Sprintf("Built using %s on %s (%s %s)", runtime.Version(), version.Hostname, runtime.GOOS, runtime.GOARCH),
	})
	if errtempl != nil {
		logrus.Error(err)
	}
}
コード例 #10
0
ファイル: lobby.go プロジェクト: TF2Stadium/Helen
func (Lobby) LobbyClose(so *wsevent.Client, args struct {
	Id *uint `json:"id"`
}) interface{} {

	player := chelpers.GetPlayer(so.Token)
	lob, tperr := lobby.GetLobbyByIDServer(uint(*args.Id))
	if tperr != nil {
		return tperr
	}

	if player.SteamID != lob.CreatedBySteamID && !(player.Role == helpers.RoleAdmin || player.Role == helpers.RoleMod) {
		return errors.New("Player not authorized to close lobby.")

	}

	if lob.State == lobby.Ended {
		return errors.New("Lobby already closed.")
	}

	lob.Close(true, false)

	notify := fmt.Sprintf("Lobby closed by %s", player.Alias())
	chat.SendNotification(notify, int(lob.ID))

	return emptySuccess
}
コード例 #11
0
ファイル: lobby.go プロジェクト: TF2Stadium/Helen
func (Lobby) LobbyServerReset(so *wsevent.Client, args struct {
	ID *uint `json:"id"`
}) interface{} {

	player := chelpers.GetPlayer(so.Token)
	lob, tperr := lobby.GetLobbyByID(*args.ID)

	if player.SteamID != lob.CreatedBySteamID && (player.Role != helpers.RoleAdmin && player.Role != helpers.RoleMod) {
		return errors.New("You are not authorized to reset server.")
	}

	if tperr != nil {
		return tperr
	}

	if lob.State == lobby.Ended {
		return errors.New("Lobby has ended")
	}

	if err := rpc.ReExecConfig(lob.ID, false); err != nil {
		return err
	}

	return emptySuccess
}
コード例 #12
0
ファイル: socket.go プロジェクト: TF2Stadium/Helen
//OnDisconnect is connected when a player with a given socketID disconnects
func OnDisconnect(socketID string, token *jwt.Token) {
	if token != nil { //player was logged in
		player := chelpers.GetPlayer(token)
		if player == nil {
			return
		}

		sessions.RemoveSocket(socketID, player.SteamID)
		id, _ := sessions.GetSpectating(socketID)
		if id != 0 {
			lob, _ := lobby.GetLobbyByID(id)
			lob.RemoveSpectator(player, true)
		}

		id, _ = player.GetLobbyID(true)
		//if player is in a waiting lobby, and hasn't connected for > 30 seconds,
		//remove him from it. Here, connected = player isn't connected from any tab/window
		if id != 0 && sessions.ConnectedSockets(player.SteamID) == 0 {
			sessions.AfterDisconnectedFunc(player.SteamID, time.Second*30, func() {
				lob, _ := lobby.GetLobbyByID(id)
				if lob.State == lobby.Waiting {
					lob.RemovePlayer(player)
				}
			})
		}
	}

}
コード例 #13
0
ファイル: player.go プロジェクト: TF2Stadium/Helen
func (Player) PlayerDisableTwitchBot(so *wsevent.Client, _ struct{}) interface{} {
	player := chelpers.GetPlayer(so.Token)
	if player.TwitchName == "" {
		return errors.New("Please connect your Twitch Account first.")
	}

	changeMu.RLock()
	last := lastTwitchBotChange[player.ID]
	changeMu.RUnlock()
	if time.Since(last) < time.Minute {
		return errors.New("Please wait for a minute before changing the bot's status")
	}

	rpc.TwitchBotLeave(player.TwitchName)

	changeMu.Lock()
	lastTwitchBotChange[player.ID] = time.Now()
	changeMu.Unlock()

	time.AfterFunc(1*time.Minute, func() {
		changeMu.Lock()
		delete(lastTwitchBotChange, player.ID)
		changeMu.Unlock()
	})
	return emptySuccess
}
コード例 #14
0
ファイル: mumble.go プロジェクト: TF2Stadium/Helen
func (Mumble) GetMumblePassword(so *wsevent.Client, _ struct{}) interface{} {
	player := chelpers.GetPlayer(so.Token)

	return newResponse(struct {
		Password string `json:"password"`
	}{player.MumbleAuthkey})
}
コード例 #15
0
ファイル: lobby.go プロジェクト: TF2Stadium/Helen
func (Lobby) LobbySetRequirement(so *wsevent.Client, args struct {
	ID *uint `json:"id"` // lobby ID

	Slot     *int         `json:"slot"` // -1 if to set for all slots
	Type     *string      `json:"type"`
	Value    *json.Number `json:"value"`
	Password *string      `json:"password" empty:"-"`
}) interface{} {

	lob, err := lobby.GetLobbyByID(*args.ID)
	if err != nil {
		return err
	}

	player := chelpers.GetPlayer(so.Token)
	if lob.CreatedBySteamID != player.SteamID {
		return errors.New("Only lobby owners can change requirements.")
	}

	if !(*args.Slot >= 0 && *args.Slot < 2*format.NumberOfClassesMap[lob.Type]) {
		return errors.New("Invalid slot.")
	}

	req, err := lob.GetSlotRequirement(*args.Slot)
	if err != nil { //requirement doesn't exist. create one
		req.Slot = *args.Slot
		req.LobbyID = *args.ID
	}

	var n int64
	var f float64

	switch *args.Type {
	case "hours":
		n, err = args.Value.Int64()
		req.Hours = int(n)
	case "lobbies":
		n, err = args.Value.Int64()
		req.Lobbies = int(n)
	case "reliability":
		f, err = args.Value.Float64()
		req.Reliability = f
	case "password":
		req.Password = *args.Password
	default:
		return errors.New("Invalid requirement type.")
	}

	if err != nil {
		return errors.New("Invalid requirement.")
	}

	req.Save()
	lobby.BroadcastLobby(lob)
	lobby.BroadcastLobbyList()

	return emptySuccess
}
コード例 #16
0
ファイル: player.go プロジェクト: TF2Stadium/Helen
func (Player) PlayerSettingsGet(so *wsevent.Client, args struct {
	Key *string `json:"key"`
}) interface{} {

	player := chelpers.GetPlayer(so.Token)
	if *args.Key == "*" {
		return newResponse(player.Settings)
	}

	setting := player.GetSetting(*args.Key)
	return newResponse(setting)
}
コード例 #17
0
ファイル: chat.go プロジェクト: TF2Stadium/Helen
func (Chat) ChatSend(so *wsevent.Client, args struct {
	Message *string `json:"message"`
	Room    *int    `json:"room"`
}) interface{} {
	p := chelpers.GetPlayer(so.Token)
	if banned, until := p.IsBannedWithTime(player.BanChat); banned {
		ban, _ := p.GetActiveBan(player.BanChat)
		return fmt.Errorf("You've been banned from creating lobbies till %s (%s)", until.Format(time.RFC822), ban.Reason)
	}

	if *args.Room > 0 {
		//Check if player has either joined, or is spectating lobby
		var count int
		spec := p.IsSpectatingID(uint(*args.Room))
		db.DB.Model(&lobby.LobbySlot{}).Where("lobby_id = ? AND player_id = ?", *args.Room, p.ID).Count(&count)

		if !spec && count == 0 {
			return errors.New("Player is not in the lobby.")
		}
	} else {
		// else room is the lobby list room
		*args.Room = 0
	}
	switch {
	case len(*args.Message) == 0:
		return errors.New("Cannot send an empty message")

	case (*args.Message)[0] == '\n':
		return errors.New("Cannot send messages prefixed with newline")

	case len(*args.Message) > 150:
		return errors.New("Message too long")
	}

	message := chat.NewChatMessage(*args.Message, *args.Room, p)

	if strings.HasPrefix(*args.Message, "!admin") {
		chelpers.SendToSlack(*args.Message, p.Name, p.SteamID)
		return emptySuccess
	}

	message.Save()
	message.Send()

	return emptySuccess
}
コード例 #18
0
ファイル: lobby.go プロジェクト: TF2Stadium/Helen
func (Lobby) LobbySpectatorJoin(so *wsevent.Client, args struct {
	Id *uint `json:"id"`
}) interface{} {

	lob, err := lobby.GetLobbyByID(*args.Id)

	if err != nil {
		return err
	}

	player := chelpers.GetPlayer(so.Token)
	var specSameLobby bool

	arr, tperr := player.GetSpectatingIds()
	if len(arr) != 0 {
		for _, id := range arr {
			if id == *args.Id {
				specSameLobby = true
				continue
			}
			//a socket should only spectate one lobby, remove socket from
			//any other lobby room
			//multiple sockets from one player can spectatte multiple lobbies
			socket.AuthServer.Leave(so, fmt.Sprintf("%d_public", id))
		}
	}

	// If the player is already in the lobby (either joined a slot or is spectating), don't add them.
	// Just Broadcast the lobby to them, so the frontend displays it.
	if id, _ := player.GetLobbyID(false); id != *args.Id && !specSameLobby {
		tperr = lob.AddSpectator(player)

		if tperr != nil {
			return tperr
		}
	}

	hooks.AfterLobbySpec(socket.AuthServer, so, player, lob)
	lobby.BroadcastLobbyToUser(lob, player.SteamID)
	return emptySuccess
}
コード例 #19
0
ファイル: lobby.go プロジェクト: TF2Stadium/Helen
func (Lobby) LobbyRemoveSteamRestriction(so *wsevent.Client, args struct {
	ID uint `json:"id"`
}) interface{} {
	player := chelpers.GetPlayer(so.Token)

	lob, err := lobby.GetLobbyByID(args.ID)
	if err != nil {
		return err
	}

	if player.SteamID != lob.CreatedBySteamID && (player.Role != helpers.RoleAdmin && player.Role != helpers.RoleMod) {
		return errors.New("You aren't authorized to do this.")
	}

	lob.PlayerWhitelist = ""
	lob.Save()

	lobby.BroadcastLobby(lob)
	lobby.BroadcastLobbyList()

	return emptySuccess
}
コード例 #20
0
ファイル: lobby.go プロジェクト: TF2Stadium/Helen
func (Lobby) LobbySpectatorLeave(so *wsevent.Client, args struct {
	Id *uint `json:"id"`
}) interface{} {

	player := chelpers.GetPlayer(so.Token)
	lob, tperr := lobby.GetLobbyByID(*args.Id)
	if tperr != nil {
		return tperr
	}

	if !player.IsSpectatingID(lob.ID) {
		if id, _ := player.GetLobbyID(false); id == *args.Id {
			hooks.AfterLobbySpecLeave(so, lob)
			return emptySuccess
		}
	}

	lob.RemoveSpectator(player, true)
	hooks.AfterLobbySpecLeave(so, lob)

	return emptySuccess
}
コード例 #21
0
ファイル: lobby.go プロジェクト: TF2Stadium/Helen
func (Lobby) LobbyShuffle(so *wsevent.Client, args struct {
	Id uint `json:"id"`
}) interface{} {
	player := chelpers.GetPlayer(so.Token)

	lob, err := lobby.GetLobbyByID(args.Id)
	if err != nil {
		return err
	}

	if player.SteamID != lob.CreatedBySteamID && (player.Role != helpers.RoleAdmin && player.Role != helpers.RoleMod) {
		return errors.New("You aren't authorized to shuffle this lobby.")
	}

	if err = lob.ShuffleAllSlots(); err != nil {
		return err
	}

	room := fmt.Sprintf("%s_private", hooks.GetLobbyRoom(args.Id))
	broadcaster.SendMessageToRoom(room, "lobbyShuffled", args)
	chat.NewBotMessage(fmt.Sprintf("Lobby shuffled by %s", player.Alias()), int(args.Id)).Send()
	return emptySuccess
}
コード例 #22
0
ファイル: lobby.go プロジェクト: TF2Stadium/Helen
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
}
コード例 #23
0
ファイル: lobby.go プロジェクト: TF2Stadium/Helen
func (Lobby) LobbyCreate(so *wsevent.Client, args struct {
	Map         *string        `json:"map"`
	Type        *string        `json:"type" valid:"debug,6s,highlander,4v4,ultiduo,bball"`
	League      *string        `json:"league" valid:"ugc,etf2l,esea,asiafortress,ozfortress,bballtf"`
	ServerType  *string        `json:"serverType" valid:"server,storedServer,serveme"`
	Serveme     *servemeServer `json:"serveme" empty:"-"`
	Server      *string        `json:"server" empty:"-"`
	RconPwd     *string        `json:"rconpwd" empty:"-"`
	WhitelistID *string        `json:"whitelistID"`
	Mumble      *bool          `json:"mumbleRequired"`

	Password            *string `json:"password" empty:"-"`
	SteamGroupWhitelist *string `json:"steamGroupWhitelist" empty:"-"`
	// restrict lobby slots to twitch subs for a particular channel
	// not a pointer, since it is set to false when the argument json
	// string doesn't have the field
	TwitchWhitelistSubscribers bool `json:"twitchWhitelistSubs"`
	TwitchWhitelistFollowers   bool `json:"twitchWhitelistFollows"`
	RegionLock                 bool `json:"regionLock"`

	Requirements *struct {
		Classes map[string]Requirement `json:"classes,omitempty"`
		General Requirement            `json:"general,omitempty"`
	} `json:"requirements" empty:"-"`

	Discord *struct {
		RedChannel *string `json:"redChannel,omitempty"`
		BluChannel *string `json:"bluChannel,omitempty"`
	} `json:"discord" empty:"-"`
}) interface{} {
	p := chelpers.GetPlayer(so.Token)
	if banned, until := p.IsBannedWithTime(player.BanCreate); banned {
		ban, _ := p.GetActiveBan(player.BanCreate)
		return fmt.Errorf("You've been banned from creating lobbies till %s (%s)", until.Format(time.RFC822), ban.Reason)
	}

	if p.HasCreatedLobby() {
		if p.Role != helpers.RoleAdmin && p.Role != helpers.RoleMod {
			return errors.New("You have already created a lobby.")
		}
	}

	var steamGroup string
	var context *servemetf.Context
	var reservation servemetf.Reservation

	if *args.SteamGroupWhitelist != "" {
		if reSteamGroup.MatchString(*args.SteamGroupWhitelist) {
			steamGroup = reSteamGroup.FindStringSubmatch(*args.SteamGroupWhitelist)[1]
		} else {
			return errors.New("Invalid Steam group URL")
		}
	}

	if *args.ServerType == "serveme" {
		if args.Serveme == nil {
			return errors.New("No serveme info given.")
		}
		var err error
		var start, end time.Time

		if start, err = time.Parse(servemetf.TimeFormat, (*args.Serveme).StartsAt); err != nil {
			return err
		}
		if end, err = time.Parse(servemetf.TimeFormat, (*args.Serveme).EndsAt); err != nil {
			return err
		}

		randBytes := make([]byte, 6)
		rand.Read(randBytes)
		*args.RconPwd = base64.URLEncoding.EncodeToString(randBytes)

		reservation = servemetf.Reservation{
			StartsAt:    start.Format(servemetf.TimeFormat),
			EndsAt:      end.Format(servemetf.TimeFormat),
			ServerID:    (*args.Serveme).Server.ID,
			WhitelistID: 1,
			RCON:        *args.RconPwd,
			Password:    "******",
		}

		context = helpers.GetServemeContextIP(chelpers.GetIPAddr(so.Request))
		resp, err := context.Create(reservation, so.Token.Claims.(*chelpers.TF2StadiumClaims).SteamID)
		if err != nil || resp.Reservation.Errors != nil {
			if err != nil {
				logrus.Error(err)
			} else {
				logrus.Error(resp.Reservation.Errors)
			}

			return errors.New("Couldn't get serveme reservation")
		}

		*args.Server = resp.Reservation.Server.IPAndPort
		reservation = resp.Reservation
	} else if *args.ServerType == "storedServer" {
		if *args.Server == "" {
			return errors.New("No server ID given")
		}

		id, err := strconv.ParseUint(*args.Server, 10, 64)
		if err != nil {
			return err
		}
		server, err := gameserver.GetStoredServer(uint(id))
		if err != nil {
			return err
		}
		*args.Server = server.Address
		*args.RconPwd = server.RCONPassword
	} else { // *args.ServerType == "server"
		if args.RconPwd == nil || *args.RconPwd == "" {
			return errors.New("RCON Password cannot be empty")
		}
		if args.Server == nil || *args.Server == "" {
			return errors.New("Server Address cannot be empty")
		}
	}

	var count int

	lobbyType := playermap[*args.Type]
	db.DB.Model(&gameserver.ServerRecord{}).Where("host = ?", *args.Server).Count(&count)
	if count != 0 {
		return errors.New("A lobby is already using this server.")
	}

	randBytes := make([]byte, 6)
	rand.Read(randBytes)
	serverPwd := base64.URLEncoding.EncodeToString(randBytes)

	//TODO what if playermap[lobbytype] is nil?
	info := gameserver.ServerRecord{
		Host:           *args.Server,
		RconPassword:   *args.RconPwd,
		ServerPassword: serverPwd,
	}

	lob := lobby.NewLobby(*args.Map, lobbyType, *args.League, info, *args.WhitelistID, *args.Mumble, steamGroup)

	if args.TwitchWhitelistSubscribers || args.TwitchWhitelistFollowers {
		if p.TwitchName == "" {
			return errors.New("Please connect your twitch account first.")
		}

		lob.TwitchChannel = p.TwitchName
		if args.TwitchWhitelistFollowers {
			lob.TwitchRestriction = lobby.TwitchFollowers
		} else {
			lob.TwitchRestriction = lobby.TwitchSubscribers
		}
	}

	lob.Discord = args.Discord != nil
	if lob.Discord {
		if !reDiscordInvite.MatchString(*args.Discord.RedChannel) || !reDiscordInvite.MatchString(*args.Discord.BluChannel) {
			return errors.New("Invalid Discord invite URL")
		}

		lob.DiscordRedChannel = *args.Discord.RedChannel
		lob.DiscordBluChannel = *args.Discord.BluChannel
	}

	lob.RegionLock = args.RegionLock
	lob.CreatedBySteamID = p.SteamID
	lob.RegionCode, lob.RegionName = helpers.GetRegion(*args.Server)
	if (lob.RegionCode == "" || lob.RegionName == "") && config.Constants.GeoIP {
		if reservation.ID != 0 {
			err := context.Delete(reservation.ID, p.SteamID)
			for err != nil {
				err = context.Delete(reservation.ID, p.SteamID)
			}
		} else if *args.ServerType == "storedServer" {
			gameserver.PutStoredServer(*args.Server)
		}

		return errors.New("Couldn't find the region for this server.")
	}

	if lobby.MapRegionFormatExists(lob.MapName, lob.RegionCode, lob.Type) {
		if reservation.ID != 0 {
			err := context.Delete(reservation.ID, p.SteamID)
			for err != nil {
				err = context.Delete(reservation.ID, p.SteamID)
			}
		} else if *args.ServerType == "storedServer" {
			gameserver.PutStoredServer(*args.Server)
		}

		return errors.New("Your region already has a lobby with this map and format.")
	}

	if *args.ServerType == "serveme" {
		lob.ServemeID = reservation.ID
	}

	lob.Save()
	lob.CreateLock()

	if *args.ServerType == "serveme" {
		now := time.Now()

		for {
			status, err := context.Status(reservation.ID, p.SteamID)
			if err != nil {
				logrus.Error(err)
			}
			if status == "ready" {
				break
			}

			time.Sleep(10 * time.Second)
			if time.Since(now) >= 3*time.Minute {
				lob.Delete()
				return errors.New("Couldn't get Serveme reservation, try another server.")
			}
		}

		lob.ServemeCheck(context)
	}

	err := lob.SetupServer()
	if err != nil { //lobby setup failed, delete lobby and corresponding server record
		lob.Delete()
		return err
	}

	lob.SetState(lobby.Waiting)

	if args.Requirements != nil {
		for class, requirement := range (*args.Requirements).Classes {
			if requirement.Restricted.Blu {
				newRequirement("blu", class, requirement, lob)
			}
			if requirement.Restricted.Red {
				newRequirement("red", class, requirement, lob)
			}
		}
		if args.Requirements.General.Hours != 0 || args.Requirements.General.Lobbies != 0 {
			for i := 0; i < 2*format.NumberOfClassesMap[lob.Type]; i++ {
				req := &lobby.Requirement{
					LobbyID: lob.ID,
					Hours:   args.Requirements.General.Hours,
					Lobbies: args.Requirements.General.Lobbies,
					Slot:    i,
				}
				req.Save()
			}

		}
	}

	if *args.Password != "" {
		for i := 0; i < 2*format.NumberOfClassesMap[lob.Type]; i++ {
			req := &lobby.Requirement{
				LobbyID:  lob.ID,
				Slot:     i,
				Password: *args.Password,
			}
			req.Save()
		}
	}

	chat.NewBotMessage(fmt.Sprintf("Lobby created by %s", p.Alias()), int(lob.ID)).Send()

	lobby.BroadcastLobbyList()
	return newResponse(
		struct {
			ID uint `json:"id"`
		}{lob.ID})
}
コード例 #24
0
ファイル: ban.go プロジェクト: TF2Stadium/Helen
func BanPlayer(w http.ResponseWriter, r *http.Request) {
	err := r.ParseForm()
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
	}

	values := r.Form
	steamid := values.Get("steamid")
	reason := values.Get("reason")
	banType := values.Get("type")
	remove := values.Get("remove")
	token := values.Get("xsrf-token")
	if !xsrftoken.Valid(token, config.Constants.CookieStoreSecret, "admin", "POST") {
		http.Error(w, "invalid xsrf token", http.StatusBadRequest)
		return
	}

	ban, ok := map[string]player.BanType{
		"joinLobby":       player.BanJoin,
		"joinMumbleLobby": player.BanJoinMumble,
		"createLobby":     player.BanCreate,
		"chat":            player.BanChat,
		"full":            player.BanFull,
	}[banType]
	if !ok {
		http.Error(w, "Invalid ban type", http.StatusBadRequest)
		return
	}

	player, err := player.GetPlayerBySteamID(steamid)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	if remove == "true" {
		err := player.Unban(ban)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
		} else {
			fmt.Fprintf(w, "Player %s (%s) has been unbanned (%s)", player.Name, player.SteamID, ban.String())
		}
		return
	}

	until, err := time.Parse("2006-01-02 15:04", values.Get("date")+" "+values.Get("time"))
	if err != nil {
		http.Error(w, "invalid time format", http.StatusBadRequest)
		return
	} else if until.Sub(time.Now()) < 0 {
		http.Error(w, "invalid time", http.StatusBadRequest)
		return
	}

	jwt, _ := chelpers.GetToken(r)
	bannedByPlayer := chelpers.GetPlayer(jwt)

	err = player.BanUntil(until, ban, reason, bannedByPlayer.ID)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	fmt.Fprintf(w, "Player %s (%s) has been banned (%s) till %v", player.Name, player.SteamID, ban.String(), until)
}