public override async Task PlaytestFifteenMinuteTask(RconService rconService,
                                                             SrcdsLogService srcdsLogService)
        {
            await base.PlaytestFifteenMinuteTask(rconService, srcdsLogService);

            if (_dataService.RSettings.ProgramSettings.Debug)
            {
                _ = _log.LogMessage("TF2 class PlaytestFifteenMinuteTask", false, color: LOG_COLOR);
            }

            var embed = new EmbedBuilder()
                        .WithAuthor($"Setting up test server for {CleanedTitle}")
                        .WithTitle("Workshop Link")
                        .WithUrl(WorkshopLink.ToString())
                        .WithThumbnailUrl(CanUseGallery
                    ? GalleryImages[0]
                    : _dataService.RSettings.General.FallbackTestImageUrl)
                        .WithDescription(
                $"{DatabaseUtil.GetTestServer(ServerLocation).Description}" +
                $"\n{Description}")
                        .WithColor(new Color(51, 100, 173));

            embed.AddField("Connect To",
                           $"`connect {ServerLocation}; password {_dataService.RSettings.General.CasualPassword}`");

            await rconService.RconCommand(ServerLocation,
                                          $"exec {_dataService.RSettings.General.PostgameConfig}");

            await TestingChannel.SendMessageAsync(embed : embed.Build());
        }
        public override async Task PlaytestTwentyMinuteTask(RconService rconService,
                                                            SrcdsLogService srcdsLogService)
        {
            await base.PlaytestTwentyMinuteTask(rconService, srcdsLogService);

            if (_dataService.RSettings.ProgramSettings.Debug)
            {
                _ = _log.LogMessage("CSGO class PlaytestTwentyMinuteTask", false, color: LOG_COLOR);
            }

            var wsId = GeneralUtil.GetWorkshopIdFromFqdn(WorkshopLink.ToString());

            await rconService.RconCommand(ServerLocation, $"host_workshop_map {wsId}");

            if (!IsCasual)
            {
                //Delay before setting password again.
                await Task.Delay(15000);

                await rconService.RconCommand(ServerLocation, $"sv_password {CompPassword}");
            }

            //Run a loop to validate that the level has actually changed.
            _ = Task.Run(async() =>
            {
                var tries = 0;
                //Loop until timeout, or success
                while (tries < 10)
                {
                    //Wait before retry
                    await Task.Delay(30 * 1000);

                    var runningLevel = await rconService.GetRunningLevelAsync(ServerLocation);

                    if (runningLevel != null && runningLevel.Length == 3 && runningLevel[1] == wsId)
                    {
                        break;
                    }

                    tries++;
                    await _log.LogMessage($"Level not set after {tries} attempts. Trying again.", color: LOG_COLOR);
                    await rconService.RconCommand(ServerLocation, $"host_workshop_map {wsId}");
                }

                if (tries <= 10)
                {
                    await _log.LogMessage($"Level changed after {tries} attempts!", color: LOG_COLOR);
                }
                else
                {
                    await _log.LogMessage($"Failed to change level after {tries} attempts!", color: LOG_COLOR);
                }
            });
        }
        public override async Task PlaytestTwentyMinuteTask(RconService rconService,
                                                            SrcdsLogService srcdsLogService)
        {
            await base.PlaytestTwentyMinuteTask(rconService, srcdsLogService);

            if (_dataService.RSettings.ProgramSettings.Debug)
            {
                _ = _log.LogMessage("TF2 class PlaytestTwentyMinuteTask", false, color: LOG_COLOR);
            }

            var wsId = GeneralUtil.GetWorkshopIdFromFqdn(WorkshopLink.ToString());

            await rconService.RconCommand(ServerLocation, $"changelevel workshop/{wsId}");
        }
        public override async Task PlaytestFifteenMinuteTask(RconService rconService,
                                                             SrcdsLogService srcdsLogService)
        {
            await base.PlaytestFifteenMinuteTask(rconService, srcdsLogService);

            if (_dataService.RSettings.ProgramSettings.Debug)
            {
                _ = _log.LogMessage("CSGO class PlaytestFifteenMinuteTask", false, color: LOG_COLOR);
            }

            var gameMode = IsCasual ? "casual" : "comp";

            var embed = new EmbedBuilder()
                        .WithAuthor($"Setting up test server for {CleanedTitle}")
                        .WithTitle("Workshop Link")
                        .WithUrl(WorkshopLink.ToString())
                        .WithThumbnailUrl(CanUseGallery
                    ? GalleryImages[0]
                    : _dataService.RSettings.General.FallbackTestImageUrl)
                        .WithDescription(
                $"{DatabaseUtil.GetTestServer(ServerLocation).Description}" +
                $"\n{Description}")
                        .WithColor(new Color(51, 100, 173));

            //Set password as needed, again just in case RCON wasn't listening / server wasn't ready.
            if (IsCasual)
            {
                await rconService.RconCommand(ServerLocation,
                                              $"sv_password {_dataService.RSettings.General.CasualPassword}");

                embed.AddField("Connect To",
                               $"`connect {ServerLocation}; password {_dataService.RSettings.General.CasualPassword}`");
            }
            else
            {
                await rconService.RconCommand(ServerLocation,
                                              $"sv_password {CompPassword}");
            }

            //Delay to make sure level has actually changed
            await Task.Delay(10000);

            await rconService.RconCommand(ServerLocation,
                                          $"exec {_dataService.RSettings.General.PostgameConfig}; bot_stop 1");

            await rconService.RconCommand(ServerLocation, "say No damage activated!; script_execute nodamage");

            await TestingChannel.SendMessageAsync(embed : embed.Build());
        }
        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());
            }
        }