Skip to content

Instantly share code, notes, and snippets.

@AlexChesser
Forked from nuzayets/vax.js
Created June 16, 2021 19:22
Show Gist options
  • Save AlexChesser/86544724458375668530caab24c4663e to your computer and use it in GitHub Desktop.
Save AlexChesser/86544724458375668530caab24c4663e to your computer and use it in GitHub Desktop.
Automatically book 2nd dose vaccine at closest location Ontario
/***
* 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 = "your@email.com";
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