I’m done with COVID. It’s the worst and I can’t wait for it to go away. While I can understand a bit of the hesitation some people have with the COVID-19 vaccine, I’m on team "get it in me", and I’m counting down the days until we collectively kick this thing in the capsid.
The other day my friend, Mike, threw out an idea: knowing that he and I were going to eventually 1. find out the vaccine is available to us, which would cause each of us to 2. spend all day checking the appointment availability in our areas. He had the idea of creating some sort of bot to check the local vaccine eligibility page throughout the day and send out an email or some sort of notification when appointments were available in our area.
Mike has a background in databases and PHP, so he had a good grasp on what had to get done, but asked me for some advice on how to put it all together. Together, we went from this idea to programming our own personal appointment trackers using our iPhones and a couple of free apps.
Article Updates
-
Line 55 in the Scriptable Code was changed from
return location.availableAppointments === "AA";
toreturn location.availableAppointments === "Y";
Approach
Mike and I both live in Western New York, so our main resource for vaccine availability was this page on the New York State website. While doing a little digging, Mike found a JSON endpoint that is used by this page to provide locations and their appointment statuses. Scraping this page would be possible, but reading from a JSON feed makes things much easier.
While thinking of all of the ways this bot could be accomplished, it dawned on me that we could use a brilliant iOS app, called Scriptable, and skip the whole server and app setup altogether. In a nut shell, Scriptable lets you use JavaScript syntax and some built-in APIs to pull off some really impressive automation that could otherwise be impossible via iOS’s Shortcuts app. It even integrates with Shortcuts and has lots of other really nice ways to make the scripts you write available throughout the OS.
I wrote the initial script in JavaScript and Mike and I refined it along the way. The end result displays something like this:
It’s nothing super fancy, but it does the trick. The script makes a request to the JSON feed, filters the results down to a list of specific locations, determines if there are available appointments in one of those locations, then sends a local notification with the results.
When the notification pops up, tapping on it takes you to the NYS eligibility page so you can begin the process of setting up your appointment.
Scriptable Code
The script we used here is specific to NYS and their eligibility website, however, the process here could be replicated for other locations, provided that you have the data available in some form that can be read and parsed in JavaScript. Should you want to try to set something like this up(* see my caveats below), here’s how we did it:
First, you'll need to download Scriptable from the App Store. It’s free, but if this works out for you and you want to send the developer a tip, you can do so right within the app.
Once you have it installed, create a new script and copy and paste this code in:
/*
* If true, send notification even when no
* locations have appointments.
*/
const alwaysNotify = true;
/*
* Log steps to debug in Scriptable
*/
const debug = false;
/*
* Limit results to only specific locations
* when onlyMyLocations is true.
*/
const myLocations = [
"Henrietta, NY",
"Buffalo, NY",
"Syracuse, NY",
"Utica, NY",
];
/*
* Filter locations to the list in myLocations.
*/
const onlyMyLocations = true;
/*
* Request appointment data from the website.
*/
const request = new Request("https://am-i-eligible.covid19vaccine.health.ny.gov/api/list-providers");
const response = await request.loadJSON();
if (debug) {
log(response.providerList);
}
/*
* If onlyMyLocations is true, filter all of the
* data down to only the addresses in myLocations,
* otherwise use all of the locations.
*/
const myLocationsData = onlyMyLocations ? response.providerList.filter((location) => {
return myLocations.includes(location.address);
}) : response.providerList;
if (debug) {
log(myLocationsData);
}
/*
* From the results of myLocations, find
* the locations where appointments are available.
*/
const availableLocations = myLocationsData.filter((location) => {
return location.availableAppointments === "Y";
});
if (debug) {
log(availableLocations);
}
/*
* Set a notification body based on whether
* or not there are results.
* If alwaysNotify is true, a fallback message
* will be sent when no appointments are
* available.
*/
let body;
if (availableLocations.length) {
body = "Locations:";
for (let i=0; i<availableLocations.length; i++) {
body += ` ${availableLocations[i].address}${i < availableLocations.length - 1 ? ';' : '' }`;
}
} else if (alwaysNotify) {
body = "No appointments available";
}
if (debug) {
log(body);
}
/*
* If appointments are available,
* send a notification.
* Tap the notification to see the
* eligability page in Safari.
*/
if (body) {
const notify = new Notification();
notify.sound = "default";
notify.title = "COVID Vaccine Checker";
notify.body = body;
notify.openURL = "https://am-i-eligible.covid19vaccine.health.ny.gov";
notify.schedule();
};
/*
* Let Scriptable know that the script is done.
*/
Script.complete()
At the top of this script you’ll see a few variables that are set to some sane defaults and they give you a quick way to customize the experience. The one you will want to edit is myLocations
. This lets you narrow down the list to specific areas where you would go to get the vaccine. In my case, I left a few extras in there for testing.
When updating the items in myLocations
it's important that the spelling and case match that of the address
values in the JSON feed:
{
"providerList": [
{
"providerName": "SUNY Polytechnic Institute - Wildcat Field House",
"address": "Utica, NY",
"availableAppointments": "NAC"
},
{
"providerName": "University at Buffalo South Campus - Harriman Hall",
"address": "Buffalo, NY",
"availableAppointments": "NAC"
},
{
"providerName": "Rochester Dome Arena",
"address": "Henrietta, NY",
"availableAppointments": "NAC"
}
... other locations
],
"lastUpdated": "2/16/2021, 8:03:33 PM"
}
Once the script is customized to your liking, you can pick an icon and give it a name in your script’s settings. It can be added to your Home Screen or ran within Scriptable, however, Mike and I opted to automate it. More on that after these fine disclaimers:
*Disclaimer: you many use this script, provided as-is, however you’d like, using your own discretion. Ideally it can help in alerting you when and where vaccine appointments are available, but it doesn’t replace getting appointment information from an official source. Also, I realize there is no error handling or sanitization going on here, but for the scope and the life of this script, I’m not too worried about that.
Automating with Shortcuts
If your iOS device is up to date, you should have the Shortcuts app installed by default. In the app, you can set it up to interact with your Scriptable script on demand or via Siri, but to automate running this script you can follow these directions:
- Tap on the Automation tab and tap the plus icon to create a new automation.
- Tap on Create Personal Automation to run this script on your device.
- Select Time of Day and choose when and how often the script should run. Click Next when you’re done.
- This step may be different depending on what Siri suggestions are shown, but to be sure you can add your script, tap on Add Action, tap Apps, scroll down to Scriptable, then select your script from the list. NOTE: depending on how complicated your script is, you can set Shortcuts to run your script within the Scriptable app in this action’s settings.
- After tapping Next and getting to the New Automation summary screen, turn Ask Before Running off and then hit Done to finish set up.
If all goes well you should see the script run at the time you chose. If you were thinking you’d check the eligibility website several times a day, you can repeat this process to set up multiple automations to run throughout the day.
During this process I've observed two things:
First, there’s irony for me in that with the lack of free time I’ve had due to COVID-19 meant that I haven’t taken the time to really do any recreational coding. It was nice to collaborate and solve a problem with code, without it being a huge undertaking or time commitment.
Second, having gone to some extreme lengths to secure the purchase of a PS5, I’ve learned that it helps to use technology to your advantage. In this case we’re not talking about getting an alert the moment the appointment page gets updated, but by automating this task I can carry on with my day and let my script do the work of checking for me.
If you wind up using this script, improving on it, or developing a version for an area outside of New York, I'd love to hear how you found it helpful. Either way, let’s get vaccinated so we can all get back out there. 💉🦠