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