private void LoadAccounts()
 {
     accounts = IoHelperCore.ReadAccounts();
     foreach (var acc in accounts)
     {
         var access = acc.Access.GetCurrentAccess();
         InsertAccIntoListView(acc.AccInfo.Nickname, acc.AccInfo.ServerUrl, access.Proxy, access.ProxyPort);
     }
 }
        private void InsertAccIntoListView(string nick, string url, string proxy, int port)
        {
            var item = new ListViewItem();

            item.SubItems[0].Text = $"{nick} ({IoHelperCore.UrlRemoveHttp(url)})";     //account
            item.SubItems.Add("❌");                                                    //proxy error
            item.SubItems.Add(string.IsNullOrEmpty(proxy) ? "/" : proxy + ":" + port); //proxy
            accListView.Items.Add(item);
        }
Exemple #3
0
        private void InsertAccIntoListView(string nick, string url, string proxy, int port, bool selected = false)
        {
            var item = new ListViewItem();

            item.SubItems[0].Text      = $"{nick} ({IoHelperCore.UrlRemoveHttp(url)})"; //account
            item.SubItems[0].ForeColor = Color.FromName(selected ? "DodgerBlue" : "Black");
            //item.SubItems.Add("❌"); //proxy error
            item.SubItems.Add(string.IsNullOrEmpty(proxy) ? "/" : proxy + ":" + port); //proxy
            accListView.Items.Add(item);
        }
Exemple #4
0
 private void button4_Click(object sender, EventArgs e) // Logout all accounts
 {
     new Thread(() =>
     {
         foreach (var acc in accounts)
         {
             IoHelperCore.Logout(acc);
         }
     }).Start();
     generalUc1.UpdateBotRunning("false");
 }
Exemple #5
0
        private void SetupChromeDriver(Access access, string username, string server)
        {
            ChromeOptions options = new ChromeOptions();

            if (!string.IsNullOrEmpty(access.Proxy))
            {
                options.Proxy = new Proxy()
                {
                    Kind         = ProxyKind.Manual,
                    IsAutoDetect = false,
                    SslProxy     = $"<{access.Proxy}:{access.ProxyPort}>"
                };
                options.AddArgument("ignore-certificate-errors");
            }
            if (!string.IsNullOrEmpty(access.UserAgent))
            {
                options.AddArgument("--user-agent=" + access.UserAgent);
            }

            // Make browser headless to preserve memory resources
            if (acc.Settings.HeadlessMode)
            {
                options.AddArguments("headless");
            }

            // Do not download images in order to preserve memory resources
            if (acc.Settings.DisableImages)
            {
                options.AddArguments("--blink-settings=imagesEnabled=false");
            }

            // Add browser caching
            var accFolder = IoHelperCore.GetCacheFolder(username, server, access.Proxy);
            var dir       = Path.Combine(IoHelperCore.CachePath, accFolder);

            Directory.CreateDirectory(dir);
            options.AddArguments("user-data-dir=" + dir);

            // Disable message "Chrome is being controlled by automated test software"
            //options.AddArgument("--excludeSwitches=enable-automation"); // Doesn't work anymore

            // Hide command prompt
            var service = ChromeDriverService.CreateDefaultService();

            service.HideCommandPromptWindow = true;
            try
            {
                this.Driver = new ChromeDriver(service, options);
            }
            catch (Exception e)
            {
                // TODO: log exception
            }
        }
Exemple #6
0
        private void LoadAccounts()
        {
            // For migration purposes only! Remove after few versions
            if (IoHelperCore.AccountsTxtExists() && !IoHelperCore.SQLiteExists())
            {
                DbRepository.SyncAccountsTxt();
                File.Delete(IoHelperCore.AccountsPath);
            }

            accounts = DbRepository.GetAccounts();
            RefreshAccView();
        }
        private void button3_Click(object sender, EventArgs e) // Remove an account
        {
            var acc = GetSelectedAcc();

            if (acc == null)
            {
                return;
            }

            IoHelperCore.RemoveCache(acc);
            accounts.Remove(acc);
            accListView.Items.RemoveAt(accSelected);
        }
Exemple #8
0
        private void button24_Click(object sender, EventArgs e) //import build tasks button
        {
            var acc  = GetSelectedAcc();
            var vill = GetSelectedVillage();

            string location = IoHelperForms.PromptUserForBuidTasksLocation();

            if (location == null)
            {
                return;
            }
            IoHelperCore.AddBuildTasksFromFile(acc, vill, location);
            UpdateUc();
        }
Exemple #9
0
        public void AddNewAccess(AccessRaw raw)
        {
            var access = new Access()
            {
                Password      = raw.Password,
                Proxy         = raw.Proxy,
                ProxyPort     = raw.ProxyPort,
                ProxyUsername = raw.ProxyUsername,
                ProxyPassword = raw.ProxyPassword,
                IsSittering   = false,
                UserAgent     = IoHelperCore.GetUseragent(),
                LastUsed      = DateTime.MinValue
            };

            AllAccess.Add(access);
        }
Exemple #10
0
        private void button5_Click(object sender, EventArgs e) //all villages select from file
        {
            var acc = GetSelectedAcc();

            string location = IoHelperForms.PromptUserForBuidTasksLocation();

            if (location == null)
            {
                return;
            }

            foreach (var vill in acc.Villages)
            {
                IoHelperCore.AddBuildTasksFromFile(acc, vill, location);
            }
        }
Exemple #11
0
        public static void SyncAccountsTxt()
        {
            using (var context = new TbsContext())
            {
                var accs   = IoHelperCore.ReadAccounts();
                var dbAccs = new List <DbAccount>(accs.Count);

                foreach (var acc in accs)
                {
                    dbAccs.Add(ConvertAcc(acc));
                }

                context.DbAccount.AddRange(dbAccs);
                context.SaveChanges();
            }
        }
Exemple #12
0
        private void button2_Click(object sender, EventArgs e) //login button
        {
            var acc = GetSelectedAcc();

            if (0 < acc.Access.AllAccess.Count)
            {
                new Thread(() => _ = IoHelperCore.LoginAccount(acc)).Start();
                generalUc1.UpdateBotRunning("true");
                return;
            }

            // Alert user that account has no access defined
            string            message = "Account you are trying to login has no access' defined. Please edit the account.";
            string            caption = "Error in account";
            MessageBoxButtons buttons = MessageBoxButtons.OK;
            DialogResult      result  = MessageBox.Show(message, caption, buttons);
        }
Exemple #13
0
        private void button6_Click(object sender, EventArgs e) // Login all accounts
        {
            new Thread(async() =>
            {
                var ran = new Random();
                foreach (var acc in accounts)
                {
                    // If account is already running, don't login
                    if (acc.TaskTimer?.IsBotRunning() ?? false)
                    {
                        continue;
                    }

                    _ = IoHelperCore.LoginAccount(acc);
                    await Task.Delay(ran.Next(500, 5000));
                }
            }).Start();
            generalUc1.UpdateBotRunning("true");
        }
Exemple #14
0
        /// <summary>

        /// Creates chrome extension (.crx) for proxy authentication
        /// </summary>
        /// <param name="username">Travian username</param>
        /// <param name="server">Travian server</param>
        /// <param name="access">Access</param>
        /// <returns>Path of the chrome extension</returns>
        public static string CreateExtension(string username, string server, Access access)
        {
            var cacheDir = IoHelperCore.GetCacheDir(username, server, access);
            var dir      = Path.Combine(cacheDir, "DisableWebRTCLeak");

            Directory.CreateDirectory(dir);

            CreateFile(Path.Combine(dir, "manifest.json"), manifestJson);
            CreateFile(Path.Combine(dir, "common.js"), backgroundJs);

            var zipPath = Path.Combine(cacheDir, "DisableWebRTCLeak.crx");

            if (File.Exists(zipPath))
            {
                File.Delete(zipPath);
            }
            ZipFile.CreateFromDirectory(dir, zipPath);

            return(zipPath);
        }
        /// <summary>
        /// Creates chrome extension (.crx) for proxy authentication
        /// </summary>
        /// <param name="username">Travian username</param>
        /// <param name="server">Travian server</param>
        /// <param name="access">Access</param>
        /// <returns>Path of the chrome extension</returns>
        public static string CreateExtension(string username, string server, Access access)
        {
            var cacheDir = IoHelperCore.GetCacheDir(username, server, access);
            var dir      = Path.Combine(cacheDir, "ProxyAuthExtension");

            Directory.CreateDirectory(dir);

            CreateFile(Path.Combine(dir, "manifest.json"), manifestJson);
            CreateFile(Path.Combine(dir, "background.js"), GenerateBackgroundJs(access));

            var zipPath = Path.Combine(cacheDir, "ProxyAuthExtension.crx");

            if (File.Exists(zipPath))
            {
                File.Delete(zipPath);
            }
            ZipFile.CreateFromDirectory(dir, zipPath);

            return(zipPath);
        }
Exemple #16
0
        public override async Task <TaskRes> Execute(Account acc)
        {
            TaskExecutor.RemoveSameTasksForVillage(acc, Vill, typeof(UpdateDorf1), this);
            TaskExecutor.RemoveSameTasksForVillage(acc, Vill, typeof(UpdateDorf2), this);

            await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/dorf1.php"); // Update dorf1

            await Task.Delay(AccountHelper.Delay());

            await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/dorf2.php"); // Update dorf2

            // On new village import the building tasks
            if (ImportTasks && !string.IsNullOrEmpty(acc.NewVillages.BuildingTasksLocationNewVillage))
            {
                IoHelperCore.AddBuildTasksFromFile(acc, Vill, acc.NewVillages.BuildingTasksLocationNewVillage);
            }

            await UpdateTroopsResearchedAndLevels(acc);

            await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/dorf2.php");

            await Task.Delay(AccountHelper.Delay());

            await UpdateTroopsTraining(acc);

            var firstTroop = TroopsHelper.TribeFirstTroop(acc.AccInfo.Tribe);

            Vill.Troops.TroopToTrain = firstTroop;
            Vill.Troops.Researched.Add(firstTroop);

            if (await VillageHelper.EnterBuilding(acc, Vill, Classificator.BuildingEnum.TownHall))
            {
                // Village has town hall, parse celebration duration
                Vill.Expansion.CelebrationEnd = TimeParser.GetCelebrationTime(acc.Wb.Html);
            }

            return(TaskRes.Executed);
        }
        private void button1_Click_1(object sender, EventArgs e)
        {
            var acc = GetSelectedAcc();

            string location = IoHelperForms.PromptUserForBuidTasksLocation();

            if (location == null)
            {
                return;
            }

            for (int i = 0; i < tableModelMain.Rows.Count; i++)
            {
                if (tableModelMain.Rows[i].SelectedItems.Count() > 0)
                {
                    var cells = tableModelMain.Rows[i].Cells;
                    //Village id
                    var id   = Int32.Parse(cells[0].Text);
                    var vill = acc.Villages.First(x => x.Id == id);

                    IoHelperCore.AddBuildTasksFromFile(acc, vill, location);
                }
            }
        }
Exemple #18
0
        public override async Task <TaskRes> Execute(Account acc)
        {
            var wb = acc.Wb.Driver;
            await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?tt=2&id=39");

            var wavesReady = new List <WaveReadyModel>();

            // Get request time for getting more accurate attacks
            Ping      ping      = new Ping();
            PingReply reply     = ping.Send(IoHelperCore.UrlRemoveHttp(acc.AccInfo.ServerUrl));
            var       reqTripMs = (int)(reply.RoundtripTime / 2);

            Random rnd = new Random();

            // Prepare the waves
            for (int i = 0; i < SendWaveModels.Count; i++)
            {
                await Task.Delay(rnd.Next(800, 1000));

                acc.Wb.Log($"Preparing {i + 1}. wave...");

                // TODO: eliminate the need of this first request, will send a second on each wave
                var htmlDoc1 = HttpHelper.SendGetReq(acc, "/build.php?tt=2&id=39");

                var build = htmlDoc1.GetElementbyId("build");

                var req = new RestRequest
                {
                    Resource = "/build.php?tt=2&id=39",
                    Method   = Method.POST,
                };

                req.AddParameter("dname", "");
                req.AddParameter("x", SendWaveModels[i].TargetCoordinates.x.ToString());
                req.AddParameter("y", SendWaveModels[i].TargetCoordinates.y.ToString());
                req.AddParameter("c", ((int)SendWaveModels[i].MovementType).ToString());
                req.AddParameter("s1", "ok");

                foreach (var hidden in hiddenFields)
                {
                    var value = build.Descendants("input").FirstOrDefault(x => x.GetAttributeValue("name", "") == hidden);
                    if (value == null)
                    {
                        continue;
                    }
                    req.AddParameter(hidden, value.GetAttributeValue("value", ""));
                }

                // Get available troops
                int[] troopsAtHome = TroopsMovementParser.GetTroopsInRallyPoint(htmlDoc1);

                // Send fake attack dirty hack
                if (SendWaveModels[i].FakeAttack)
                {
                    for (int j = 0; j < 10; j++)
                    {
                        if (troopsAtHome[j] > 19)
                        {
                            SendWaveModels[i].Troops[j] = 19;
                            troopsAtHome[j]            -= 19;
                            break;
                        }
                    }
                }

                for (int j = 0; j < SendWaveModels[i].Troops.Length; j++)
                {
                    // If negative value, send all available units
                    if (SendWaveModels[i].Troops[j] < 0)
                    {
                        SendWaveModels[i].Troops[j] = troopsAtHome[j];
                        troopsAtHome[j]             = 0;
                    }

                    switch (acc.AccInfo.ServerVersion)
                    {
                    case Classificator.ServerVersionEnum.T4_4:
                        req.AddParameter($"t{j + 1}", TroopCount(SendWaveModels[i].Troops[j]));
                        break;

                    case Classificator.ServerVersionEnum.T4_5:
                        req.AddParameter($"troops[0][t{j + 1}]", TroopCount(SendWaveModels[i].Troops[j]));
                        break;
                    }
                }
                await Task.Delay(rnd.Next(800, 1000));

                var ret = HttpHelper.SendPostReq(acc, req);

                var htmlDoc2 = new HtmlAgilityPack.HtmlDocument();
                htmlDoc2.LoadHtml(ret);

                // Get time it takes for troops to the target, for later usage
                var timespan = TroopsMovementParser.GetTimeOfMovement(htmlDoc2);
                lastArriveAt = TroopsMovementParser.GetArrivalTime(htmlDoc2);

                if (timeDifference == TimeSpan.Zero)
                {
                    var serverTime = TimeParser.GetServerTime(htmlDoc2);
                    timeDifference = DateTime.Now - serverTime;
                    // Negate seconds and milliseconds in time difference.
                    var negateMillis = timeDifference.Milliseconds;
                    negateMillis  += timeDifference.Seconds * 1000;
                    timeDifference = timeDifference.Subtract(new TimeSpan(0, 0, 0, 0, negateMillis));

                    var executeTime = CorrectExecuteTime(timespan);
                    if (DateTime.Now.AddMinutes(1) < executeTime)
                    {
                        // Restart this task at the correct time

                        acc.Wb.Log($"Bot will send waves in {TimeHelper.InSeconds(executeTime)} seconds");
                        this.NextExecute = executeTime;
                        return(TaskRes.Executed);
                    }
                }

                //var ajaxToken = await HttpHelper.GetAjaxToken(wb);
                var req2 = new RestRequest
                {
                    Resource = "/build.php?tt=2&id=39",
                    Method   = Method.POST,
                };

                req2.AddParameter("s1", "ok");

                // Copy all hidden names and values
                var build2   = htmlDoc2.GetElementbyId("build");
                var hiddens2 = build2.Descendants("input").Where(x => x.GetAttributeValue("type", "") == "hidden");
                foreach (var hidden2 in hiddens2)
                {
                    var val  = hidden2.GetAttributeValue("value", "");
                    var name = hidden2.GetAttributeValue("name", "");
                    req2.AddParameter(name, val);
                }

                // Add catapult targets
                string cataCount = "0";
                switch (acc.AccInfo.ServerVersion)
                {
                case Classificator.ServerVersionEnum.T4_4:
                    cataCount = req2.Parameters.FirstOrDefault(x => x.Name == "t8").Value.ToString();
                    break;

                case Classificator.ServerVersionEnum.T4_5:
                    cataCount = req2.Parameters.FirstOrDefault(x => x.Name == "troops[0][t8]").Value.ToString();
                    // If T4.5, we need to get value "a" as well - From Confirm button
                    var    button = htmlDoc2.GetElementbyId("btn_ok");
                    string a      = button.GetAttributeValue("value", "");
                    req2.AddParameter("a", a);
                    break;
                }

                if (int.Parse(cataCount) > 0)
                {
                    req2.AddParameter("ctar1", "99"); // 99 = Random, 1 = woodcuter, 2 = claypit..
                    req2.AddParameter("ctar2", "99"); // 99 = Random
                }

                wavesReady.Add(new WaveReadyModel
                {
                    Request      = req2,
                    MovementTime = timespan
                });
            }

            var waitMs = 1000 - DateTime.Now.Millisecond - reqTripMs;

            if (waitMs < 0)
            {
                waitMs += 1000;
            }
            var wait = new TimeSpan(0, 0, 0, 0, waitMs);

            // Calculate how much you need to wait so waves arrive at the correct time!
            var      targetArrival = SendWaveModels.FirstOrDefault(x => x.Arrival != DateTime.MinValue).Arrival;
            TimeSpan waitForTarget = (targetArrival - lastArriveAt);

            if (waitForTarget > TimeSpan.Zero)
            {
                var waitForTargetSec      = (int)waitForTarget.TotalSeconds - 1; // -1 to compensate
                var waitForTargetTimeSpan = new TimeSpan(0, 0, waitForTargetSec);
                wait = wait.Add(waitForTargetTimeSpan);
            }
            await Task.Delay(wait);

            // Send the waves
            DateTime lastSent = default;

            for (int i = 0; i < wavesReady.Count; i++)
            {
                lastSent = DateTime.Now;
                acc.Wb.Log($"{DateTime.Now.Second}.{DateTime.Now.Millisecond}] Sending wave {i + 1}");
                _ = HttpHelper.SendPostReq(acc, wavesReady[i].Request);

                // Wait +- 10% selected delay
                var delay = SendWaveModels[i].DelayMs;

                // Negate the time it took to send the request
                delay -= (int)(DateTime.Now - lastSent).TotalMilliseconds;
                Console.WriteLine("New Delay " + delay);

                //var delay10Percent = (int)delay / 100;
                //await Task.Delay(rnd.Next(delay - delay10Percent, delay + delay10Percent));
                if (0 < delay)
                {
                    await Task.Delay(delay);
                }
            }
            acc.Wb.Log($"Successfully sent {wavesReady.Count} waves!");

            await Task.Delay(AccountHelper.Delay() * 2);

            await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?gid=16&tt=1&filter=2&subfilters=4");

            //Todo: check waves?
            return(TaskRes.Executed);
        }
        private void SetupChromeDriver(Access access, string username, string server)
        {
            ChromeOptions options = new ChromeOptions();

            // Turn on logging preferences for buildings localization (string).
            //var loggingPreferences = new OpenQA.Selenium.Chromium.ChromiumPerformanceLoggingPreferences();
            //loggingPreferences.IsCollectingNetworkEvents = true;
            //options.PerformanceLoggingPreferences = loggingPreferences;
            //options.SetLoggingPreference("performance", LogLevel.All);

            if (!string.IsNullOrEmpty(access.Proxy))
            {
                if (!string.IsNullOrEmpty(access.ProxyUsername))
                {
                    // Add proxy authentication
                    var extensionPath = ProxyHelper.CreateExtension(username, server, access);
                    options.AddExtension(extensionPath);
                }

                options.AddArgument($"--proxy-server={access.Proxy}:{access.ProxyPort}");
                options.AddArgument("ignore-certificate-errors"); // --ignore-certificate-errors ?
            }

            options.AddArgument($"--user-agent={access.UserAgent}");

            //options.AddArguments("--disable-logging");
            //options.AddArguments("--disable-metrics");
            //options.AddArguments("--disable-dev-tools");
            //options.AddArguments("--disable-gpu-shader-disk-cache");
            //options.AddArguments("--aggressive-cache-discard");
            //options.AddArguments("--arc-disable-gms-core-cache");

            // Mute audio because of the Ads
            options.AddArguments("--mute-audio");

            // Make browser headless to preserve memory resources
            if (acc.Settings.HeadlessMode)
            {
                options.AddArguments("headless");
            }

            // Do not download images in order to preserve memory resources / proxy traffic
            if (acc.Settings.DisableImages)
            {
                options.AddArguments("--blink-settings=imagesEnabled=false");                             //--disable-images
            }
            // Add browser caching
            var dir = IoHelperCore.GetCacheDir(username, server, access);

            Directory.CreateDirectory(dir);
            options.AddArguments("user-data-dir=" + dir);

            // Hide command prompt
            chromeService = ChromeDriverService.CreateDefaultService();
            chromeService.HideCommandPromptWindow = true;
            try
            {
                if (acc.Settings.OpenMinimized)
                {
                    options.AddArguments("--window-position=5000,5000");
                    this.Driver = new ChromeDriver(chromeService, options);
                    this.Driver.Manage().Window.Position = new System.Drawing.Point(200, 200); // TODO: change coords?
                    this.Driver.Manage().Window.Minimize();
                }
                else
                {
                    this.Driver = new ChromeDriver(chromeService, options);
                }

                // Set timeout
                this.Driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(60);
            }
            catch (Exception e)
            {
                Log($"Error opening chrome driver! Is it already opened?", e);
            }
        }
Exemple #20
0
 private void SaveAccounts_TimerElapsed(object sender, ElapsedEventArgs e) => IoHelperCore.SaveAccounts(accounts, false);
Exemple #21
0
 private void button5_Click(object sender, EventArgs e) // Logout
 {
     new Thread(() => IoHelperCore.Logout(GetSelectedAcc())).Start();
     generalUc1.UpdateBotRunning("false");
 }
        private void button2_Click(object sender, EventArgs e) //login button
        {
            var acc = GetSelectedAcc();

            new Thread(() => IoHelperCore.LoginAccount(acc)).Start();
        }
Exemple #23
0
 private void ControlPanel_FormClosing(object sender, FormClosingEventArgs e)
 {
     IoHelperCore.SaveAccounts(accounts, true);
 }
 public void Post([FromBody] string value)
 {
     IoHelperCore.LoginAccount(acc.GetAccounts().FirstOrDefault());
 }
 private void ControlPanel_FormClosing(object sender, FormClosingEventArgs e)
 {
     IoHelperCore.Quit(accounts);
 }
Exemple #26
0
 public Acc()
 {
     accounts = IoHelperCore.ReadAccounts();
 }
        public override async Task <TaskRes> Execute(HtmlDocument htmlDoc, ChromeDriver wb, Files.Models.AccModels.Account acc)
        {
            await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?tt=2&id=39");

            var wavesReady = new List <WaveReadyModel>();

            // Get request time for getting more accurate attacks
            Ping      ping      = new Ping();
            PingReply reply     = ping.Send(IoHelperCore.UrlRemoveHttp(acc.AccInfo.ServerUrl));
            var       reqTripMs = (int)(reply.RoundtripTime / 2);

            Random rnd = new Random();

            // Prepare the waves
            for (int i = 0; i < SendWaveModels.Count; i++)
            {
                Console.WriteLine(DateTime.Now + "Send wave 1");
                await Task.Delay(rnd.Next(800, 1000));

                var htmlDoc1 = await HttpHelper.SendGetReq(acc, "/build.php?tt=2&id=39");

                var build = htmlDoc1.GetElementbyId("build");

                var ajaxToken = await HttpHelper.GetAjaxToken(wb);

                var values = new Dictionary <string, string>
                {
                    { "dname", "" }, // Name of the village, empty. Bot uses coordinates
                    { "x", SendWaveModels[i].Coordinates.x.ToString() },
                    { "y", SendWaveModels[i].Coordinates.y.ToString() },
                    { "c", ((int)SendWaveModels[i].MovementType).ToString() }, // 2 = reinformance, 3 = attack, 4 = raid
                    { "s1", "ok" },
                    { "ajaxToken", ajaxToken }
                };

                foreach (var hidden in hiddenFields)
                {
                    var value = build.Descendants("input").FirstOrDefault(x => x.GetAttributeValue("name", "") == hidden).GetAttributeValue("value", "");
                    values.Add(hidden, value);
                }

                // Get available troops
                int[] troopsAtHome = TroopsMovementParser.GetTroopsInRallyPoint(htmlDoc1);
                // Send all off dirty hack
                if (SendWaveModels[i].AllOff)
                {
                    for (int j = 0; j < 10; j++)
                    {
                        var troop = TroopsHelper.TroopFromInt(acc, j);
                        if (TroopsHelper.IsTroopOffensive(troop) || TroopsHelper.IsTroopRam(troop))
                        {
                            SendWaveModels[i].Troops[j] = troopsAtHome[j];
                            troopsAtHome[j]             = 0;
                        }
                    }
                }
                // Send fake attack dirty hack
                if (SendWaveModels[i].FakeAttack)
                {
                    for (int j = 0; j < 10; j++)
                    {
                        if (troopsAtHome[j] > 19)
                        {
                            SendWaveModels[i].Troops[j] = 19;
                            troopsAtHome[j]            -= 19;
                            break;
                        }
                    }
                }

                for (int j = 0; j < SendWaveModels[i].Troops.Length; j++)
                {
                    values.Add($"t{j + 1}", SendWaveModels[i].Troops[j].ToString());
                }


                var content = new FormUrlEncodedContent(values);

                await Task.Delay(rnd.Next(800, 1000));

                var ret = await HttpHelper.SendPostReq(acc, content, "/build.php?tt=2&id=39");

                var htmlDoc2 = new HtmlAgilityPack.HtmlDocument();
                htmlDoc2.LoadHtml(ret);

                // Get time it takes for troops to the target, for later usage
                var timespan = TroopsMovementParser.GetTimeOfMovement(htmlDoc2);
                lastArriveAt = TroopsMovementParser.GetArrivalTime(htmlDoc2);
                if (timeDifference == TimeSpan.Zero)
                {
                    var serverTime = TimeParser.GetServerTime(htmlDoc2);
                    timeDifference = DateTime.Now - serverTime;
                    // Negate seconds and milliseconds in time difference.
                    var negateMillis = timeDifference.Milliseconds;
                    negateMillis  += timeDifference.Seconds * 1000;
                    timeDifference = timeDifference.Subtract(new TimeSpan(0, 0, 0, 0, negateMillis));

                    var executeTime = CorrectExecuteTime(timespan);
                    if (DateTime.Now.AddMinutes(1) < executeTime)
                    {
                        // Restart this task at the correct time
                        this.NextExecute = executeTime;
                        return(TaskRes.Executed);
                    }
                }

                //var ajaxToken = await HttpHelper.GetAjaxToken(wb);
                var values2 = new Dictionary <string, string>
                {
                    { "s1", "ok" },
                };

                // Copy all hidden names and values
                var build2   = htmlDoc2.GetElementbyId("build");
                var hiddens2 = build2.Descendants("input").Where(x => x.GetAttributeValue("type", "") == "hidden");
                foreach (var hidden2 in hiddens2)
                {
                    var val  = hidden2.GetAttributeValue("value", "");
                    var name = hidden2.GetAttributeValue("name", "");
                    values2.Add(name, val);
                }

                // Add catapult targets
                values2.TryGetValue("t8", out string cataCount);
                if (int.Parse(cataCount) > 0)
                {
                    values2.Add("ctar1", "99"); // 99 = Random, 1 = woodcuter, 2 = claypit..
                    values2.Add("ctar2", "99"); // 99 = Random
                }

                wavesReady.Add(new WaveReadyModel
                {
                    Content      = new FormUrlEncodedContent(values2),
                    MovementTime = timespan
                });

                this.DurationCounter = 0;
                Console.WriteLine(DateTime.Now + "Send wave 2");
            }

            var waitMs = 1000 - DateTime.Now.Millisecond - reqTripMs;

            if (waitMs < 0)
            {
                waitMs += 1000;
            }
            var wait = new TimeSpan(0, 0, 0, 0, waitMs);

            // Calculate how much you need to wait so waves will arrive at correct time!
            var      targetArrival = SendWaveModels.FirstOrDefault(x => x.Arrival != DateTime.MinValue).Arrival;
            TimeSpan waitForTarget = (targetArrival - lastArriveAt);

            if (waitForTarget > TimeSpan.Zero)
            {
                var waitForTargetSec      = waitForTarget.Seconds + (waitForTarget.Minutes * 60) - 1; // -1 to compensate
                var waitForTargetTimeSpan = new TimeSpan(0, 0, waitForTargetSec);
                wait = wait.Add(waitForTargetTimeSpan);
                this.DurationCounter = -(int)(wait.TotalSeconds * 2);
            }
            await Task.Delay(wait);

            // Send the waves
            for (int i = 0; i < wavesReady.Count; i++)
            {
                // Wait +- 10% selected delay
                var delay          = SendWaveModels[i].DelayMs;
                var delay10Percent = (int)delay / 10;
                await Task.Delay(rnd.Next(delay - delay10Percent, delay + delay10Percent));

                _ = HttpHelper.SendPostReq(acc, wavesReady[i].Content, "/build.php?tt=2&id=39");

                this.DurationCounter = 0;
            }

            await Task.Delay(AccountHelper.Delay() * 2);

            acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?gid=16&tt=1&filter=2&subfilters=4");
            //Todo: check waves?
            return(TaskRes.Executed);
        }
 private void button5_Click(object sender, EventArgs e) // Logout
 {
     new Thread(() => IoHelperCore.Logout(GetSelectedAcc())).Start();
 }