コード例 #1
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
}
コード例 #2
0
ファイル: twitch.go プロジェクト: TF2Stadium/Helen
func TFTVStreamStatusUpdater() {
	ticker := time.NewTicker(5 * time.Minute)
	u := &url.URL{
		Scheme: "https",
		Host:   "api.twitch.tv",
		Path:   "kraken/streams",
	}
	values := u.Query()
	values.Set("game", "Team Fortress 2")
	values.Set("channel", "teamfortresstv")
	values.Set("stream_type", "live")
	u.RawQuery = values.Encode()

	var reply struct {
		Total   int `json:"_total"`
		Streams []struct {
			Channel struct {
				Status string `json:"status"`
			} `json:"channel"`
		} `json:"streams"`
	}
	var streaming bool

	for {
		req, _ := http.NewRequest("GET", u.String(), nil)
		req.Header.Set("Accept", "application/vnd.twitchtv.v3+json")
		req.Header.Add("Client-ID", config.Constants.TwitchClientID)

		resp, err := helpers.HTTPClient.Do(req)
		if err != nil {
			logrus.Error(err)
			continue
		}

		json.NewDecoder(resp.Body).Decode(&reply)
		if reply.Total != 0 && !streaming {
			str := fmt.Sprintf(`twitch.tv/teamfortresstv is live with "%s"`, reply.Streams[0].Channel.Status)
			message := chat.NewBotMessage(str, 0)
			message.Send()
			streaming = true
		} else {
			streaming = false
		}
		<-ticker.C
	}
}
コード例 #3
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
}
コード例 #4
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})
}