-
-
Save AlexChesser/86544724458375668530caab24c4663e to your computer and use it in GitHub Desktop.
Automatically book 2nd dose vaccine at closest location Ontario
This file contains hidden or 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
/*** | |
* Automated Vaccine Booker Thing | |
* | |
* I wish everything had an API. | |
* | |
* ____________________ | |
* / PLEASE \ | |
* ! READ ! | |
* ! ENTIRELY ! | |
* \____________________/ | |
* ! ! | |
* ! ! | |
* L_ ! | |
* / _)! | |
* / /__L | |
* _____/ (____) | |
* (____) | |
* _____ (____) | |
* \_(____) | |
* ! ! | |
* ! ! | |
* \__/ | |
* | |
* NOTE - THIS WILL AUTOMATICALLY BOOK WITH NO CONFIRMATION. | |
* It will replace your existing 2nd dose appointment | |
* if you have one. | |
* | |
* 1. You must log in through https://covid19.ontariohealth.ca/booking-home | |
* and be eligible for 2nd dose. | |
* 2. When you select the option that isn't Pharmacy, you are sent to | |
* https://vaccine.covaxonbooking.ca/location-search | |
* You MUST be on this page as pictured: https://i.imgur.com/dfAe1sD.png | |
* 3. Fill in your information below. Your location will be used for the distance | |
* calculation. Your personal info will be used to book the appointment. | |
* 4. Paste the entire file into the browser's Web Developer Tools console. | |
* 5. Output will be in the console. Your confirmation will be in your email on success. | |
*/ | |
// YOUR INFORMATION GOES HERE: | |
// *************************** | |
let FIRSTNAME = "FNAME"; | |
let LASTNAME = "LNAME"; | |
let EMAIL = "[email protected]"; | |
let PHONE = "+14165551234"; // <- in that format | |
let YOUR_LOCATION = {lat: 43.646723, lng: -79.413695}; // use Google Maps | |
let MAX_DISTANCE_METERS = 10000; | |
let MAX_DATE = "2021-06-27"; | |
// *************************** | |
let cancelToken = { cancelled: false }; | |
let cancel = () => cancelToken.cancelled = true; | |
let go = async (c) => { | |
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); | |
const API = parcelRequire("bpkL").ServicesContext._currentValue.bookingService; | |
API._apiCommService._baseURL = "https://api.covaxonbooking.ca/public"; | |
const log = (...o) => console.log(new Date().toLocaleString(), ...o); | |
let session = {}; | |
try { | |
session = Object.entries(document.getElementById('root'))[3][1]._internalRoot | |
.current.lastEffect.memoizedState.next.next.memoizedState; | |
} catch { | |
throw "Error: You MUST be on the 'Find a Vaccination Center Location - " + | |
"Enter a City, Address or Postal Code' page before running this. " + | |
"Please refresh and go to that screen first."; | |
} | |
var successfullyBooked = false; | |
while (!successfullyBooked) { | |
const find_good_location = async () => { | |
const result = await API.searchLocations({ | |
focusPoint: YOUR_LOCATION, | |
fromDate: new Date, | |
vaccineData: parcelRequire("8vBb").getVaccineDataAtStepOrLatest(session.vaccineData, ["screening"]), | |
locationQuery: session.locationQuery || void 0, | |
doseNumber: session.appointmentRescheduleFrom || session.previousAppointments.length + 1, | |
includeThirdPartyLocations: true, | |
cursor: "", | |
limit: 20, | |
locationType: "CombinedBooking" | |
}); | |
log("looking..."); | |
const vloc = result.locations.find( l => l.distanceInMeters <= MAX_DISTANCE_METERS); | |
if (vloc === undefined && result.locations[0] !== undefined) { | |
log("closest location found is too far", result.locations[0]); | |
} else { | |
log("no locations found", result); | |
} | |
return vloc !== undefined && vloc; | |
}; | |
var vaxLocation = false; | |
while (vaxLocation === false) { | |
if (c.cancelled) throw "cancelled"; | |
await sleep(500); | |
vaxLocation = await find_good_location(); | |
} | |
log("got a location", vaxLocation); | |
const startDate = new Date(); | |
const endDate = new Date(MAX_DATE); | |
const vaccineData = session.vaccineData.latest; | |
const doseNumber = 2; | |
const availabilityResponse = await API.getLocationAvailability(vaxLocation, startDate, endDate, vaccineData, doseNumber); | |
const availableDate = availabilityResponse.availability.find( a => a.available ); | |
if (!availableDate) { | |
log("no availability...", availabilityResponse); | |
await sleep(500); | |
continue; | |
} | |
log("got a date with availability", availableDate); | |
const slotsResponse = await API.getLocationSlots(vaxLocation, availableDate.date, vaccineData); | |
const availableSlot = slotsResponse.slotsWithAvailability.find( _ => true ); | |
if (availableSlot === undefined) { | |
log("unable to find an available slot", slotsResponse); | |
continue; | |
} | |
log("found a time slot", availableSlot); | |
const reserveSlotResponse = await API.reserveSlot(doseNumber, vaxLocation, | |
availableDate.date, availableSlot.localStartTime, | |
vaccineData, "", session.sessionId); | |
if (!reserveSlotResponse.value || !reserveSlotResponse.value.reservationId) { | |
log("unable to reserve the timeslot", reserveSlotResponse); | |
continue; | |
} | |
log("got a reserved slot", reserveSlotResponse); | |
const reservationId = reserveSlotResponse.value.reservationId; | |
const personalDetails = [ | |
{ "id": "q.patient.firstname", "value": FIRSTNAME, "type": "text" }, | |
{ "id": "q.patient.lastname", "value": LASTNAME, "type": "text" }, | |
{ "id": "q.patient.email", "value": EMAIL, "type": "email" }, | |
{ "id": "q.patient.mobile", "value": PHONE, "type": "mobile-phone" }]; | |
const additionalQuestions = [ | |
{"id": "q.patient.proxy.section.hideshow","value": "No","type": "single-select"}, | |
{"id": "q.patient.desc.proxy.name","type": "text"}, | |
{"id": "q.patient.desc.proxy.phone","type": "text"}, | |
{"id": "q.patient.desc.relationship.to.the.client","type": "single-select"}]; | |
const createAppointmentResponse = await API.createAppointment({ | |
eligibilityQuestions: [], | |
personalDetails, | |
additionalQuestions, | |
appointments: [ { reservationId: reservationId } ], | |
oneTime: "", | |
locale: "en-CA", | |
externalAppointments: session.externalAppointments | |
}); | |
log("Success! Check your email.", createAppointmentResponse); | |
successfullyBooked = true; | |
} | |
} | |
try { | |
await go(cancelToken); | |
} catch (error) { | |
console.error("an unexpected error occurred. try logging in again " + | |
"if the following error doesn't mean anything:\n", error); | |
} | |
// Type cancel(); in the console to stop. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment