// ********************************************************* Private Methods private static List <Indeed> ReduceQuickies(List <Indeed> superset, bool companySingleApply, SqlConnection con) { List <Indeed> reduced = new List <Indeed>(); if (companySingleApply) { reduced.AddRange ( superset.Where ( page => !IndeedSql.AlreadyAppliedCompany(page.Company, con) && !IndeedSql.AlreadyAppliedToJob(page.Jobkey, page.Url, con) ) ); } else { reduced.AddRange ( superset.Where ( page => !IndeedSql.AlreadyAppliedToJob(page.Jobkey, page.Url, con) ) ); } return(reduced); }
private static bool SaveSubmission(Indeed applied, bool successfulApply, SqlConnection con) { InsertApplyOps ops = new InsertApplyOps(); ops.Jobkey = applied.Jobkey ?? ""; ops.Url = applied.Url ?? ""; ops.Snippet = applied.Snippet ?? ""; ops.JobTitle = applied.JobTitle ?? ""; ops.Company = applied.Company ?? ""; ops.DateTimeApplied = DateTime.Now; ops.Sponsored = applied.Sponsored.ToString(); ops.Expired = applied.Expired.ToString(); ops.IndeedApply = applied.IndeedApply.ToString(); ops.FormattedLocationFull = applied.FormattedLocationFull ?? ""; ops.FormattedRelativeTime = applied.FormattedRelativeTime ?? ""; ops.OnMouseDown = applied.OnMouseDown ?? ""; ops.Latitude = applied.Latitude ?? ""; ops.Longitude = applied.Longitude ?? ""; ops.City = applied.City ?? ""; ops.State = applied.State ?? ""; ops.Country = applied.Country ?? ""; ops.FormattedLocation = applied.FormattedLocation ?? ""; ops.Source = applied.Source ?? ""; ops.Date = applied.Date ?? ""; try { IndeedSql.InsertApply(ops, successfulApply, con); return(true); } catch { Console.WriteLine("ERROR IN SAVING TO DB: MANUALLY INSERT NOW"); return(false); } }
public static void ViaIndeed(string searchTerm, string location, string countryCode, bool companySingleApply, string sql, User user, string apikey) { SqlConnection con = new SqlConnection(sql); // Append string with rest of display display = "Location: " + location + " Search Term(s): " + searchTerm; Console.Clear(); // Retrieve all pages with "Quick Apply" button on them ONLY var supersetQuickies = GetAllQuickies(searchTerm, location, countryCode, apikey); Console.Clear(); Console.WriteLine(display); // Reduce by configurations passed. Do not appy to // same company 2ce in a session (companySingleApply) var reducedQuckies = ReduceQuickies(supersetQuickies, companySingleApply, con); //There is nothing (new) to add therefore exit if (reducedQuckies.Count == 0) { return; } // Initialize Chrome Driver with Selenium API var driver = new ChromeDriver(); for (int j = 0; j < reducedQuckies.Count; j++) { // If already applied to company proceed loop if (IndeedSql.AlreadyAppliedCompany(reducedQuckies[j].Company, con)) { continue; } //Load the Job Posting page driver.Url = reducedQuckies[j].Url; string jk = reducedQuckies[j].Jobkey; // Passed from Indeed API query string jobTitle = reducedQuckies[j].JobTitle; // Passed from Indeed API query string hl = "en"; // English parameter string co = countryCode; //Get Variables to Store later from Job Posting page directly: string jobCompany = driver.FindElementByClassName("company").Text; string jobId = ""; try { jobId = driver.FindElements (By.CssSelector(".indeed-apply-widget"))[0] .GetAttribute("data-indeed-apply-jobid"); } catch { continue; } string apiToken = driver.FindElements(By.CssSelector(".indeed-apply-widget"))[0].GetAttribute( "data-indeed-apply-apitoken"); string postUrl = driver.FindElements(By.CssSelector(".indeed-apply-widget"))[0].GetAttribute( "data-indeed-apply-posturl"); string jobUrl = driver.FindElements(By.CssSelector(".indeed-apply-widget"))[0].GetAttribute( "data-indeed-apply-joburl"); string iaUid = driver.FindElement(By.Id("indeed-apply-js")) .GetAttribute("data-indeed-apply-qs") .Replace("vjtk=", ""); //iaUid == vjtk (variable)!!!!!! string advNum = driver.FindElements(By.CssSelector(".indeed-apply-widget"))[0].GetAttribute( "data-indeed-apply-advnum"); string email = string.Empty; try { email = driver.FindElements(By.CssSelector(".indeed-apply-widget"))[0].GetAttribute( "data-indeed-apply-email"); } catch {} // Generate URL is for the Application page ONLY string applyUrl = GenerateURL.ApplyUrl(email, postUrl, jk, jobTitle, jobUrl, jobCompany, jobId, apiToken, co, hl, advNum, iaUid); // Cover Letter Construction string pathToTemplate = user.CoverLetter; // Path to cover letter template. // Location of template string coverLetter = File.ReadAllText(pathToTemplate); // Simple replace to insert Location on the Fly (e.g. Richmond, VA) coverLetter = coverLetter.Replace("%varArea%", reducedQuckies[j].FormattedLocationFull); // Simple replace to insert Position on the Fly coverLetter = coverLetter.Replace("%varPos%", reducedQuckies[j].JobTitle); // Simple replace to insert Company Name (e.g. Bit Byte Buffer, LLC) coverLetter = coverLetter.Replace("%varCompany%", reducedQuckies[j].Company); // Workaround because driver will crash if you use for too long. // This may be resolved with newer versions of the driver count++; if (count == 10) { count = 0; driver.Close(); driver = new ChromeDriver(); driver.Url = reducedQuckies[j].Url; //Information Page } // Navigate to Application Page driver.Url = applyUrl; // Fill in My Name try // 1st Potential Id { driver.FindElementById("applicant.name").Clear(); driver.FindElementById("applicant.name").SendKeys(user.AppName); } catch { try // 2nd Potential Id (prefixed with "input-") { driver.FindElementById("input-applicant.name").Clear(); driver.FindElementById("input-applicant.name").SendKeys(user.AppName); } catch { // Can't insert name, therefore must not be a // quick apply (otherwise run should go smoothly) continue; } } // Fill in My Email try // 1st Potential Id { driver.FindElementById("applicant.email").Clear(); driver.FindElementById("applicant.email").SendKeys(user.AppEmail); } catch { try // 2nd Potential Id (prefixed with "input-") { driver.FindElementById("input-applicant.email").Clear(); driver.FindElementById("input-applicant.email").SendKeys(user.AppEmail); } catch { continue; } } // Fill in Phone Number try // 1st Potential Id { driver.FindElementById("applicant.phoneNumber").Clear(); driver.FindElementById("applicant.phoneNumber").SendKeys(user.AppPhone); } catch { try // 2nd Potential Id (prefixed with "input-") { driver.FindElementById("input-applicant.phoneNumber").Clear(); driver.FindElementById("input-applicant.phoneNumber").SendKeys(user.AppPhone); } catch { continue; } } //Upload Resume try { driver.FindElementById("resume") .SendKeys(user.AppResumePath); } catch { try { driver.FindElementById("ia-FilePicker-resume") .SendKeys(user.AppResumePath); } catch { continue; } } //Upload Supporting documents (e.g. Degree, Certifications, etc.) try { if (!string.IsNullOrEmpty(user.AppSupportingDoc1)) { driver.FindElementById("multattach1") .SendKeys(user.AppSupportingDoc1); } if (!string.IsNullOrEmpty(user.AppSupportingDoc2)) { driver.FindElementById("multattach2") .SendKeys(user.AppSupportingDoc2); } if (!string.IsNullOrEmpty(user.AppSupportingDoc3)) { driver.FindElementById("multattach3") .SendKeys(user.AppSupportingDoc3); } if (!string.IsNullOrEmpty(user.AppSupportingDoc4)) { driver.FindElementById("multattach4") .SendKeys(user.AppSupportingDoc4); } if (!string.IsNullOrEmpty(user.AppSupportingDoc5)) { driver.FindElementById("multattach5") .SendKeys(user.AppSupportingDoc5); } } catch { // stub: means there is no control for // supporting file uploads on page which is common } try { // Fill cover letter text box on form (attempt 1 with original Id) IJavaScriptExecutor js = driver; js.ExecuteScript("document.getElementById('applicant.applicationMessage').setAttribute('style', '')"); driver.FindElementById("applicant.applicationMessage").Click(); driver.FindElementById("applicant.applicationMessage").Clear(); driver.FindElementById("applicant.applicationMessage").SendKeys(coverLetter); } catch { try { // Fill cover letter text box on form (attempt 2 with new preixed "textarea-" Id) IJavaScriptExecutor js = driver; js.ExecuteScript("document.getElementById('textarea-applicant.applicationMessage').setAttribute('style', '')"); driver.FindElementById("textarea-applicant.applicationMessage").Click(); driver.FindElementById("textarea-applicant.applicationMessage").Clear(); driver.FindElementById("textarea-applicant.applicationMessage").SendKeys(coverLetter); } catch { // Could not identify an Application Message textbox to fill continue; } } //************ Apply Here ************* //Click on button submit try // Attempt 1, click button by CSS Class Selector { driver.FindElement(By.CssSelector(".button_content")).Click(); } catch { try // Attempt 2, click button by CSS ID Selector { driver.FindElement(By.CssSelector("#form-action-submit")).Click(); } catch { // Stub: Cannot find Application Button continue; } } // Let new page load for 1.5 seconds after clicking // submit application button Thread.Sleep(1500); try // Additional Yes/No questions added to US applications sometimes { driver.FindElement(By.Id("q_0")).SendKeys("Yes"); driver.FindElement(By.Id("apply")).Click(); } catch { // Stub: Not uncommon for this not to exist. In most cases it does not exist. } // Start Save process Stopwatch sw = new Stopwatch(); sw.Start(); while (true) { try { //Give it 2.5 minutes to upload all documents as max time permissible if (sw.ElapsedMilliseconds > 60000 * 2.5) { // Insert Failure message here!! SaveSubmission(reducedQuckies[j], false, con); //Changed to true as they are fine. Console.Clear(); Console.WriteLine(display); Console.WriteLine("\nFailed to apply: " + reducedQuckies[j].Company + " (" + reducedQuckies[j].JobTitle + ")"); break; // Exit while loop } driver.FindElement(By.Id("ia_success")); //Insert success message here!! Console.Clear(); Console.WriteLine(display); Console.WriteLine("\nSucceeded in applying to: " + reducedQuckies[j].Company + " (" + reducedQuckies[j].JobTitle + ")"); SaveSubmission(reducedQuckies[j], true, con); break; } catch { // Stub: recursion occurs until element found on page // and save is successful, or element is not found after // 2.5 minutes and record is saved as unsuccessful application } } // Sleep for 2 seconds before moving to next application Thread.Sleep(2000); } driver.Close(); driver.Dispose(); }