internal async void PlaytestPostTasks(PlaytestCommandInfo playtestCommandInfo)
        {
            await _data.RconCommand(playtestCommandInfo.ServerAddress, $"host_workshop_map {playtestCommandInfo.WorkshopId}");

            await Task.Delay(15000); //Wait for map to change

            await _data.RconCommand(playtestCommandInfo.ServerAddress,
                                    $"sv_cheats 1; bot_stop 1;sv_voiceenable 0;exec {_data.RSettings.General.PostgameConfig};" +
                                    $"say Please join the level testing voice channel for feedback!;" +
                                    $"say Please join the level testing voice channel for feedback!;" +
                                    $"say Please join the level testing voice channel for feedback!;" +
                                    $"say Please join the level testing voice channel for feedback!;" +
                                    $"say Please join the level testing voice channel for feedback!");

            DownloadHandler.DownloadPlaytestDemo(playtestCommandInfo);

            const string demoUrl = "http://demos.tophattwaffle.com";

            var embed = new EmbedBuilder()
                        .WithAuthor($"Download playtest demo for {playtestCommandInfo.Title}", _data.Guild.IconUrl, demoUrl)
                        .WithThumbnailUrl(playtestCommandInfo.ThumbNailImage)
                        .WithColor(new Color(243, 128, 72))
                        .WithDescription($"[Download Demo Here]({demoUrl}) | [Map Images]({playtestCommandInfo.ImageAlbum}) | [Playtesting Information](https://www.tophattwaffle.com/playtesting/)");

            await _data.TestingChannel.SendMessageAsync(playtestCommandInfo.CreatorMentions, embed : embed.Build());
        }
        public static PlaytestCommandInfo GetPlaytestCommandInfo()
        {
            if (_data.RSettings.ProgramSettings.Debug)
            {
                _ = _log.LogMessage("Getting old playtest command information...", false, color: LOG_COLOR);
            }

            PlaytestCommandInfo commandInfo = null;

            try
            {
                using (var db = new LiteDatabase(DBPATH))
                {
                    //Grab our collection
                    var collection = db.GetCollection <PlaytestCommandInfo>(COLLECTION_PLAYTEST_COMMAND);

                    commandInfo = collection.FindOne(Query.EQ("_id", 1));
                }
            }
            catch (Exception e)
            {
                //TODO: Don't actually know what exceptions can happen here, catch all for now.
                _ = _log.LogMessage("Something happened getting announcement message\n" +
                                    $"{e}", false, color: ConsoleColor.Red);
                return(commandInfo);
            }

            return(commandInfo);
        }
        public static bool StorePlaytestCommandInfo(PlaytestCommandInfo playtestCommandInfo)
        {
            try
            {
                using (var db = new LiteDatabase(DBPATH))
                {
                    //Grab our collection
                    var collection = db.GetCollection <PlaytestCommandInfo>(COLLECTION_PLAYTEST_COMMAND);

                    var commandInfo = collection.FindOne(Query.EQ("_id", 1));

                    //If not null, we need to remove the old record first.
                    if (commandInfo != null)
                    {
                        if (_data.RSettings.ProgramSettings.Debug)
                        {
                            _ = _log.LogMessage("Old playtest command info record found, deleting", false, color: LOG_COLOR);
                        }

                        collection.Delete(1);
                    }

                    //Insert new entry with ID of 1, and our values.
                    collection.Insert(playtestCommandInfo);
                }
            }
            catch (Exception e)
            {
                //TODO: Don't actually know what exceptions can happen here, catch all for now.
                _ = _log.LogMessage("Something happened storing announcement message\n" +
                                    $"{e}", false, color: ConsoleColor.Red);
                return(false);
            }
            return(true);
        }
        public virtual async Task PlaytestCommandPre(bool replyInContext,
                                                     SrcdsLogService srcdsLogService, RconService rconService)
        {
            if (_dataService.RSettings.ProgramSettings.Debug)
            {
                _ = _log.LogMessage("Base class PlaytestCommandPre", false, color: LOG_COLOR);
            }

            PlaytestCommandRunning = true;

            _dataService.SetStartAlert(false);

            await _log.LogMessage("Running Playtest Pre Tasks!", color : LOG_COLOR);

            //Store test information for later use. Will be written to the DB.
            var    gameMode = IsCasual ? "casual" : "comp";
            string mentions = null;

            Creators.ForEach(x => mentions += $"{x.Mention} ");
            PlaytestCommandInfo             = new PlaytestCommandInfo
            {
                Id       = 1, //Only storing 1 of these in the DB at a time, so hard code to 1.
                Mode     = gameMode,
                DemoName = $"{StartDateTime:MM_dd_yyyy}" +
                           $"_{CleanedTitle.Substring(0, CleanedTitle.IndexOf(' ')).Trim()}" +
                           $"_{gameMode}",
                WorkshopId      = GeneralUtil.GetWorkshopIdFromFqdn(WorkshopLink.ToString()),
                ServerAddress   = ServerLocation,
                Title           = CleanedTitle,
                ThumbNailImage  = CanUseGallery ? GalleryImages[0] : _dataService.RSettings.General.FallbackTestImageUrl,
                ImageAlbum      = ImageGallery.ToString(),
                CreatorMentions = mentions,
                StartDateTime   = StartDateTime.GetValueOrDefault(),
                Game            = Game.ToString()
            };


            var fbf = srcdsLogService.GetFeedbackFile(server);

            //If somehow the session does not exist...
            if (fbf == null)
            {
                srcdsLogService.CreateFeedbackFile(server, GetFeedbackFileName());
                fbf = srcdsLogService.GetFeedbackFile(server);
            }

            await fbf.LogFeedback($"Playtest starting feedback started at: {DateTime.Now} CT");

            //Write to the DB so we can restore this info next boot
            DatabaseUtil.StorePlaytestCommandInfo(PlaytestCommandInfo);

            //Figure out where to send the no context message

            //No context to send these messages to - default them
            if (!replyInContext)
            {
                await TestingChannel.SendMessageAsync(embed : new EmbedBuilder()
                                                      .WithAuthor($"Pre-start playtest of {CleanedTitle}")
                                                      .WithColor(new Color(55, 55, 165))
                                                      .WithDescription($"\nOn **{PlaytestCommandInfo.ServerAddress}**" +
                                                                       $"\nWith config of **{PlaytestCommandInfo.Mode}**" +
                                                                       $"\nWorkshop ID **{PlaytestCommandInfo.WorkshopId}**").Build());
            }
        }
Ejemplo n.º 5
0
        public static async Task <string> DownloadPlaytestDemo(PlaytestCommandInfo playtestCommandInfo)
        {
            var server = DatabaseUtil.GetTestServer(playtestCommandInfo.ServerAddress);

            if (server == null)
            {
                return(null);
            }

            var dateInsert = "";

            //Arrived from a public test, where a proper start time did not exist.
            if (playtestCommandInfo.StartDateTime == new DateTime())
            {
                dateInsert = $"{DateTime.Now:MM_dd_yyyy}_";
                playtestCommandInfo.StartDateTime = DateTime.Now;
            }

            var localPath =
                $"{_dataService.RSettings.ProgramSettings.PlaytestDemoPath}\\{playtestCommandInfo.StartDateTime:yyyy}" +
                $"\\{playtestCommandInfo.StartDateTime:MM} - {playtestCommandInfo.StartDateTime:MMMM}\\{dateInsert}{playtestCommandInfo.DemoName}";

            string remoteBspPath = null;

            if (playtestCommandInfo.Game.Equals("tf2", StringComparison.OrdinalIgnoreCase))
            {
                //TF2 is ass and stores workshop maps in a totally different folder
                remoteBspPath = $"/steamapps/workshop/content/440/{playtestCommandInfo.WorkshopId}";
            }
            else if (playtestCommandInfo.Game.Equals("csgo", StringComparison.OrdinalIgnoreCase))
            {
                remoteBspPath = $"{server.FtpPath}/maps/workshop/{playtestCommandInfo.WorkshopId}";
            }
            else
            {
                await _log.LogMessage("Game for playtest is invalid. This should never happen.", true, true, true);

                return(null);
            }

            switch (server.FtpType.ToLower())
            {
            case "ftps":
            case "ftp":

                var ftpClient = await ConnectFtpClient(server);

                if (ftpClient == null)
                {
                    return(null);
                }

                try
                {
                    //Download Demo
                    ftpClient.DownloadFile($"{localPath}\\{playtestCommandInfo.DemoName}.dem",
                                           GetFile(ftpClient, server.FtpPath, playtestCommandInfo.DemoName));

                    //Download BSP
                    var bspFile = GetFile(ftpClient, remoteBspPath, ".bsp");
                    ftpClient.DownloadFile($"{localPath}\\{Path.GetFileName(bspFile)}", bspFile);
                }
                catch (Exception e)
                {
                    await _log.LogMessage(
                        $"Failed to download file from playtest server. {server.GetFtpAddress()}\n{e.Message}",
                        color : LOG_COLOR);
                }

                ftpClient.Disconnect();
                ftpClient.Dispose();

                await _log.LogMessage(
                    $"```Listing of test download directory:\n{string.Join("\n", Directory.GetFiles(localPath))}```",
                    color : LOG_COLOR);

                break;

            case "sftp":
                var client = await ConnectSftpClient(server);

                if (client == null)
                {
                    return(null);
                }

                Directory.CreateDirectory(localPath);

                try
                {
                    var remoteDemoFile = GetFile(client, server.FtpPath, playtestCommandInfo.DemoName);
                    using (Stream stream = File.OpenWrite($"{localPath}\\{remoteDemoFile.Name}"))
                    {
                        client.DownloadFile(remoteDemoFile.FullName, stream);
                    }

                    var remoteBspFile = GetFile(client, remoteBspPath, ".bsp");
                    using (Stream stream = File.OpenWrite($"{localPath}\\{remoteBspFile.Name}"))
                    {
                        client.DownloadFile(remoteBspFile.FullName, stream);
                    }
                }
                catch (Exception e)
                {
                    await _log.LogMessage(
                        $"Failed to download file from playtest server. {server.GetFtpAddress()}\n{e.Message}",
                        color : LOG_COLOR);
                }

                client.Disconnect();
                client.Dispose();

                await _log.LogMessage(
                    $"```Listing of test download directory:\n{string.Join("\n", Directory.GetFiles(localPath))}```",
                    color : LOG_COLOR);

                break;

            default:
                await _log.LogMessage(
                    $"The FTP type on the server is incorrectly set. {server.GetFtpAddress()} is using {server.FtpType}",
                    alert : true, color : LOG_COLOR);

                break;
            }

            //Return the path to the demo.
            return(Directory.GetFiles(localPath)
                   .FirstOrDefault(x => x.EndsWith(".dem", StringComparison.OrdinalIgnoreCase)));
        }
        public static async void DownloadPlaytestDemo(PlaytestCommandInfo playtestCommandInfo)
        {
            var server = DatabaseHandler.GetTestServer(playtestCommandInfo.ServerAddress);

            if (server == null)
            {
                return;
            }

            string localPath = $"{_data.RSettings.ProgramSettings.PlaytestDemoPath}\\{playtestCommandInfo.StartDateTime:yyyy}" +
                               $"\\{playtestCommandInfo.StartDateTime:MM} - {playtestCommandInfo.StartDateTime:MMMM}\\{playtestCommandInfo.DemoName}";

            switch (server.FtpType.ToLower())
            {
            case "ftps":
            case "ftp":
                using (var client = new FtpClient(server.Address, server.FtpUser, server.FtpPassword))
                {
                    if (server.FtpType == "ftps")
                    {
                        client.EncryptionMode       = FtpEncryptionMode.Explicit;
                        client.SslProtocols         = SslProtocols.Tls;
                        client.ValidateCertificate += (control, e) => { e.Accept = true; };
                    }

                    try
                    {
                        client.Connect();
                    }
                    catch (Exception e)
                    {
                        await _log.LogMessage($"Failed to connect to FTP server. {server.Address}\n {e.Message}", alert : true);

                        return;
                    }

                    try
                    {
                        //Download Demo
                        client.DownloadFile($"{localPath}\\{playtestCommandInfo.DemoName}.dem",
                                            GetFile(client, server.FtpPath, playtestCommandInfo.DemoName));

                        //Download BSP
                        string bspFile = GetFile(client,
                                                 $"{server.FtpPath}/maps/workshop/{playtestCommandInfo.WorkshopId}", ".bsp");
                        client.DownloadFile($"{localPath}\\{Path.GetFileName(bspFile)}", bspFile);
                    }
                    catch (Exception e)
                    {
                        await _log.LogMessage($"Failed to download file from playtest server. {server.Address}\n{e.Message}");
                    }

                    client.Disconnect();

                    await _log.LogMessage($"```Listing of test download directory:\n{string.Join("\n", Directory.GetFiles(localPath))}```");
                }

                break;

            case "sftp":
                using (var client = new SftpClient(server.Address, server.FtpUser, server.FtpPassword))
                {
                    try
                    {
                        client.Connect();
                    }
                    catch (Exception e)
                    {
                        await _log.LogMessage($"Failed to connect to SFTP server. {server.Address}\n {e.Message}", alert : true);

                        return;
                    }

                    Directory.CreateDirectory(localPath);

                    try
                    {
                        var remoteDemoFile = GetFile(client, server.FtpPath, playtestCommandInfo.DemoName);
                        using (Stream stream = File.OpenWrite($"{localPath}\\{remoteDemoFile.Name}"))
                        {
                            client.DownloadFile(remoteDemoFile.FullName, stream);
                        }

                        var remoteBspFile = GetFile(client, $"{server.FtpPath}/maps/workshop/{playtestCommandInfo.WorkshopId}", ".bsp");
                        using (Stream stream = File.OpenWrite($"{localPath}\\{remoteBspFile.Name}"))
                        {
                            client.DownloadFile(remoteBspFile.FullName, stream);
                        }
                    }
                    catch (Exception e)
                    {
                        await _log.LogMessage($"Failed to download file from playtest server. {server.Address}\n{e.Message}");
                    }

                    client.Disconnect();

                    await _log.LogMessage($"```Listing of test download directory:\n{string.Join("\n", Directory.GetFiles(localPath))}```");
                }

                break;

            default:
                await _log.LogMessage($"The FTP type on the server is incorrectly set. {server.Address} is using {server.FtpType}", alert : true);

                break;
            }
        }
        public async Task PlaytestAsync(string command)
        {
            //Reload the last used playtest if the current event is null
            if (_playtestCommandInfo == null)
            {
                _playtestCommandInfo = DatabaseHandler.GetPlaytestCommandInfo();
            }


            //Make sure we have a valid event, if not, abort.
            if (!_calendar.GetTestEventNoUpdate().IsValid)
            {
                await ReplyAsync("This command requires a valid playtest event.");

                return;
            }

            //Setup a few variables we'll need later
            string config = _calendar.GetTestEventNoUpdate().IsCasual
                ? _data.RSettings.General.CasualConfig
                : _data.RSettings.General.CompConfig;

            switch (command.ToLower())
            {
            case "prestart":
            case "pre":

                //Store test information for later use. Will be written to the DB.
                string gameMode = _calendar.GetTestEventNoUpdate().IsCasual ? "casual" : "comp";
                string mentions = null;
                _calendar.GetTestEventNoUpdate().Creators.ForEach(x => mentions += $"{x.Mention} ");
                _playtestCommandInfo = new PlaytestCommandInfo
                {
                    Id       = 1, //Only storing 1 of these in the DB at a time, so hard code to 1.
                    Mode     = gameMode,
                    DemoName = $"{_calendar.GetTestEventNoUpdate().StartDateTime:MM_dd_yyyy}" +
                               $"_{_calendar.GetTestEventNoUpdate().Title.Substring(0, _calendar.GetTestEventNoUpdate().Title.IndexOf(' '))}" +
                               $"_{gameMode}",
                    WorkshopId      = _data.GetWorkshopIdFromFqdn(_calendar.GetTestEventNoUpdate().WorkshopLink.ToString()),
                    ServerAddress   = _calendar.GetTestEventNoUpdate().ServerLocation,
                    Title           = _calendar.GetTestEventNoUpdate().Title,
                    ThumbNailImage  = _calendar.GetTestEventNoUpdate().CanUseGallery ? _calendar.GetTestEventNoUpdate().GalleryImages[0] : _data.RSettings.General.FallbackTestImageUrl,
                    ImageAlbum      = _calendar.GetTestEventNoUpdate().ImageGallery.ToString(),
                    CreatorMentions = mentions,
                    StartDateTime   = _calendar.GetTestEventNoUpdate().StartDateTime.Value
                };

                //Write to the DB so we can restore this info next boot
                DatabaseHandler.StorePlaytestCommandInfo(_playtestCommandInfo);

                await ReplyAsync($"Pre-start playtest of **{_playtestCommandInfo.Title}**" +
                                 $"\nOn **{_playtestCommandInfo.ServerAddress}**" +
                                 $"\nWith config of **{config}**" +
                                 $"\nWorkshop ID **{_playtestCommandInfo.WorkshopId}**");

                await _data.RconCommand(_playtestCommandInfo.ServerAddress, $"exec {config}");

                await Task.Delay(1000);

                await _data.RconCommand(_playtestCommandInfo.ServerAddress, $"host_workshop_map {_playtestCommandInfo.WorkshopId}");

                break;

            case "start":
                await ReplyAsync($"Start playtest of **{_playtestCommandInfo.Title}**" +
                                 $"\nOn **{_playtestCommandInfo.ServerAddress}**" +
                                 $"\nWith config of **{config}**" +
                                 $"\nWorkshop ID **{_playtestCommandInfo.WorkshopId}**" +
                                 $"\nDemo Name **{_playtestCommandInfo.DemoName}**");

                await _data.RconCommand(_playtestCommandInfo.ServerAddress, $"exec {config}");

                await Task.Delay(3000);

                await _data.RconCommand(_playtestCommandInfo.ServerAddress, $"tv_record {_playtestCommandInfo.DemoName}; say Recording {_playtestCommandInfo.DemoName}");

                await Task.Delay(1000);

                await _data.RconCommand(_playtestCommandInfo.ServerAddress, $"say Playtest of {_playtestCommandInfo.Title} is live! Be respectful and GLHF!");

                await Task.Delay(1000);

                await _data.RconCommand(_playtestCommandInfo.ServerAddress, $"say Playtest of {_playtestCommandInfo.Title} is live! Be respectful and GLHF!");

                await Task.Delay(1000);

                await _data.RconCommand(_playtestCommandInfo.ServerAddress, $"say Playtest of {_playtestCommandInfo.Title} is live! Be respectful and GLHF!");

                break;

            case "post":
                //This is fired and forgotten. All error handling will be done in the method itself.
                await ReplyAsync($"Post playtest of **{_playtestCommandInfo.Title}**" +
                                 $"\nOn **{_playtestCommandInfo.ServerAddress}**" +
                                 $"\nWorkshop ID **{_playtestCommandInfo.WorkshopId}**" +
                                 $"\nDemo Name **{_playtestCommandInfo.DemoName}**");

                PlaytestPostTasks(_playtestCommandInfo);
                break;

            case "pause":
            case "p":
                await _data.RconCommand(_playtestCommandInfo.ServerAddress,
                                        @"mp_pause_match;say Pausing Match!;say Pausing Match!;say Pausing Match!;say Pausing Match!");
                await ReplyAsync($"```Pausing playtest on {_playtestCommandInfo.ServerAddress}!```");

                break;

            case "unpause":
            case "u":
                await _data.RconCommand(_playtestCommandInfo.ServerAddress,
                                        @"mp_unpause_match;say Unpausing Match!;say Unpausing Match!;say Unpausing Match!;say Unpausing Match!");
                await ReplyAsync($"```Unpausing playtest on {_playtestCommandInfo.ServerAddress}!```");

                break;

            case "scramble":
            case "s":
                await _data.RconCommand(_playtestCommandInfo.ServerAddress, "mp_scrambleteams 1" +
                                        ";say Scrambling Teams!;say Scrambling Teams!;say Scrambling Teams!;say Scrambling Teams!");
                await ReplyAsync($"```Scrambling teams on {_playtestCommandInfo.ServerAddress}!```");

                break;

            case "kick":
            case "k":
                var kick = new KickUserRcon(Context, _interactive, _data, _log);
                await kick.KickPlaytestUser(_playtestCommandInfo.ServerAddress);

                break;

            default:
                await ReplyAsync("Invalid action, please consult the help document for this command.");

                break;
            }
        }