diff --git a/scripts/content.js b/scripts/content.js index faa3f6f..5e00901 100644 --- a/scripts/content.js +++ b/scripts/content.js @@ -12,34 +12,36 @@ let config = { password: null, frequency: null, countdown: null, + apptId: null, + apptDate: null, + signinAttempts: null, }; let minute = 60; -let signin_attempts = 0; let isRunning = false; function isSignInPage() { - return window.location.pathname.match(/^\/\w{2}-\w{2}\/n?iv\/users\/sign_in/); + return Boolean(window.location.pathname.match(/^\/\w{2}-\w{2}\/n?iv\/users\/sign_in/)); } function isLoggedOutPage() { - return window.location.pathname.match(/^\/\w{2}-\w{2}\/n?iv$/); + return Boolean(window.location.pathname.match(/^\/\w{2}-\w{2}\/n?iv$/)); } function isDashboardPage() { - return window.location.pathname.match(/^\/\w{2}-\w{2}\/n?iv\/groups\/\d+/); + return Boolean(window.location.pathname.match(/^\/\w{2}-\w{2}\/n?iv\/groups\/\d+/)); } function isAppointmentPage() { - return window.location.pathname.match(/^\/\w{2}-\w{2}\/n?iv\/schedule\/\d+\/appointment$/); + return Boolean(window.location.pathname.match(/^\/\w{2}-\w{2}\/n?iv\/schedule\/\d+\/appointment$/)); } function isConfirmationPage() { - return window.location.pathname.match(/^\/\w{2}-\w{2}\/n?iv\/schedule\/\d+\/appointment\/instructions$/); + return Boolean(window.location.pathname.match(/^\/\w{2}-\w{2}\/n?iv\/schedule\/\d+\/appointment\/instructions$/)); } function isNotEnglishPage() { - return (isSignInPage() + return Boolean(isSignInPage() || isLoggedOutPage() || isDashboardPage() || isAppointmentPage() @@ -60,18 +62,10 @@ async function goToSignInPage() { await chrome.storage.local.set({ "__status": "going to sign in page" }); document.querySelector(".homeSelectionsContainer a[href*='/sign_in']").click(); await delay(PAGE_WAIT_TIME); - // Should be on sign in page + return isSignInPage(); } async function enterCredentials() { - if (signin_attempts >= MAX_SIGNIN_ATTEMPTS) { - await chrome.storage.local.set({ "__status": "too many sign in attempts" }); - return; - } - - console.log('Signing in'); - await chrome.storage.local.set({ "__status": "signing in" }); - document.getElementById("user_email").value = config.username; document.getElementById("user_password").value = config.password; let policyConfirmed = document.querySelector('[for="policy_confirmed"]'); @@ -79,14 +73,19 @@ async function enterCredentials() { policyConfirmed.click(); } document.querySelector("#sign_in_form input[type=submit]").click(); - signin_attempts += 1; await delay(PAGE_WAIT_TIME); - if (!isDashboardPage()) { - console.log('Sign in failed'); - await chrome.storage.local.set({ "__status": "sign in failed" }); - return; + return isDashboardPage(); +} + +async function getAppointmentId() { + let appointments = document.querySelectorAll("p.consular-appt [href]") + if (appointments.length > 1) { + console.log("Multiple appointments found, taking the first one"); } + + let apptId = appointments[0].href.replace(/\D/g, ""); + return apptId; } async function checkDates() { @@ -103,14 +102,6 @@ async function runner() { isRunning = true; // console.log('runner start'); - page = window.location.pathname; - let isSignIn = !!page.match(/^\/[a-z]{2}-[a-z]{2}\/(n|)iv\/users\/sign_in/) - let isLoggedOut = !!page.match(/^\/[a-z]{2}-[a-z]{2}\/(n|)iv$/) - let isDashboard = !!page.match(/^\/[a-z]{2}-[a-z]{2}\/(n|)iv\/groups\/\d{1,}/) - let isAppointment = !!page.match(/^\/[a-z]{2}-[a-z]{2}\/(n|)iv\/schedule\/\d{1,}\/appointment$/) - let isConfirmation = !!page.match(/^\/[a-z]{2}-[a-z]{2}\/(n|)iv\/schedule\/\d{1,}\/appointment\/instructions$/) - let isNotEnglish = (isSignIn || isLoggedOut || isDashboard || isAppointment || isConfirmation) && !page.match(/^\/en-/) - let prev_config = Object.assign({}, config); let result = await new Promise(resolve => chrome.storage.local.get(null, resolve)); @@ -119,6 +110,9 @@ async function runner() { config.password = result['__password'] || ""; config.frequency = result['__frequency'] || 1; config.countdown = result['__countdown'] || 0; + config.signinAttempts = result['__signinAttempts'] || 0; + config.apptId = result['__apptId'] || null; + config.apptDate = result['__apptDate'] || null; if (prev_config.activate === null) { console.log('Reading config: ' + JSON.stringify(config)); @@ -158,7 +152,8 @@ async function runner() { // clear signin attempts when credentials are changed if (key === 'username' && config[key] || key === 'password' && config[key]) { - signin_attempts = 0; + config.signinAttempts = 0; + await chrome.storage.local.set({ "__signinAttempts": config.signinAttempts }); } } } @@ -195,17 +190,78 @@ async function runner() { return; } - if (isNotEnglish) { + if (isNotEnglishPage()) { await switchToEnglishPage(); } - if (isLoggedOut) { - await goToSignInPage(); - } else if (isSignIn) { - await enterCredentials() - } else if (isDashboard) { - signin_attempts = 0; - await checkDates(); + if (isLoggedOutPage()) { + if (!await goToSignInPage()) { + console.log('Failed to go to sign in page'); + await chrome.storage.local.set({ "__status": "failed to go to sign in page" }); + isRunning = false; + return; + }; + + } else if (isSignInPage()) { + // Prevent brute forcing + if (config.signinAttempts >= MAX_SIGNIN_ATTEMPTS) { + await chrome.storage.local.set({ "__status": "too many sign in attempts" }); + isRunning = false; + return; + } + + // Sign in + console.log('Signing in attempt: ' + config.signinAttempts) + await chrome.storage.local.set({ "__status": "signing in #" + config.signinAttempts }); + let signedIn = await enterCredentials(); + config.signinAttempts += 1; + await chrome.storage.local.set({ "__signinAttempts": config.signinAttempts }); + if (!signedIn) { + console.log('Sign in failed'); + await chrome.storage.local.set({ "__status": "sign in failed" }); + isRunning = false; + return; + }; + + } else if (isDashboardPage()) { + // reset signin attempts when successfully logged in + config.signinAttempts = 0; + await chrome.storage.local.set({ "__status": "fetching appointment info" }); + await chrome.storage.local.set({ "__signinAttempts": config.signinAttempts }); + + // get appointmentId + if (!config.apptId) { + config.apptId = await getAppointmentId(); + if (config.apptId) { + console.log(`Appointment ID: ${apptId}`); + await chrome.storage.local.set({ "__apptId": apptId }); + } else { + console.log('No appointments found'); + await chrome.storage.local.set({ "__status": "no appointment found" }); + isRunning = false; + return; + } + } + + // get current appointment date + let apptInfo = document.querySelector("p.consular-appt [href*='" + config.apptId + "']").parentNode.parentNode.parentNode + if (!apptInfo.querySelector("h4").innerText.match(/Attend Appointment/)) { + console.log('Appointment not available'); + await chrome.storage.local.set({ "__status": "appointment not available" }); + isRunning = false; + return; + } + let apptDate = new Date(apptInfo.querySelector("p.consular-appt").innerText.match(/\d{1,2} \w+, \d{4}/)[0]); + apptDate = apptDate.toISOString().slice(0, 10); + if (config.apptDate && apptDate != config.apptDate) { + config.apptDate = apptDate; + await chrome.storage.local.set({ "__apptDate": apptDate }); + } + + // go to appointment page + let apptLink = apptInfo.querySelector("p.consular-appt [href]").getAttribute("href").replace("/addresses/consulate", "/appointment"); + window.location.href = apptLink; + await delay(PAGE_WAIT_TIME); } // console.log('runner done');