function log_ts(message) { console.log(new Date().toISOString() + " " + message); } async function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } const pathnameRegex = /^\/\w{2}-\w{2}\/n?iv/; const MAX_SIGNIN_ATTEMPTS = 2; const PAGE_WAIT_TIME = 5000; let config = { activate: null, username: null, password: null, frequency: null, countdown: null, }; let minute = 60; let signin_attempts = 0; function isSignInPage() { return 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$/); } function isDashboardPage() { return 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$/); } function isConfirmationPage() { return window.location.pathname.match(/^\/\w{2}-\w{2}\/n?iv\/schedule\/\d+\/appointment\/instructions$/); } function isNotEnglishPage() { return (isSignInPage() || isLoggedOutPage() || isDashboardPage() || isAppointmentPage() || isConfirmationPage() ) && !window.location.pathname.match(/^\/en-/); } async function switchToEnglishPage() { log_ts('Changing page to English'); await chrome.storage.local.set({ "__status": "switching to English" }); window.location.href(window.location.pathname.replace(/^\/\w{2}-{2}/, '/en-us')); delay(PAGE_WAIT_TIME); // Should be on English page } async function goToSignInPage() { log_ts('Going to sign in page') await chrome.storage.local.set({ "__status": "going to sign in page" }); document.querySelector(".homeSelectionsContainer a[href*='/sign_in']").click(); delay(PAGE_WAIT_TIME); // Should be on sign in page } async function enterCredentials() { if (signin_attempts == MAX_SIGNIN_ATTEMPTS) { log_ts('Too many sign in attempts'); await chrome.storage.local.set({ "__status": "too many sign in attempts" }); return; } log_ts('Signing in'); await chrome.storage.local.set({ "__status": "signing in" }); document.getElementById("user_email").value = config.username; document.getElementById("user_password").value = config.password; document.querySelector('[for="policy_confirmed"]').click(); document.querySelector("#sign_in_form input[type=submit]").click(); signin_attempts += 1; delay(PAGE_WAIT_TIME); // Should be on dashboard page } async function checkDates() { log_ts('checkDates start'); config.countdown = config.frequency * minute; await chrome.storage.local.set({ "__countdown": config.countdown }); log_ts('checkDates done'); } async function runner() { 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-/) // log_ts('runner start'); let prev_config = Object.assign({}, config); let result = await new Promise(resolve => chrome.storage.local.get(null, resolve)); config.activate = result['__activate'] || false; config.username = result['__username'] || ""; config.password = result['__password'] || ""; config.frequency = result['__frequency'] || 1; config.countdown = result['__countdown'] || 0; if (prev_config.activate === null) { log_ts('Reading config: ' + JSON.stringify(config)); return; } let configChanged = false; for (let key in config) { if (config.hasOwnProperty(key) && config[key] !== prev_config[key]) { log_ts(`Config change: ${key}, ${prev_config[key]} => ${config[key]}`); configChanged = true; // reduce countdown if frequency is reduced if (key === 'frequency') { let max_countdown = config[key] * minute; if (config.countdown > max_countdown) { config.countdown = max_countdown; await chrome.storage.local.set({ "__countdown": config.countdown }); } } if (key === 'activate') { if (config[key]) { log_ts('Activating extension'); config.countdown = 5; await chrome.storage.local.set({ "__countdown": config.countdown }); } else { log_ts('Deactivating extension'); // reset countdown when deactivating the extension config.countdown = 0; await chrome.storage.local.set({ "__countdown": config.countdown }); await chrome.storage.local.set({ "__status": "inactive" }); } } // clear signin attempts when credentials are changed if (key === 'username' && config[key] || key === 'password' && config[key]) { signin_attempts = 0; } } } if (configChanged) { // print whole config log_ts(JSON.stringify(config)); } if (!config.activate) { return; } if (config.username === "" || config.password === "") { log_ts('Username or password is empty'); await chrome.storage.local.set({ "__status": "missing credentials" }); return; } if (config.frequency <= 0) { log_ts('Frequency is 0 or negative'); await chrome.storage.local.set({ "__status": "invalid frequency" }); return; } if (config.countdown > 0) { config.countdown -= 1; log_ts(`Countdown: ${config.countdown}`); await chrome.storage.local.set({ "__countdown": config.countdown }); await chrome.storage.local.set({ "__status": `waiting, ${config.countdown}s` }); return; } if (isNotEnglish) { await switchToEnglishPage(); } if (isLoggedOut) { await goToSignInPage(); } else if (isSignIn) { await enterCredentials() } else if (isDashboard) { signin_attempts = 0; await checkDates(); } // log_ts('runner done'); } setInterval(runner, 1000);