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 }
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 } }
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 }
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}) }