-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
108 lines (95 loc) · 4.49 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { launch, TimeoutError } from 'puppeteer';
import { sendPushoverNotification } from './notify.js';
import dotenv from 'dotenv';
import path from 'path';
const env = process.env.NODE_ENV || 'development';
const sucessMessage = 'Appointments available! Go to https://bit.ly/4cFXN5E to schedule your appointment';
const failureMessage = 'No appointment slots available.';
const timeoutMessage = 'Request timed out.';
const maxRetries = 3;
const timeOut = 120000; // 2 minutes
dotenv.config({ path: path.resolve(process.cwd(), `.env.${env}`) });
const checkAppointmentAvailability = async () => {
// Launch the browser
const browser = await launch({
headless: env !== 'development',
timeout: 0, // This disables the default timeout for browser launch.
args: ['--no-sandbox', '--disable-setuid-sandbox', '--incognito'],
protocolTimeout: timeOut,
});
try {
// hacky workarround, new page doesn't use incognito, so we get the default page and use that.
const pages = await browser.pages();
const page = pages[0];
// Navigate to the URL
await page.goto('https://www.exteriores.gob.es/Consulados/santiagodechile/es/ServiciosConsulares/Paginas/CitaPrevia.aspx');
// Click on the "Solicitud de Cita" link
const citaLink = 'https://www.citaconsular.es/es/hosteds/widgetdefault/24e329baaaf932b93de4fc7f95bc53535';
await page.waitForSelector(`a[href="${citaLink}"]`);
await page.click(`a[href="${citaLink}"]`);
// Wait for the new page or tab to load
const newPagePromise = new Promise(x => browser.once('targetcreated', target => x(target.page())));
const newPage = await newPagePromise;
// Handle the alert by accepting it on the new page
newPage.on('dialog', async dialog => {
await dialog.accept();
});
// Wait for the button to be available and visible
await newPage.waitForSelector('#idCaptchaButton', { visible: true, timeout: timeOut });
// Click on the "Continue / Continuar" button
await newPage.click('#idCaptchaButton');
// Check for availability
await newPage.waitForSelector('#idListServices', { visible: true, timeout: timeOut });
const appointmentAvailable = await newPage.evaluate(() => {
const widget = document.querySelector('#idListServices');
return widget && widget.textContent.includes('LEY MEMORIA');
});
await browser.close();
return appointmentAvailable;
} catch (error) {
browser.close(); // make sure we close even if we error, to avoid OOM
throw error;
}
}
const checkAppointmentAvailabilityAndNotify = async (maxRetries) => {
let retries = maxRetries;
let startTime;
while (retries > 0) {
try {
startTime = Date.now();
console.log(`Starting attempt #${maxRetries - retries + 1}`);
const appointmentAvailable = await checkAppointmentAvailability();
if (appointmentAvailable) {
console.log('Appointment slots available!');
await sendPushoverNotification(sucessMessage, 'Appointment Alert', 2);
break; // Exit the loop if successful
} else {
console.log('No appointment slots available.');
await sendPushoverNotification(failureMessage, 'Appointment Alert', -2);
break; // Exit the loop if unsuccessful
}
} catch (error) {
if (error instanceof TimeoutError) {
console.log('A timeout error occurred:', error.message);
retries--;
if (retries === 0) {
console.log('Max retries reached, no more attempts.');
await sendPushoverNotification(timeoutMessage, 'Appointment Alert', -2);
}
} else {
console.error('An unexpected error occurred:', error);
throw error;
}
} finally {
const endTime = Date.now();
console.log(`Time taken: ${(endTime - startTime) / 1000} seconds`);
}
}
}
(async () => {
console.log('Starting App');
console.log('Environment:', process.env.NODE_ENV);
const spainTime = new Intl.DateTimeFormat('en-GB', { timeZone: 'Europe/Madrid', timeStyle: 'long', dateStyle: 'long' }).format(new Date());
console.log('Current time in Spain:', spainTime);
await checkAppointmentAvailabilityAndNotify(maxRetries);
})();