-
Notifications
You must be signed in to change notification settings - Fork 57
/
index.js
109 lines (82 loc) · 2.87 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
109
const puppeteer = require('puppeteer');
const {parseISO, compareAsc, isBefore, format} = require('date-fns')
require('dotenv').config();
const {delay, sendEmail, logStep} = require('./utils');
const {siteInfo, loginCred, IS_PROD, NEXT_SCHEDULE_POLL, MAX_NUMBER_OF_POLL, NOTIFY_ON_DATE_BEFORE} = require('./config');
let isLoggedIn = false;
let maxTries = MAX_NUMBER_OF_POLL
const login = async (page) => {
logStep('logging in');
await page.goto(siteInfo.LOGIN_URL);
const form = await page.$("form#sign_in_form");
const email = await form.$('input[name="user[email]"]');
const password = await form.$('input[name="user[password]"]');
const privacyTerms = await form.$('input[name="policy_confirmed"]');
const signInButton = await form.$('input[name="commit"]');
await email.type(loginCred.EMAIL);
await password.type(loginCred.PASSWORD);
await privacyTerms.click();
await signInButton.click();
await page.waitForNavigation();
return true;
}
const notifyMe = async (earliestDate) => {
const formattedDate = format(earliestDate, 'dd-MM-yyyy');
logStep(`sending an email to schedule for ${formattedDate}`);
await sendEmail({
subject: `We found an earlier date ${formattedDate}`,
text: `Hurry and schedule for ${formattedDate} before it is taken.`
})
}
const checkForSchedules = async (page) => {
logStep('checking for schedules');
await page.setExtraHTTPHeaders({
'Accept': 'application/json, text/javascript, */*; q=0.01',
'X-Requested-With': 'XMLHttpRequest'
});
await page.goto(siteInfo.APPOINTMENTS_JSON_URL);
const originalPageContent = await page.content();
const bodyText = await page.evaluate(() => {
return document.querySelector('body').innerText
});
try{
console.log(bodyText);
const parsedBody = JSON.parse(bodyText);
if(!Array.isArray(parsedBody)) {
throw "Failed to parse dates, probably because you are not logged in";
}
const dates =parsedBody.map(item => parseISO(item.date));
const [earliest] = dates.sort(compareAsc)
return earliest;
}catch(err){
console.log("Unable to parse page JSON content", originalPageContent);
console.error(err)
isLoggedIn = false;
}
}
const process = async (browser) => {
logStep(`starting process with ${maxTries} tries left`);
if(maxTries-- <= 0){
console.log('Reached Max tries')
return
}
const page = await browser.newPage();
if(!isLoggedIn) {
isLoggedIn = await login(page);
}
const earliestDate = await checkForSchedules(page);
if(earliestDate && isBefore(earliestDate, parseISO(NOTIFY_ON_DATE_BEFORE))){
await notifyMe(earliestDate);
}
await delay(NEXT_SCHEDULE_POLL)
await process(browser)
}
(async () => {
const browser = await puppeteer.launch(!IS_PROD ? {headless: false}: undefined);
try{
await process(browser);
}catch(err){
console.error(err);
}
await browser.close();
})();