public async Task <IEnumerable <AddressResponse> > ProcessApplications(RemoteWebDriver aDriver, BlockingCollection <AddressResponse> aResponses)
        {
            foreach (var address in aResponses.GetConsumingEnumerable())
            {
                if (await MapTheVoteScripter.SelectMapMarker(aDriver, address))
                {
                    // If we can successfully sleect a marker, this means that we have it in the cache,
                    // and it's valid. We can move on to the SoS site to submit an application.
                    var submissionSuccess = await SubmitNewApplication(aDriver, address);

                    if (submissionSuccess)
                    {
                        var applicationLogged = await MapTheVoteScripter.MarkApplicationProcessed(aDriver);

                        if (applicationLogged)
                        {
                            SubmittedAddresses.Add(address);
                        }
                    }
                }
            }

            await MapTheVoteScripter.CloseMarkerWindow(aDriver);

            return(SubmittedAddresses);
        }
Example #2
0
        static void Main(string[] args)
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("MapThe.Vote/Map Address Builder");
            Console.WriteLine("By: CJ Stankovich https://github.com/siegeJ");
            Console.ForegroundColor = ConsoleColor.White;

            Util.PreventSleep();

            ParseCommandLineArguments(args);

            SetupDriver();

            if (!string.IsNullOrEmpty(JSESSIONID))
            {
                // Can't set a cookie for a domain that we're not yet on.
                // Go to something that we know will 404 so that we can set cookies
                // before continuing execution.
                _driver.Navigate().GoToUrl(@"https://mapthe.vote/404page");

                // TODO: Attempt to get cookie from browser.
                _driver.Manage().Cookies.AddCookie(new OpenQA.Selenium.Cookie("JSESSIONID", JSESSIONID, "mapthe.vote", "/", null));
            }

            // With our JSESSION initialized, we can move onto the actual map.
            _driver.Navigate().GoToUrl(@"https://mapthe.vote/map");

            // Need to manually log in if we don't have a valid cookie.
            if (string.IsNullOrEmpty(JSESSIONID))
            {
                MapTheVoteScripter.Login(_driver);

                var jsessionCookie = _driver.Manage().Cookies.GetCookieNamed("JSESSIONID");
                if (jsessionCookie != null)
                {
                    JSESSIONID = jsessionCookie.Value;
                }
            }

            // I hate this, but for some reason waiting for map-msg-button just doesn't work.
            Util.RandomWait(1000).Wait();

            _driver.ClickOnElement("map-msg-button", ElementSearchType.ClassName).Wait();

            DateTime startingTime = default;

            var        numFails = 0;
            var        lastNumAddressesParsed = 0;
            ViewBounds prevBounds             = null;

            var appSubmitter = new ApplicationSubmitter();

            while (numFails < 3)
            {
                Task <IEnumerable <AddressResponse> > processAppsTask = null;
                appSubmitter.SubmittedAddresses.Clear();

                try
                {
                    // Wait for user input if we've successfully parsed everything from the
                    // previous run. Otherwise we can use the same bounds again in order to
                    // re-sweep for the markers that we may have missed.
                    // This can happpen
                    var noAddressesParsed = lastNumAddressesParsed == 0;
                    if (noAddressesParsed || (prevBounds == null))
                    {
                        if (noAddressesParsed && prevBounds != null && (prevBounds.Zoom > ViewBounds.ZOOM_LIMITS.Item1))
                        {
                            MapTheVoteScripter.DecrementZoom(_driver, prevBounds);
                            // Reset fail count if we're going to try searching around.
                            numFails = 0;
                        }
                        else
                        {
                            // End execution if the user has idled out
                            var success = MapTheVoteScripter.WaitForMarkerSelection(_driver);
                            if (!success)
                            {
                                break;
                            }
                        }

                        prevBounds = MapTheVoteScripter.GetCurrentViewBounds(_driver);
                    }
                    else
                    {
                        Console.WriteLine("Repeating the previous search to find uncached values.");
                    }

                    startingTime = DateTime.Now;

                    var scraper = new AddressScraper();
                    scraper.Initialize(JSESSIONID);

                    if (prevBounds != null)
                    {
                        MapTheVoteScripter.CenterOnViewBounds(_driver, prevBounds);
                    }

                    var getAddressesTask = scraper.GetTargetAddresses(_driver, prevBounds);
                    processAppsTask = appSubmitter.ProcessApplications(_driver, scraper.ParsedAddresses);

                    Task.WaitAll(getAddressesTask, processAppsTask);

                    lastNumAddressesParsed = getAddressesTask.Result;
                }
                catch (Exception e)
                {
                    Util.LogError(ErrorPhase.Misc, e.ToString());
                }

                // Do this in case the user did something to f**k things up. This way we can still successfully write out the file.
                // TODO: Thread the filewriting.
                if (processAppsTask != null && processAppsTask.Status == TaskStatus.Running)
                {
                    processAppsTask.Wait();
                }

                var lastNumAddressesSubmitted = appSubmitter.SubmittedAddresses.Count;

                var addressesSubmitted = lastNumAddressesSubmitted != 0;
                // We wait for 3 consecutive fails before ultimately deciding to call it quits.
                numFails = addressesSubmitted ? 0 : numFails + 1;
                if (addressesSubmitted)
                {
                    var adressesSubmitted = lastNumAddressesSubmitted != 0;
                    Console.WriteLine($"Successfully submitted { lastNumAddressesSubmitted } / { lastNumAddressesParsed } applications.");

                    // Sort our addresses by Zip, City, and then address.
                    appSubmitter.SubmittedAddresses.Sort((lhs, rhs) =>
                    {
                        var compareVal = lhs.Zip5.CompareTo(rhs.Zip5);

                        if (compareVal == 0)
                        {
                            compareVal = lhs.City.CompareTo(rhs.City);

                            if (compareVal == 0)
                            {
                                compareVal = lhs.FormattedAddress.CompareTo(rhs.FormattedAddress);
                            }
                        }

                        return(compareVal);
                    });

                    WriteAddressesFile(AddressesFileName, appSubmitter.SubmittedAddresses);
                }

                Console.WriteLine("Completed in {0}", DateTime.Now - startingTime);
            }

            CombineAddressesFiles();

            Console.WriteLine("Execution complete. Restart the application to send more registration forms.");
        }