Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d4c8835e9b | |||
| 776b0afdab | |||
| c428e4ab11 | |||
| d19b9ced8f | |||
| 4a506de6fe | |||
| 2070cdb30a | |||
| fcb9f9dbf3 | |||
| 094e2d2b81 |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "not-a-rescheduler",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.4",
|
||||
"permissions": [ "storage", "tabs", "activeTab", "notifications", "declarativeContent" ],
|
||||
"content_scripts": [
|
||||
{
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<label for="frequency">Check frequency<br>(every <span id="frequency_info">N</span> minutes)</label>
|
||||
</div>
|
||||
<div class="col">
|
||||
<input type="range" id="frequency" name="frequency" min="1" max="15" step="1">
|
||||
<input type="range" id="frequency" name="frequency" min="0.5" max="10" step="0.5">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -75,12 +75,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- consulates -->
|
||||
<div class="row">
|
||||
<div class="col">Consulates:</div>
|
||||
</div>
|
||||
<div id="consulatesConfig">
|
||||
</div>
|
||||
<!-- current appointment -->
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Current appointment: <span id="currApptConsulate">somewhere</span>, <span id="currApptDate">some time</span>
|
||||
@@ -91,6 +86,12 @@
|
||||
Status: <span class="smooth-text" id="status">Inactive</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- consulates -->
|
||||
<div id="consulatesConfig">
|
||||
</div>
|
||||
|
||||
<!-- buttons -->
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<button type="button" class="btn btn-info btn-sm" id="showConfigButton">Config</button>
|
||||
|
||||
@@ -107,7 +107,7 @@ function smoothTextChange(element, newText) {
|
||||
<th scope="col">City</th>
|
||||
<th scope="col" style="white-space: nowrap;">Current Date</th>
|
||||
<th scope="col" style="white-space: nowrap;">Best Date</th>
|
||||
<th scope="col">Autobook</th>
|
||||
<th scope="col">Book</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@@ -5,6 +5,7 @@ const pathnameRegex = /^\/\w{2}-\w{2}\/n?iv/;
|
||||
const MAX_SIGNIN_ATTEMPTS = 1;
|
||||
const PAGE_WAIT_TIME = 3792;
|
||||
const MINUTE = 60;
|
||||
const RANDOM_JITTER = 0.1;
|
||||
const SOFT_BAN_TIMEOUT = 27;
|
||||
const NOTIF_CHANNEL = "snegov_test"
|
||||
|
||||
@@ -44,11 +45,15 @@ function getRandomInt(max) {
|
||||
return Math.floor(Math.random() * Math.floor(max));
|
||||
}
|
||||
|
||||
|
||||
function getJitter(frequency) {
|
||||
return frequency * MINUTE * RANDOM_JITTER;
|
||||
}
|
||||
|
||||
function getFutureDate(minutes, maxRandomSeconds = 0) {
|
||||
// return date some amount of minutes in future plus random amount of seconds
|
||||
let futureDate = new Date();
|
||||
futureDate.setMinutes(futureDate.getMinutes() + minutes);
|
||||
futureDate.setSeconds(futureDate.getSeconds() + getRandomInt(maxRandomSeconds));
|
||||
futureDate.setSeconds(futureDate.getSeconds() + minutes * MINUTE + getRandomInt(maxRandomSeconds));
|
||||
return futureDate.toISOString();
|
||||
}
|
||||
|
||||
@@ -86,7 +91,7 @@ function getPathnameParts(pathname) {
|
||||
let pathParts = pathname.split('/');
|
||||
let locale = pathParts[1] || 'en-us';
|
||||
let visaType = pathParts[2] || 'niv';
|
||||
return { locale, visaType };
|
||||
return [ locale, visaType ];
|
||||
}
|
||||
|
||||
function isSignInPage() {
|
||||
@@ -124,10 +129,8 @@ async function handleHttpError(e) {
|
||||
console.log(msg);
|
||||
await sendNotification(msg);
|
||||
await logOut();
|
||||
return null;
|
||||
} else {
|
||||
console.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,7 +198,7 @@ async function getConsulates() {
|
||||
"isSelected": option.selected,
|
||||
"bestDate": null,
|
||||
"currentDate": null,
|
||||
"nextCheckAt": getFutureDate(0, config.frequency * MINUTE),
|
||||
"nextCheckAt": getFutureDate(0, getJitter(config.frequency)),
|
||||
"autobook": false,
|
||||
};
|
||||
}
|
||||
@@ -203,15 +206,27 @@ async function getConsulates() {
|
||||
}
|
||||
|
||||
async function getAvailableDates(consulateId) {
|
||||
let uri = window.location.pathname + `/days/${consulateId}.json?appointments[expedite]=false`
|
||||
let dates = fetch(uri, { headers: { "x-requested-with": "XMLHttpRequest" }})
|
||||
let addressUri = window.location.pathname + `/address/${consulateId}`
|
||||
fetch(addressUri, { headers: { "x-requested-with": "XMLHttpRequest" } })
|
||||
.catch(error => console.error('Error:', error));
|
||||
|
||||
let datesUri = window.location.pathname + `/days/${consulateId}.json?appointments[expedite]=false`
|
||||
let dates = fetch(datesUri, { headers: {
|
||||
"x-requested-with": "XMLHttpRequest",
|
||||
"accept": "application/json, text/javascript, */*; q=0.01",
|
||||
// "cache-control": "no-cache",
|
||||
}})
|
||||
.then(d => d.json())
|
||||
.catch(async e => {
|
||||
await handleHttpError(e);
|
||||
throw e;
|
||||
})
|
||||
.then(data => {
|
||||
let dateList = data.map(item => item.date);
|
||||
dateList.sort();
|
||||
return dateList;
|
||||
})
|
||||
.catch(async e => handleHttpError(e));
|
||||
.catch(e => null);
|
||||
return dates;
|
||||
}
|
||||
|
||||
@@ -229,8 +244,12 @@ async function getAvailableTimes(consulateId, date) {
|
||||
let uri = window.location.pathname + `/times/${consulateId}.json?date=${date}&appointments[expedite]=false`
|
||||
let times = await fetch(uri, { headers: { "x-requested-with": "XMLHttpRequest" } })
|
||||
.then(d => d.json())
|
||||
.catch(async e => {
|
||||
await handleHttpError(e);
|
||||
throw e;
|
||||
})
|
||||
.then(data => data.available_times)
|
||||
.catch(e => handleHttpError(e));
|
||||
.catch(e => null);
|
||||
return times;
|
||||
}
|
||||
|
||||
@@ -247,7 +266,7 @@ async function runner() {
|
||||
config.activate = result['__activate'] || false;
|
||||
config.username = result['__username'] || "";
|
||||
config.password = result['__password'] || "";
|
||||
config.frequency = parseInt(result['__frequency'] || 1);
|
||||
config.frequency = parseFloat(result['__frequency'] || 1);
|
||||
config.signinAttempts = result['__signinAttempts'] || 0;
|
||||
config.apptId = result['__apptId'] || null;
|
||||
config.currentAppt = result['__currentAppt'] || { consulate: null, date: null };
|
||||
@@ -278,7 +297,7 @@ async function runner() {
|
||||
if (key === 'frequency') {
|
||||
let wasChanged = false;
|
||||
for (let consulate in config.consulates) {
|
||||
let newNextCheckAt = getFutureDate(config.frequency, 10);
|
||||
let newNextCheckAt = getFutureDate(config.frequency, getJitter(config.frequency));
|
||||
if (config.consulates[consulate].nextCheckAt > newNextCheckAt) {
|
||||
config.consulates[consulate].nextCheckAt = newNextCheckAt;
|
||||
wasChanged = true;
|
||||
@@ -334,6 +353,7 @@ async function runner() {
|
||||
if (currentHourUTC >= 23 || currentHourUTC < 9) {
|
||||
// Continue running the code
|
||||
} else {
|
||||
await chrome.storage.local.set({ "__status": "not operational hours" });
|
||||
isRunning = false;
|
||||
return;
|
||||
}
|
||||
@@ -507,7 +527,7 @@ async function runner() {
|
||||
console.log(msg);
|
||||
await chrome.storage.local.set({ "__status": msg });
|
||||
let availDates = await getAvailableDates(config.consulates[consulate].id);
|
||||
config.consulates[consulate].nextCheckAt = getFutureDate(config.frequency, 10);
|
||||
config.consulates[consulate].nextCheckAt = getFutureDate(config.frequency, getJitter(config.frequency));
|
||||
|
||||
if (!availDates) {
|
||||
msg = `Failed to fetch available dates in ${consulate}`;
|
||||
@@ -529,7 +549,7 @@ async function runner() {
|
||||
|
||||
// Only set SOFT_BAN_TIMEOUT if it's not the first 5 minutes of 23pm UTC
|
||||
if (!(currentHourUTC === 23 && currentMinuteUTC < 5)) {
|
||||
config.consulates[consulate].nextCheckAt = getFutureDate(SOFT_BAN_TIMEOUT, 10);
|
||||
config.consulates[consulate].nextCheckAt = getFutureDate(SOFT_BAN_TIMEOUT, getJitter(config.frequency));
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user