Separate configuration and context for consulates
This commit is contained in:
parent
d4c8835e9b
commit
3f2ba8bd2a
114
popup/popup.js
114
popup/popup.js
@ -14,34 +14,33 @@ function smoothTextChange(element, newText) {
|
|||||||
document.getElementById("version").innerText = `v${$version}`;
|
document.getElementById("version").innerText = `v${$version}`;
|
||||||
|
|
||||||
await chrome.storage.local.get().then(items => {
|
await chrome.storage.local.get().then(items => {
|
||||||
document.getElementById("activate").checked = items["__activate"] || false;
|
document.getElementById("activate").checked = items["cfg_activate"] || false;
|
||||||
document.getElementById("username").value = items["__username"] || "";
|
document.getElementById("username").value = items["cfg_username"] || "";
|
||||||
document.getElementById("password").value = items["__password"] || "";
|
document.getElementById("password").value = items["cfg_password"] || "";
|
||||||
document.getElementById("frequency").value = items["__frequency"] || 1;
|
document.getElementById("frequency").value = items["cfg_frequency"] || 1;
|
||||||
document.getElementById("frequency_info").innerText = items["__frequency"] || 1;
|
document.getElementById("frequency_info").innerText = items["cfg_frequency"] || 1;
|
||||||
document.getElementById("status").innerText = items["__status"] || "unknown";
|
document.getElementById("status").innerText = items["ctx_statusMsg"] || "unknown";
|
||||||
let currentAppt = items["__currentAppt"] || {"consulate": "somewhere", "date": "some time"};
|
let currentAppt = items["ctx_currentAppt"] || {"consulate": "somewhere", "date": "some time"};
|
||||||
document.getElementById("currApptConsulate").innerText = currentAppt["consulate"];
|
document.getElementById("currApptConsulate").innerText = currentAppt["consulate"];
|
||||||
document.getElementById("currApptDate").innerText = currentAppt["date"];
|
document.getElementById("currApptDate").innerText = currentAppt["date"];
|
||||||
document.getElementById("deltaAppt").value = items["__deltaAppt"] || 1;
|
document.getElementById("deltaAppt").value = items["cfg_deltaAppt"] || 1;
|
||||||
document.getElementById("deltaNow").value = items["__deltaNow"] || 1;
|
document.getElementById("deltaNow").value = items["cfg_deltaNow"] || 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
// update frequency value
|
// update frequency value
|
||||||
chrome.storage.onChanged.addListener((changes, area) => {
|
chrome.storage.onChanged.addListener((changes, area) => {
|
||||||
if (changes.__frequency)
|
if (changes.cfg_frequency)
|
||||||
document.getElementById("frequency_info").innerText = changes.__frequency.newValue;
|
document.getElementById("frequency_info").innerText = changes.cfg_frequency.newValue;
|
||||||
});
|
});
|
||||||
// update status
|
// update status
|
||||||
chrome.storage.onChanged.addListener((changes, area) => {
|
chrome.storage.onChanged.addListener((changes, area) => {
|
||||||
if (changes.__status)
|
if (changes.ctx_statusMsg)
|
||||||
// document.getElementById("status").innerText = changes.__status.newValue;
|
smoothTextChange(document.getElementById("status"), changes.ctx_statusMsg.newValue);
|
||||||
smoothTextChange(document.getElementById("status"), changes.__status.newValue);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// activate checkbox
|
// activate checkbox
|
||||||
document.getElementById("activate").addEventListener("change", async e => {
|
document.getElementById("activate").addEventListener("change", async e => {
|
||||||
await chrome.storage.local.set({ "__activate": e.target.checked });
|
await chrome.storage.local.set({ "cfg_activate": e.target.checked });
|
||||||
});
|
});
|
||||||
|
|
||||||
// credentials
|
// credentials
|
||||||
@ -53,8 +52,8 @@ function smoothTextChange(element, newText) {
|
|||||||
|
|
||||||
async function save_credentials() {
|
async function save_credentials() {
|
||||||
await chrome.storage.local.set({
|
await chrome.storage.local.set({
|
||||||
"__username": usernameField.value,
|
"cfg_username": usernameField.value,
|
||||||
"__password": passwordField.value
|
"cfg_password": passwordField.value
|
||||||
});
|
});
|
||||||
saveStatusElement.classList.add("show");
|
saveStatusElement.classList.add("show");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -74,7 +73,7 @@ function smoothTextChange(element, newText) {
|
|||||||
});
|
});
|
||||||
saveCredsButton.addEventListener("click", async () => {
|
saveCredsButton.addEventListener("click", async () => {
|
||||||
await save_credentials();
|
await save_credentials();
|
||||||
await chrome.storage.local.set({ "__signinAttempts": 0 });
|
await chrome.storage.local.set({ "ctx_signinAttempts": 0 });
|
||||||
});
|
});
|
||||||
|
|
||||||
showPasswordButton.addEventListener("mousedown", function() {
|
showPasswordButton.addEventListener("mousedown", function() {
|
||||||
@ -86,18 +85,19 @@ function smoothTextChange(element, newText) {
|
|||||||
|
|
||||||
// range sliders
|
// range sliders
|
||||||
document.getElementById("frequency").addEventListener("input", function() {
|
document.getElementById("frequency").addEventListener("input", function() {
|
||||||
chrome.storage.local.set({ __frequency: this.value });
|
chrome.storage.local.set({ cfg_frequency: this.value });
|
||||||
});
|
});
|
||||||
document.getElementById("deltaAppt").addEventListener("input", function() {
|
document.getElementById("deltaAppt").addEventListener("input", function() {
|
||||||
chrome.storage.local.set({ __deltaAppt: this.value });
|
chrome.storage.local.set({ cfg_deltaAppt: this.value });
|
||||||
});
|
});
|
||||||
document.getElementById("deltaNow").addEventListener("change", function() {
|
document.getElementById("deltaNow").addEventListener("change", function() {
|
||||||
chrome.storage.local.set({ __deltaNow: this.value });
|
chrome.storage.local.set({ cfg_deltaNow: this.value });
|
||||||
});
|
});
|
||||||
|
|
||||||
// consulates
|
// consulates
|
||||||
await chrome.storage.local.get(['__consulates']).then((result) => {
|
await chrome.storage.local.get(['cfg_consulates', 'ctx_consulates']).then((result) => {
|
||||||
let consulates = result['__consulates'];
|
let consCfg = result['cfg_consulates'];
|
||||||
|
let consCtx = result['ctx_consulates'];
|
||||||
|
|
||||||
let html = `
|
let html = `
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
@ -112,10 +112,10 @@ function smoothTextChange(element, newText) {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
`
|
`
|
||||||
for (let c in consulates) {
|
for (let c in consCtx) {
|
||||||
let cSelected = consulates[c].isSelected === true ? "checked" : "";
|
let cSelected = consCfg[c]?.isSelected === true ? "checked" : "";
|
||||||
let cAutobook = consulates[c].autobook === true ? "checked" : "";
|
let cAutoBook = consCfg[c]?.autoBook === true ? "checked" : "";
|
||||||
let cId = consulates[c].id;
|
let cId = consCtx[c].id;
|
||||||
html += `
|
html += `
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@ -124,12 +124,12 @@ function smoothTextChange(element, newText) {
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td style="white-space: nowrap;">${c}</td>
|
<td style="white-space: nowrap;">${c}</td>
|
||||||
<td style="white-space: nowrap;"><span class="smooth-text" id="currentDate-${cId}">${consulates[c].currentDate || "-"}</span></td>
|
<td style="white-space: nowrap;"><span class="smooth-text" id="currentDate-${cId}">${consCtx[c].currentDate || "-"}</span></td>
|
||||||
<td style="white-space: nowrap;"><span class="smooth-text" id="bestDate-${cId}">${consulates[c].bestDate || "-"}</span></td>
|
<td style="white-space: nowrap;"><span class="smooth-text" id="bestDate-${cId}">${consCtx[c].bestDate || "-"}</span></td>
|
||||||
<td>
|
<td>
|
||||||
<div class="form-check form-switch" style="text-align: left;">
|
<div class="form-check form-switch" style="text-align: left;">
|
||||||
<input class="form-check-input" type="checkbox" role="switch" id="autobook-${cId}" ${cAutobook}>
|
<input class="form-check-input" type="checkbox" role="switch" id="autoBook-${cId}" ${cAutoBook}>
|
||||||
<!--<label class="form-check-label" for="autobook-${cId}">Autobook</label>-->
|
<!--<label class="form-check-label" for="autoBook-${cId}">Autobook</label>-->
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -138,30 +138,35 @@ function smoothTextChange(element, newText) {
|
|||||||
html += `</tbody></table>`;
|
html += `</tbody></table>`;
|
||||||
document.getElementById('consulatesConfig').innerHTML = html;
|
document.getElementById('consulatesConfig').innerHTML = html;
|
||||||
|
|
||||||
for (let c in consulates) {
|
for (let c in consCtx) {
|
||||||
let cId = consulates[c].id;
|
let cId = consCtx[c].id;
|
||||||
document.getElementById(`isSelected-${cId}`).addEventListener("change", async e => {
|
document.getElementById(`isSelected-${cId}`).addEventListener("change", async e => {
|
||||||
consulates[c].isSelected = e.target.checked;
|
consCfg[c].isSelected = e.target.checked;
|
||||||
await chrome.storage.local.set({ "__consulates": consulates });
|
await chrome.storage.local.set({ "cfg_consulates": consCfg });
|
||||||
});
|
});
|
||||||
document.getElementById(`autobook-${cId}`).addEventListener("change", async e => {
|
document.getElementById(`autoBook-${cId}`).addEventListener("change", async e => {
|
||||||
consulates[c].autobook = e.target.checked;
|
consCfg[c].autoBook = e.target.checked;
|
||||||
await chrome.storage.local.set({ "__consulates": consulates });
|
await chrome.storage.local.set({ "cfg_consulates": consCfg });
|
||||||
});
|
});
|
||||||
// update current & best dates
|
// update current & best dates
|
||||||
chrome.storage.onChanged.addListener((changes, area) => {
|
chrome.storage.onChanged.addListener((changes, area) => {
|
||||||
if (changes.__consulates && changes.__consulates.newValue[c].currentDate) {
|
if (area === 'local' && changes.ctx_consulates) {
|
||||||
let el = document.getElementById(`currentDate-${cId}`);
|
const newConsulates = changes.ctx_consulates.newValue;
|
||||||
if (el.innerText != changes.__consulates.newValue[c].currentDate)
|
|
||||||
smoothTextChange(document.getElementById(`currentDate-${cId}`), changes.__consulates.newValue[c].currentDate);
|
for (let c in newConsulates) {
|
||||||
}
|
if (newConsulates[c].currentDate) {
|
||||||
if (changes.__consulates && changes.__consulates.newValue[c].bestDate) {
|
let el = document.getElementById(`currentDate-${c}`);
|
||||||
let el = document.getElementById(`bestDate-${cId}`);
|
if (el && el.innerText != newConsulates[c].currentDate)
|
||||||
if (el.innerText != changes.__consulates.newValue[c].bestDate)
|
smoothTextChange(el, newConsulates[c].currentDate);
|
||||||
smoothTextChange(document.getElementById(`bestDate-${cId}`), changes.__consulates.newValue[c].bestDate);
|
}
|
||||||
|
if (newConsulates[c].bestDate) {
|
||||||
|
let el = document.getElementById(`bestDate-${c}`);
|
||||||
|
if (el && el.innerText != newConsulates[c].bestDate)
|
||||||
|
smoothTextChange(el, newConsulates[c].bestDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -172,13 +177,12 @@ function smoothTextChange(element, newText) {
|
|||||||
chrome.storage.local.clear();
|
chrome.storage.local.clear();
|
||||||
// keep user parameters
|
// keep user parameters
|
||||||
chrome.storage.local.set({
|
chrome.storage.local.set({
|
||||||
"__activate": items["__activate"] || false,
|
"cfg_activate": items["cfg_activate"] || false,
|
||||||
"__username": items["__username"] || "",
|
"cfg_username": items["cfg_username"] || "",
|
||||||
"__password": items["__password"] || "",
|
"cfg_password": items["cfg_password"] || "",
|
||||||
"__frequency": items["__frequency"] || 1,
|
"cfg_frequency": items["cfg_frequency"] || 1,
|
||||||
"__deltaAppt": items["__deltaAppt"] || 1,
|
"cfg_deltaAppt": items["cfg_deltaAppt"] || 1,
|
||||||
"__deltaNow": items["__deltaNow"] || 1,
|
"cfg_deltaNow": items["cfg_deltaNow"] || 1,
|
||||||
"__autobook": items["__autobook"] || false,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
document.getElementById("status").innerText = "unknown";
|
document.getElementById("status").innerText = "unknown";
|
||||||
|
|||||||
@ -9,21 +9,25 @@ const RANDOM_JITTER = 0.1;
|
|||||||
const SOFT_BAN_TIMEOUT = 27;
|
const SOFT_BAN_TIMEOUT = 27;
|
||||||
const NOTIF_CHANNEL = "snegov_test"
|
const NOTIF_CHANNEL = "snegov_test"
|
||||||
|
|
||||||
let config = {
|
let cfg = {
|
||||||
activate: null,
|
activate: undefined,
|
||||||
username: null,
|
username: undefined,
|
||||||
password: null,
|
password: undefined,
|
||||||
frequency: null,
|
frequency: undefined,
|
||||||
apptId: null,
|
consulates: undefined,
|
||||||
currentAppt: {
|
deltaAppt: undefined,
|
||||||
consulate: null,
|
deltaNow: undefined,
|
||||||
date: null,
|
|
||||||
},
|
|
||||||
signinAttempts: null,
|
|
||||||
consulates: null,
|
|
||||||
deltaAppt: null,
|
|
||||||
deltaNow: null,
|
|
||||||
};
|
};
|
||||||
|
let ctx = {
|
||||||
|
apptId: undefined,
|
||||||
|
currentAppt: {
|
||||||
|
consulate: undefined,
|
||||||
|
date: undefined,
|
||||||
|
},
|
||||||
|
signinAttempts: undefined,
|
||||||
|
consulates: undefined,
|
||||||
|
statusMsg: undefined,
|
||||||
|
}
|
||||||
let isRunning = false;
|
let isRunning = false;
|
||||||
let msg = "";
|
let msg = "";
|
||||||
let isFoundAppointment = false;
|
let isFoundAppointment = false;
|
||||||
@ -57,10 +61,10 @@ function getFutureDate(minutes, maxRandomSeconds = 0) {
|
|||||||
return futureDate.toISOString();
|
return futureDate.toISOString();
|
||||||
}
|
}
|
||||||
|
|
||||||
function hiddenPassword(config) {
|
function hiddenPassword(cfg) {
|
||||||
return {
|
return {
|
||||||
...config,
|
...cfg,
|
||||||
password: config.password.replace(/./g, "*"),
|
password: cfg.password.replace(/./g, "*"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +91,34 @@ function diffObjects(obj1, obj2) {
|
|||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hasAllKeys(obj, keys) {
|
||||||
|
return keys.every(k => obj.hasOwnProperty(k));
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureRequiredConsulateProperties(consCtx, consCfg, frequency = 1) {
|
||||||
|
let reqCfgKeys = ["isSelected", "autoBook"];
|
||||||
|
let reqStateKeys = ["id", "bestDate", "currentDate", "nextCheckAt"];
|
||||||
|
|
||||||
|
for (let c in consCtx) {
|
||||||
|
if (!hasAllKeys(consCtx[c], reqStateKeys)) {
|
||||||
|
consCtx[c] = {
|
||||||
|
"id": consCtx[c]?.id || null,
|
||||||
|
"bestDate": consCtx[c]?.bestDate || null,
|
||||||
|
"currentDate": consCtx[c]?.currentDate || null,
|
||||||
|
"nextCheckAt": consCtx[c]?.nextCheckAt || getFutureDate(0, frequency * MINUTE),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!consCfg[c] || !hasAllKeys(consCfg[c], reqCfgKeys)) {
|
||||||
|
consCfg[c] = {
|
||||||
|
"isSelected": consCfg[c]?.isSelected || false,
|
||||||
|
"autoBook": consCfg[c]?.autoBook || false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [consCtx, consCfg];
|
||||||
|
}
|
||||||
|
|
||||||
function getPathnameParts(pathname) {
|
function getPathnameParts(pathname) {
|
||||||
let pathParts = pathname.split('/');
|
let pathParts = pathname.split('/');
|
||||||
let locale = pathParts[1] || 'en-us';
|
let locale = pathParts[1] || 'en-us';
|
||||||
@ -164,9 +196,9 @@ async function goToDashboardPage() {
|
|||||||
return isDashboardPage();
|
return isDashboardPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function enterCredentials() {
|
async function enterCredentials(username, password) {
|
||||||
document.getElementById("user_email").value = config.username;
|
document.getElementById("user_email").value = username;
|
||||||
document.getElementById("user_password").value = config.password;
|
document.getElementById("user_password").value = password;
|
||||||
let policyConfirmed = document.querySelector('[for="policy_confirmed"]');
|
let policyConfirmed = document.querySelector('[for="policy_confirmed"]');
|
||||||
if (!policyConfirmed.getElementsByTagName('input')[0].checked) {
|
if (!policyConfirmed.getElementsByTagName('input')[0].checked) {
|
||||||
policyConfirmed.click();
|
policyConfirmed.click();
|
||||||
@ -182,7 +214,6 @@ async function getAppointmentId() {
|
|||||||
if (appointments.length > 1) {
|
if (appointments.length > 1) {
|
||||||
console.log("Multiple appointments found, taking the first one");
|
console.log("Multiple appointments found, taking the first one");
|
||||||
}
|
}
|
||||||
|
|
||||||
let apptId = appointments[0].href.replace(/\D/g, "");
|
let apptId = appointments[0].href.replace(/\D/g, "");
|
||||||
return apptId;
|
return apptId;
|
||||||
}
|
}
|
||||||
@ -195,11 +226,6 @@ async function getConsulates() {
|
|||||||
if (!option.value) continue; // skip empty option
|
if (!option.value) continue; // skip empty option
|
||||||
consulatesDict[option.text] = {
|
consulatesDict[option.text] = {
|
||||||
"id": parseInt(option.value),
|
"id": parseInt(option.value),
|
||||||
"isSelected": option.selected,
|
|
||||||
"bestDate": null,
|
|
||||||
"currentDate": null,
|
|
||||||
"nextCheckAt": getFutureDate(0, getJitter(config.frequency)),
|
|
||||||
"autobook": false,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return consulatesDict;
|
return consulatesDict;
|
||||||
@ -232,7 +258,6 @@ async function getAvailableDates(consulateId) {
|
|||||||
|
|
||||||
async function filterDates(dates, currentAppt, deltaFromAppt, deltaFromNow) {
|
async function filterDates(dates, currentAppt, deltaFromAppt, deltaFromNow) {
|
||||||
let maxDate = new Date(currentAppt);
|
let maxDate = new Date(currentAppt);
|
||||||
// let maxDate = new Date("2029-09-09");
|
|
||||||
maxDate.setDate(maxDate.getDate() - deltaFromAppt);
|
maxDate.setDate(maxDate.getDate() - deltaFromAppt);
|
||||||
let minDate = new Date();
|
let minDate = new Date();
|
||||||
minDate.setDate(minDate.getDate() + deltaFromNow);
|
minDate.setDate(minDate.getDate() + deltaFromNow);
|
||||||
@ -258,91 +283,100 @@ async function runner() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isRunning = true;
|
isRunning = true;
|
||||||
// console.log('runner start');
|
|
||||||
|
|
||||||
let prev_config = Object.assign({}, config);
|
let prev_cfg = Object.assign({}, cfg);
|
||||||
|
let prev_ctx = Object.assign({}, ctx);
|
||||||
|
|
||||||
let result = await new Promise(resolve => chrome.storage.local.get(null, resolve));
|
let result = await new Promise(resolve => chrome.storage.local.get(null, resolve));
|
||||||
config.activate = result['__activate'] || false;
|
cfg.activate = result['cfg_activate'] || false;
|
||||||
config.username = result['__username'] || "";
|
cfg.username = result['cfg_username'] || "";
|
||||||
config.password = result['__password'] || "";
|
cfg.password = result['cfg_password'] || "";
|
||||||
config.frequency = parseFloat(result['__frequency'] || 1);
|
cfg.frequency = parseFloat(result['cfg_frequency'] || 1);
|
||||||
config.signinAttempts = result['__signinAttempts'] || 0;
|
cfg.consulates = result['cfg_consulates'] || {};
|
||||||
config.apptId = result['__apptId'] || null;
|
cfg.deltaAppt = result['cfg_deltaAppt'] || 1;
|
||||||
config.currentAppt = result['__currentAppt'] || { consulate: null, date: null };
|
cfg.deltaNow = result['cfg_deltaNow'] || 1;
|
||||||
config.consulates = result['__consulates'] || null;
|
|
||||||
config.deltaAppt = result['__deltaAppt'] || 1;
|
|
||||||
config.deltaNow = result['__deltaNow'] || 1;
|
|
||||||
|
|
||||||
if (prev_config.activate === null) {
|
ctx.apptId = result['ctx_apptId'] || null;
|
||||||
console.log('Reading config: ' + JSON.stringify(hiddenPassword(config)));
|
ctx.signinAttempts = result['ctx_signinAttempts'] || 0;
|
||||||
|
ctx.currentAppt = result['ctx_currentAppt'] || { consulate: null, date: null };
|
||||||
|
ctx.consulates = result['ctx_consulates'] || {};
|
||||||
|
ctx.statusMsg = result['ctx_statusMsg'] || "";
|
||||||
|
|
||||||
|
[ctx.consulates, cfg.consulates] = ensureRequiredConsulateProperties(
|
||||||
|
ctx.consulates, cfg.consulates, cfg.frequency
|
||||||
|
);
|
||||||
|
await chrome.storage.local.set({ "cfg_consulates": cfg.consulates });
|
||||||
|
await chrome.storage.local.set({ "ctx_consulates": ctx.consulates });
|
||||||
|
|
||||||
|
if (prev_cfg.activate === undefined) {
|
||||||
|
console.log('Reading config: ' + JSON.stringify(hiddenPassword(cfg)));
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let key in config) {
|
for (let key in cfg) {
|
||||||
if (config.hasOwnProperty(key)
|
if (cfg.hasOwnProperty(key)
|
||||||
&& !_.isEqual(config[key], prev_config[key])) {
|
&& !_.isEqual(cfg[key], prev_cfg[key])) {
|
||||||
msg = `Config change: ${key}`
|
msg = `Config change: ${key}`
|
||||||
if (key === 'password') {
|
if (key === 'password') {
|
||||||
msg += ', ******** => ********';
|
msg += ', ******** => ********';
|
||||||
} else if (key === 'consulates') {
|
} else if (key === 'consulates') {
|
||||||
msg += `, ${JSON.stringify(diffObjects(config[key], prev_config[key]))}`;
|
msg += `, ${JSON.stringify(diffObjects(cfg[key], prev_cfg[key]))}`;
|
||||||
} else {
|
} else {
|
||||||
msg += `, ${prev_config[key]} => ${config[key]}`;
|
msg += `, ${prev_cfg[key]} => ${cfg[key]}`;
|
||||||
}
|
}
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
|
|
||||||
// reduce wait times for consulates if frequency is increased
|
// reduce wait times for consulates if frequency is increased
|
||||||
if (key === 'frequency') {
|
if (key === 'frequency') {
|
||||||
let wasChanged = false;
|
let wasChanged = false;
|
||||||
for (let consulate in config.consulates) {
|
for (let c in ctx.consulates) {
|
||||||
let newNextCheckAt = getFutureDate(config.frequency, getJitter(config.frequency));
|
let newNextCheckAt = getFutureDate(cfg.frequency, getJitter(cfg.frequency));
|
||||||
if (config.consulates[consulate].nextCheckAt > newNextCheckAt) {
|
if (ctx.consulates[c].nextCheckAt > newNextCheckAt) {
|
||||||
config.consulates[consulate].nextCheckAt = newNextCheckAt;
|
console.log(`Reducing wait time for ${c} from ${ctx.consulates[c].nextCheckAt} to ${newNextCheckAt}`);
|
||||||
|
ctx.consulates[c].nextCheckAt = newNextCheckAt;
|
||||||
wasChanged = true;
|
wasChanged = true;
|
||||||
console.log(`Reducing wait time for ${consulate} from ${config.consulates[consulate].nextCheckAt} to ${newNextCheckAt}`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO maybe causes additional requests
|
// TODO maybe causes additional requests
|
||||||
if (wasChanged) {
|
if (wasChanged) {
|
||||||
await chrome.storage.local.set({ "__consulates": config.consulates });
|
await chrome.storage.local.set({ "ctx_consulates": ctx.consulates });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'activate') {
|
if (key === 'activate') {
|
||||||
if (config[key]) {
|
if (cfg[key]) {
|
||||||
console.log('Activating extension');
|
console.log('Activating extension');
|
||||||
} else {
|
} else {
|
||||||
console.log('Deactivating extension');
|
console.log('Deactivating extension');
|
||||||
await chrome.storage.local.set({ "__status": "inactive" });
|
await chrome.storage.local.set({ "ctx_statusMsg": "inactive" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear signin attempts when credentials are changed
|
// clear signin attempts when credentials are changed
|
||||||
if (key === 'username' && config[key]
|
if (key === 'username' && cfg[key]
|
||||||
|| key === 'password' && config[key]) {
|
|| key === 'password' && cfg[key]) {
|
||||||
config.signinAttempts = 0;
|
ctx.signinAttempts = 0;
|
||||||
await chrome.storage.local.set({ "__signinAttempts": config.signinAttempts });
|
await chrome.storage.local.set({ "ctx_signinAttempts": ctx.signinAttempts });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.activate) {
|
if (!cfg.activate) {
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.username === "" || config.password === "") {
|
if (cfg.username === "" || cfg.password === "") {
|
||||||
console.log('Username or password is empty');
|
console.log('Username or password is empty');
|
||||||
await chrome.storage.local.set({ "__status": "missing credentials" });
|
await chrome.storage.local.set({ "ctx_statusMsg": "missing credentials" });
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.frequency <= 0) {
|
if (cfg.frequency <= 0) {
|
||||||
console.log('Frequency is 0 or negative');
|
console.log('Frequency is 0 or negative');
|
||||||
await chrome.storage.local.set({ "__status": "invalid frequency" });
|
await chrome.storage.local.set({ "ctx_statusMsg": "invalid frequency" });
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -353,7 +387,7 @@ async function runner() {
|
|||||||
if (currentHourUTC >= 23 || currentHourUTC < 9) {
|
if (currentHourUTC >= 23 || currentHourUTC < 9) {
|
||||||
// Continue running the code
|
// Continue running the code
|
||||||
} else {
|
} else {
|
||||||
await chrome.storage.local.set({ "__status": "not operational hours" });
|
await chrome.storage.local.set({ "ctx_statusMsg": "not operational hours" });
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -377,7 +411,7 @@ async function runner() {
|
|||||||
if (!await goToSignInPage()) {
|
if (!await goToSignInPage()) {
|
||||||
msg = 'Failed to go to sign in page';
|
msg = 'Failed to go to sign in page';
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
await chrome.storage.local.set({ "__status": msg });
|
await chrome.storage.local.set({ "ctx_statusMsg": msg });
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@ -386,23 +420,23 @@ async function runner() {
|
|||||||
|
|
||||||
else if (isSignInPage()) {
|
else if (isSignInPage()) {
|
||||||
// Prevent brute forcing
|
// Prevent brute forcing
|
||||||
if (config.signinAttempts >= MAX_SIGNIN_ATTEMPTS) {
|
if (ctx.signinAttempts >= MAX_SIGNIN_ATTEMPTS) {
|
||||||
await chrome.storage.local.set({ "__status": "too many sign in attempts" });
|
await chrome.storage.local.set({ "ctx_statusMsg": "too many sign in attempts" });
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign in
|
// Sign in
|
||||||
msg = 'Signing in attempt: ' + config.signinAttempts;
|
msg = 'Signing in attempt: ' + ctx.signinAttempts;
|
||||||
console.log(msg)
|
console.log(msg)
|
||||||
await chrome.storage.local.set({ "__status": msg });
|
await chrome.storage.local.set({ "ctx_statusMsg": msg });
|
||||||
let signedIn = await enterCredentials();
|
let signedIn = await enterCredentials();
|
||||||
config.signinAttempts += 1;
|
ctx.signinAttempts += 1;
|
||||||
await chrome.storage.local.set({ "__signinAttempts": config.signinAttempts });
|
await chrome.storage.local.set({ "ctx_signinAttempts": ctx.signinAttempts });
|
||||||
if (!signedIn) {
|
if (!signedIn) {
|
||||||
msg = 'Failed to sign in';
|
msg = 'Failed to sign in';
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
await chrome.storage.local.set({ "__status": msg });
|
await chrome.storage.local.set({ "ctx_statusMsg": msg });
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@ -411,31 +445,31 @@ async function runner() {
|
|||||||
|
|
||||||
else if (isDashboardPage()) {
|
else if (isDashboardPage()) {
|
||||||
// reset signin attempts when successfully logged in
|
// reset signin attempts when successfully logged in
|
||||||
config.signinAttempts = 0;
|
ctx.signinAttempts = 0;
|
||||||
await chrome.storage.local.set({ "__status": "fetching appointment info" });
|
await chrome.storage.local.set({ "ctx_statusMsg": "fetching appointment info" });
|
||||||
await chrome.storage.local.set({ "__signinAttempts": config.signinAttempts });
|
await chrome.storage.local.set({ "ctx_signinAttempts": ctx.signinAttempts });
|
||||||
|
|
||||||
// get appointmentId
|
// get appointmentId
|
||||||
if (!config.apptId) {
|
if (!ctx.apptId) {
|
||||||
config.apptId = await getAppointmentId();
|
ctx.apptId = await getAppointmentId();
|
||||||
if (config.apptId) {
|
if (ctx.apptId) {
|
||||||
console.log(`Appointment ID: ${config.apptId}`);
|
console.log(`Appointment ID: ${ctx.apptId}`);
|
||||||
await chrome.storage.local.set({ "__apptId": config.apptId });
|
await chrome.storage.local.set({ "ctx_apptId": ctx.apptId });
|
||||||
} else {
|
} else {
|
||||||
msg = 'No appointments found';
|
msg = 'No appointments found';
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
await chrome.storage.local.set({ "__status": msg });
|
await chrome.storage.local.set({ "ctx_statusMsg": msg });
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get current appointment date
|
// get current appointment date
|
||||||
let apptInfoCard = document.querySelector("p.consular-appt [href*='" + config.apptId + "']").parentNode.parentNode.parentNode
|
let apptInfoCard = document.querySelector("p.consular-appt [href*='" + ctx.apptId + "']").parentNode.parentNode.parentNode
|
||||||
if (!apptInfoCard.querySelector("h4").innerText.match(/Attend Appointment/)) {
|
if (!apptInfoCard.querySelector("h4").innerText.match(/Attend Appointment/)) {
|
||||||
msg = 'Appointment not available';
|
msg = 'Appointment not available';
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
await chrome.storage.local.set({ "__status": msg });
|
await chrome.storage.local.set({ "ctx_statusMsg": msg });
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -443,14 +477,19 @@ async function runner() {
|
|||||||
let apptConsulate = (apptInfo.match(/at (\w+)/) || [])[1];
|
let apptConsulate = (apptInfo.match(/at (\w+)/) || [])[1];
|
||||||
let apptDate = new Date(apptInfo.match(/\d{1,2} \w+, \d{4}/)[0]);
|
let apptDate = new Date(apptInfo.match(/\d{1,2} \w+, \d{4}/)[0]);
|
||||||
apptDate = apptDate.toISOString().slice(0, 10);
|
apptDate = apptDate.toISOString().slice(0, 10);
|
||||||
if (apptDate && apptConsulate
|
if (!apptDate || !apptConsulate) {
|
||||||
&& (apptDate != config.currentAppt.date
|
msg = 'Failed to fetch appointment date or consulate';
|
||||||
|| apptConsulate != config.currentAppt.consulate)) {
|
console.log(msg);
|
||||||
|
await chrome.storage.local.set({ "ctx_statusMsg": msg });
|
||||||
|
isRunning = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apptDate != ctx.currentAppt.date || apptConsulate != ctx.currentAppt.consulate) {
|
||||||
console.log(`New appointment date: ${apptDate} at ${apptConsulate},
|
console.log(`New appointment date: ${apptDate} at ${apptConsulate},
|
||||||
old: ${config.currentAppt.consulate} at ${config.currentAppt.date}`);
|
old: ${ctx.currentAppt.consulate} at ${ctx.currentAppt.date}`);
|
||||||
config.currentAppt.date = apptDate;
|
ctx.currentAppt = { consulate: apptConsulate, date: apptDate };
|
||||||
config.currentAppt.consulate = apptConsulate;
|
await chrome.storage.local.set({ "ctx_currentAppt": ctx.currentAppt });
|
||||||
await chrome.storage.local.set({ "__currentAppt": config.currentAppt });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// go to appointment page
|
// go to appointment page
|
||||||
@ -462,14 +501,13 @@ async function runner() {
|
|||||||
|
|
||||||
else if (isAppointmentPage()) {
|
else if (isAppointmentPage()) {
|
||||||
// if no apptDate, fetch it from dashboard page
|
// if no apptDate, fetch it from dashboard page
|
||||||
if (!config.currentAppt.date) {
|
if (!ctx.currentAppt.date) {
|
||||||
console.log('No appointment date is set, going back to dashboard');
|
console.log('No appointment date is set, going back to dashboard');
|
||||||
await goToDashboardPage();
|
await goToDashboardPage();
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// await chrome.storage.local.set({ "__status": "fetching consulates" });
|
|
||||||
let applicantForm = document.querySelector('form[action*="' + window.location.pathname + '"]');
|
let applicantForm = document.querySelector('form[action*="' + window.location.pathname + '"]');
|
||||||
if (applicantForm && applicantForm.method.toLowerCase() == "get") {
|
if (applicantForm && applicantForm.method.toLowerCase() == "get") {
|
||||||
applicantForm.submit();
|
applicantForm.submit();
|
||||||
@ -478,21 +516,40 @@ async function runner() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO maybe it's a rare case
|
||||||
if (!document.getElementById("consulate_date_time")) {
|
if (!document.getElementById("consulate_date_time")) {
|
||||||
msg = 'No available appointments';
|
msg = 'No available appointments';
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
await chrome.storage.local.set({ "__status": msg });
|
await chrome.storage.local.set({ "ctx_statusMsg": msg });
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!config.consulates) {
|
if (!ctx.consulates || Object.keys(ctx.consulates).length == 0) {
|
||||||
config.consulates = await getConsulates();
|
await chrome.storage.local.set({ "ctx_statusMsg": "Fetching consulates" });
|
||||||
await chrome.storage.local.set({ "__consulates": config.consulates });
|
ctx.consulates = await getConsulates();
|
||||||
}
|
if (!ctx.consulates || Object.keys(ctx.consulates).length == 0) {
|
||||||
if (!config.consulates) {
|
msg = "No consulates found";
|
||||||
console.log('No consulates found');
|
console.log(msg);
|
||||||
await chrome.storage.local.set({ "__status": "no consulates found" });
|
await chrome.storage.local.set({ "ctx_statusMsg": msg });
|
||||||
|
sendNotification(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ctx.consulates, cfg.consulates] = ensureRequiredConsulateProperties(
|
||||||
|
ctx.consulates, cfg.consulates, cfg.frequency
|
||||||
|
);
|
||||||
|
|
||||||
|
// if no consulates are selected, select one which we have appointment with
|
||||||
|
let selectedConsulates = Object.keys(ctx.consulates).filter(c => cfg.consulates[c].isSelected);
|
||||||
|
if (selectedConsulates.length == 0) {
|
||||||
|
for (let c in cfg.consulates) {
|
||||||
|
if (c === ctx.currentAppt.consulate) {
|
||||||
|
cfg.consulates[c].isSelected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await chrome.storage.local.set({ "cfg_consulates": cfg.consulates });
|
||||||
|
await chrome.storage.local.set({ "ctx_consulates": ctx.consulates });
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -501,38 +558,38 @@ async function runner() {
|
|||||||
// document.querySelector("#appointments_asc_appointment_facility_id [selected]").innerText
|
// document.querySelector("#appointments_asc_appointment_facility_id [selected]").innerText
|
||||||
|
|
||||||
// for each selected consulate check available dates
|
// for each selected consulate check available dates
|
||||||
let selectedConsulates = Object.keys(config.consulates).filter(c => config.consulates[c].isSelected);
|
let selectedConsulates = Object.keys(ctx.consulates).filter(c => cfg.consulates[c].isSelected);
|
||||||
if (selectedConsulates.length == 0) {
|
if (selectedConsulates.length == 0) {
|
||||||
msg = 'No selected consulates found';
|
msg = 'No selected consulates found';
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
await chrome.storage.local.set({ "__status": msg });
|
await chrome.storage.local.set({ "ctx_statusMsg": msg });
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let processedConsulates = 0;
|
let processedConsulates = 0;
|
||||||
for (let consulate of selectedConsulates) {
|
for (let c of selectedConsulates) {
|
||||||
// only one consulate per run
|
// only one consulate per run
|
||||||
if (processedConsulates > 0) {
|
if (processedConsulates > 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// skip if not time to check
|
// skip if not time to check
|
||||||
if (config.consulates[consulate].nextCheckAt > new Date().toISOString()) {
|
if (ctx.consulates[c].nextCheckAt > new Date().toISOString()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
processedConsulates += 1;
|
processedConsulates += 1;
|
||||||
|
|
||||||
msg = `Checking dates for ${consulate}`;
|
msg = `Checking dates for ${c}`;
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
await chrome.storage.local.set({ "__status": msg });
|
await chrome.storage.local.set({ "ctx_statusMsg": msg });
|
||||||
let availDates = await getAvailableDates(config.consulates[consulate].id);
|
let availDates = await getAvailableDates(ctx.consulates[c].id);
|
||||||
config.consulates[consulate].nextCheckAt = getFutureDate(config.frequency, getJitter(config.frequency));
|
ctx.consulates[c].nextCheckAt = getFutureDate(cfg.frequency, getJitter(cfg.frequency));
|
||||||
|
|
||||||
if (!availDates) {
|
if (!availDates) {
|
||||||
msg = `Failed to fetch available dates in ${consulate}`;
|
msg = `Failed to fetch available dates in ${c}`;
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
await chrome.storage.local.set({ "__status": msg });
|
await chrome.storage.local.set({ "ctx_statusMsg": msg });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,61 +600,60 @@ async function runner() {
|
|||||||
let currentMinuteUTC = now.getUTCMinutes();
|
let currentMinuteUTC = now.getUTCMinutes();
|
||||||
|
|
||||||
if (availDates.length == 0) {
|
if (availDates.length == 0) {
|
||||||
msg = `No available dates in ${consulate}, probably banned`;
|
msg = `No available dates in ${c}, probably banned`;
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
await chrome.storage.local.set({ "__status": msg });
|
await chrome.storage.local.set({ "ctx_statusMsg": msg });
|
||||||
|
|
||||||
// Only set SOFT_BAN_TIMEOUT if it's not the first 5 minutes of 23pm UTC
|
// Only set SOFT_BAN_TIMEOUT if it's not the first 5 minutes of 23pm UTC
|
||||||
if (!(currentHourUTC === 23 && currentMinuteUTC < 5)) {
|
if (!(currentHourUTC === 23 && currentMinuteUTC < 5)) {
|
||||||
config.consulates[consulate].nextCheckAt = getFutureDate(SOFT_BAN_TIMEOUT, getJitter(config.frequency));
|
ctx.consulates[c].nextCheckAt = getFutureDate(SOFT_BAN_TIMEOUT, getJitter(cfg.frequency));
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = `Available dates for ${consulate}: ${availDates.slice(0, 5)}`;
|
msg = `Available dates for ${c}: ${availDates.slice(0, 5)}`;
|
||||||
if (availDates.length > 5) {
|
if (availDates.length > 5) {
|
||||||
msg += ` and ${availDates.length - 10} more`;
|
msg += ` and ${availDates.length - 10} more`;
|
||||||
}
|
}
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
config.consulates[consulate].currentDate = availDates[0];
|
ctx.consulates[c].currentDate = availDates[0];
|
||||||
if (!config.consulates[consulate].bestDate
|
if (!ctx.consulates[c].bestDate || availDates[0] < ctx.consulates[c].bestDate) {
|
||||||
|| availDates[0] < config.consulates[consulate].bestDate) {
|
console.log(`New record for ${c}: ${availDates[0]}`);
|
||||||
console.log(`New record for ${consulate}: ${availDates[0]}`);
|
ctx.consulates[c].bestDate = availDates[0];
|
||||||
config.consulates[consulate].bestDate = availDates[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter dates with our requests
|
// filter dates with our requests
|
||||||
let filteredDates = await filterDates(availDates, config.currentAppt.date, config.deltaAppt, config.deltaNow);
|
let filteredDates = await filterDates(availDates, ctx.currentAppt.date, cfg.deltaAppt, cfg.deltaNow);
|
||||||
if (!filteredDates.length) {
|
if (!filteredDates.length) {
|
||||||
console.log(`No better dates in ${consulate}, currently available ${availDates[0]}`);
|
console.log(`No better dates in ${c}, currently available ${availDates[0]}`);
|
||||||
await chrome.storage.local.set({ "__status": `No better dates in ${consulate}`});
|
await chrome.storage.local.set({ "ctx_statusMsg": `no better dates in ${c}`});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Dates worth rescheduling in ${consulate}: ${filteredDates}`);
|
console.log(`Dates worth rescheduling in ${c}: ${filteredDates}`);
|
||||||
let chosenDate = filteredDates[0];
|
let chosenDate = filteredDates[0];
|
||||||
await chrome.storage.local.set({ "__status": `Found in ${consulate} better date ${chosenDate}`});
|
await chrome.storage.local.set({ "ctx_statusMsg": `Found in ${c} better date ${chosenDate}`});
|
||||||
|
|
||||||
// fill date in reschedule form
|
// fill date in reschedule form
|
||||||
await delay(PAGE_WAIT_TIME);
|
await delay(PAGE_WAIT_TIME);
|
||||||
document.getElementById("appointments_consulate_appointment_date").value = chosenDate;
|
document.getElementById("appointments_consulate_appointment_date").value = chosenDate;
|
||||||
document.getElementById("appointments_consulate_appointment_time").innerHTML = "<option></option>"
|
document.getElementById("appointments_consulate_appointment_time").innerHTML = "<option></option>"
|
||||||
|
|
||||||
let availTimes = await getAvailableTimes(config.consulates[consulate].id, chosenDate);
|
let availTimes = await getAvailableTimes(ctx.consulates[c].id, chosenDate);
|
||||||
if (!availTimes) {
|
if (!availTimes) {
|
||||||
msg = `Failed to fetch available timeslots in ${consulate} at ${chosenDate}`;
|
msg = `Failed to fetch available timeslots in ${c} at ${chosenDate}`;
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
await chrome.storage.local.set({ "__status": msg});
|
await chrome.storage.local.set({ "ctx_statusMsg": msg});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (availTimes.length == 0) {
|
if (availTimes.length == 0) {
|
||||||
msg = `No timeslots in ${consulate} at ${chosenDate}`;
|
msg = `No timeslots in ${c} at ${chosenDate}`;
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
await chrome.storage.local.set({ "__status": msg});
|
await chrome.storage.local.set({ "ctx_statusMsg": msg});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
console.log(`Available timeslots in ${consulate} at ${chosenDate}: ${availTimes}`);
|
console.log(`Available timeslots in ${c} at ${chosenDate}: ${availTimes}`);
|
||||||
let chosenTime = availTimes[0];
|
let chosenTime = availTimes[0];
|
||||||
|
|
||||||
// fill timeslot in reschedule form
|
// fill timeslot in reschedule form
|
||||||
@ -611,28 +667,29 @@ async function runner() {
|
|||||||
document.getElementById("appointments_submit").removeAttribute("disabled");
|
document.getElementById("appointments_submit").removeAttribute("disabled");
|
||||||
document.getElementById("appointments_submit").click();
|
document.getElementById("appointments_submit").click();
|
||||||
|
|
||||||
msg = `Found better appointment in ${consulate} at ${chosenDate} ${chosenTime}`;
|
msg = `Found better appointment in ${c} at ${chosenDate} ${chosenTime}`;
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
await sendNotification(msg);
|
await sendNotification(msg);
|
||||||
|
|
||||||
if (!config.consulates[consulate].autobook) {
|
if (!cfg.consulates[c].autoBook) {
|
||||||
isFoundAppointment = true;
|
isFoundAppointment = true;
|
||||||
} else {
|
} else {
|
||||||
await delay(PAGE_WAIT_TIME);
|
await delay(PAGE_WAIT_TIME);
|
||||||
msg = `Auto booking in ${consulate} at ${chosenDate} ${chosenTime}`;
|
msg = `Auto booking in ${c} at ${chosenDate} ${chosenTime}`;
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
await sendNotification(msg);
|
await sendNotification(msg);
|
||||||
document.querySelector(".reveal-overlay:last-child [data-reveal] .button.alert").click();
|
document.querySelector(".reveal-overlay:last-child [data-reveal] .button.alert").click();
|
||||||
}
|
}
|
||||||
} // end consulates loop
|
} // end consulates loop
|
||||||
|
|
||||||
for (let consulate in config.consulates) {
|
for (let c in ctx.consulates) {
|
||||||
if (!prev_config?.consulates?.[consulate]) continue;
|
if (!prev_ctx?.consulates?.[c]) continue;
|
||||||
if (config.consulates[consulate].nextCheckAt != prev_config.consulates[consulate].nextCheckAt) {
|
if (ctx.consulates[c].nextCheckAt != prev_ctx.consulates[c].nextCheckAt) {
|
||||||
console.log(`Next check for ${consulate} at ${config.consulates[consulate].nextCheckAt}`);
|
console.log(`Next check for ${c} at ${ctx.consulates[c].nextCheckAt}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await chrome.storage.local.set({ "__consulates": config.consulates });
|
await chrome.storage.local.set({ "cfg_consulates": cfg.consulates });
|
||||||
|
await chrome.storage.local.set({ "ctx_consulates": ctx.consulates });
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -640,13 +697,13 @@ async function runner() {
|
|||||||
else if (isConfirmationPage) {
|
else if (isConfirmationPage) {
|
||||||
// go back to dashboard after successful reschedule
|
// go back to dashboard after successful reschedule
|
||||||
await delay(PAGE_WAIT_TIME);
|
await delay(PAGE_WAIT_TIME);
|
||||||
config.currentAppt = { consulate: null, date: null};
|
ctx.currentAppt = { consulate: null, date: null};
|
||||||
await chrome.storage.local.set({"__currentAppt": config.currentAppt});
|
await chrome.storage.local.set({"ctx_currentAppt": ctx.currentAppt});
|
||||||
console.log('Rescheduled successfully');
|
console.log('Rescheduled successfully');
|
||||||
|
|
||||||
// switch off autobook for all consulates after successful reschedule
|
// switch off autoBook for all consulates after successful reschedule
|
||||||
for (let consulate in config.consulates) {
|
for (let c in cfg.consulates) {
|
||||||
config.consulates[consulate].autobook = false;
|
cfg.consulates[c].autoBook = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await goToDashboardPage();
|
await goToDashboardPage();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user