Last active
April 8, 2021 21:00
-
-
Save rxb/ba137f0cf2ddcbd4eb734f06956d4972 to your computer and use it in GitHub Desktop.
check the vaccine sites with less carpal tunnel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const puppeteer = require('puppeteer'); | |
// CONFIG | |
const ZIPCODE = "11222"; | |
const REFRESH_MS = 30000; | |
const ENABLED = { | |
northwell: true, | |
walgreens: true, | |
nyc: true, | |
cvs: true | |
} | |
const logWithTime = (msg, bell) => { | |
const timestamp = new Date().toLocaleTimeString(); | |
const bellstring = bell ? "\007" : ""; | |
console.log(`[${timestamp}] ${msg} `+bellstring); | |
} | |
const initWalgreens = async (page) => { | |
await page.goto('https://www.walgreens.com/findcare/vaccination/covid-19', { waitUntil: 'domcontentloaded' }); | |
console.log("WALGREENS\ncomplete forms until you arrive the appointment scheduling step, then script will automatically continue"); | |
await page.waitForFunction('document.querySelector("h1") && document.querySelector("h1").innerText.includes("Let’s check COVID-19 vaccine availability in your area.")', {timeout: 0}); | |
console.log("[ok!]\n"); | |
return page; | |
} | |
const runWalgreens = async (page) => { | |
const trySearch = async () => { | |
await page.evaluate((zip) => { | |
const inputEl = document.querySelector('#inputLocation'); | |
inputEl.value = zip; | |
}, ZIPCODE); | |
const [buttonEl] = await page.$x('//*[@id="wag-body-main-container"]/section/section/section/section/section[2]/div/span/button'); | |
await buttonEl.click(); | |
await page.waitForTimeout(2000); | |
const [unavailableEl] = await page.$x('//*[@id="wag-body-main-container"]/section/section/section/section/div/a/span[2]/p[contains(text(),"Appointments unavailable")]'); | |
if(unavailableEl){ | |
logWithTime(`walgreens: no`); | |
} | |
else{ | |
logWithTime(`WALGREENS: YES`); | |
} | |
} | |
setInterval(trySearch, REFRESH_MS); | |
} | |
const initNorthwell = async (page) => { | |
await page.setDefaultNavigationTimeout(0); | |
await page.goto('https://northwellvaccine.force.com/s/?id=a1T4x000007TQSKEA4', { waitUntil: 'domcontentloaded' }); | |
console.log("NORTHWELL") | |
console.log("[ok!]\n"); | |
return page; | |
} | |
const runNorthwell = async (page) => { | |
const trySearch = async () => { | |
await page.reload({ waitUntil: ["networkidle0", "domcontentloaded"] }); | |
const [unavailableEl] = await page.$x('/html/body/div[3]/div[2]/div/div[2]/div/div/div[2]/div/div/p[contains(text(),"COVID-19 vaccine appointments are currently filled")]'); | |
if(unavailableEl){ | |
logWithTime(`northwell: no`); | |
} | |
else{ | |
logWithTime(`NORTHWELL: YES`, true); | |
} | |
} | |
page.on('dialog', async dialog => { | |
await dialog.accept(); | |
}); | |
setInterval(trySearch, REFRESH_MS); | |
} | |
const initNYC = async (page) => { | |
await page.setDefaultNavigationTimeout(0); | |
await page.goto('https://vax4nyc.nyc.gov/patient/s/vaccination-schedule', { waitUntil: 'domcontentloaded' }); | |
console.log("NYC:\ncomplete forms until you arrive the appointment scheduling step, then script will automatically continue"); | |
await page.waitForXPath('//*[@id="main-content-0"]/div/div[3]/div/div/c-vcms-schedule-flow/main/div[2]/section[1]/div/section/c-vcms-book-appointment/article/h1[contains(text(),"Schedule an Appointment")]', {timeout: 0}); | |
console.log("[ok!]\n"); | |
return page; | |
} | |
const runNYC = async (page) => { | |
const trySearch = async () => { | |
const [inputEl] = await page.$x('//*[@id="main-content-0"]/div/div[3]/div/div/c-vcms-schedule-flow/main/div[2]/section[1]/div/section/c-vcms-book-appointment/article/div[1]/div[2]/lightning-input/div/input'); | |
await inputEl.focus(); | |
await inputEl.click({ clickCount: 3 }) | |
await inputEl.type(ZIPCODE); | |
await page.waitForTimeout(2000); | |
const [unavailableEl] = await page.$x('//*[@id="main-content-0"]/div/div[3]/div/div/c-vcms-schedule-flow/main/div[2]/section[1]/div/section/c-vcms-book-appointment/article/div[4]/div[1]/span/strong[contains(text(),"No appointments are currently available.")]'); | |
if(unavailableEl){ | |
logWithTime(`nyc: no`); | |
} | |
else{ | |
logWithTime(`NYC: YES`, true); | |
} | |
} | |
setInterval(trySearch, REFRESH_MS); | |
} | |
const initCVS = async (page) => { | |
await page.setDefaultNavigationTimeout(0); | |
await page.goto('https://www.cvs.com/immunizations/covid-19-vaccine', { waitUntil: 'domcontentloaded' }); | |
console.log("CVS:\ncomplete forms until you arrive the appointment scheduling step, then script will automatically continue"); | |
await page.waitForXPath('//*[@id="content"]/div[1]/div[2]/h2[contains(text(),"Schedule dose")]', {timeout: 0}); | |
console.log("[ok!]\n"); | |
return page; | |
} | |
const runCVS = async (page) => { | |
const trySearch = async () => { | |
const [inputEl] = await page.$x('//*[@id="address"]'); | |
await inputEl.focus(); | |
await inputEl.click({ clickCount: 3 }) | |
await inputEl.type(ZIPCODE); | |
const [buttonEl] = await page.$x('//*[@id="generic"]/div/div/div[1]/button'); | |
await buttonEl.click(); | |
await page.waitForTimeout(2000); | |
const [unavailableEl] = await page.$x('//*[@id="content"]/div[2]/cvs-store-locator/div/div/div[2]/p[contains(text(),"sorry, there are currently no appointments")]'); | |
if(unavailableEl){ | |
logWithTime(`cvs: no`); | |
} | |
else{ | |
// CVS site is glitchy | |
const [error1El] = await page.$x('//*[@id="banner_alert"]/div[2]/p[2][contains(text(),"This service is temporarily unavailable")]'); | |
const [error2El] = await page.$x('//*[@id="banner_alert"]/div[2]/p[2][contains(text(),"Please try again later")]'); | |
if(error1El || error2El){ | |
logWithTime(`cvs: error, retrying`); | |
page.goBack({ waitUntil: 'domcontentloaded' }) | |
} | |
else{ | |
logWithTime('CVS: YES', true); | |
} | |
} | |
} | |
setInterval(trySearch, REFRESH_MS); | |
} | |
const launchBrowserAndGetPage = async() => { | |
const browser = await puppeteer.launch({ | |
headless: false, | |
args: [ | |
'--disable-background-timer-throttling', | |
'--disable-backgrounding-occluded-windows', | |
'--disable-renderer-backgrounding' | |
] | |
}); | |
const newPage = await browser.newPage(); | |
return newPage; | |
} | |
async function init(){ | |
console.log('\n\n'); | |
console.log('##########################################'); | |
console.log('NYC VACCINE BOT'); | |
console.log('##########################################'); | |
console.log('\n'); | |
if(ENABLED.walgreens){ | |
const walgreensPage = await launchBrowserAndGetPage(); | |
runWalgreens(await initWalgreens(walgreensPage)); | |
} | |
if(ENABLED.cvs){ | |
const cvsPage = await launchBrowserAndGetPage(); | |
runCVS(await initCVS(cvsPage)); | |
} | |
if(ENABLED.nyc){ | |
const nycPage = await launchBrowserAndGetPage(); | |
runNYC(await initNYC(nycPage)); | |
} | |
if(ENABLED.northwell){ | |
const northwellPage = await launchBrowserAndGetPage(); | |
runNorthwell(await initNorthwell(northwellPage)); | |
} | |
} | |
init(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
🎉