Since the vaccination slots have opened all over the country; getting a slot has become as difficult as booking tatkal ticket on IRCTC. There are many apps now available who notifies when slots are available; I had an idea - Can I code my own cowin slot notifier? Will it be as effective as other apps? Turns out, the answer is yes. Without further waiting, let's jump into the code.
We will develop a very minimalistic NodeJs application which will notify us when the slots are available.
Pre-Requisites
- Cowin Public APIs - https://apisetu.gov.in/public/api/cowin
- Some knowledge of a NodeJs.
Part 1: Fetching the data
The API which we need to target are Appointment Availability APIs. Following APIs are exposed by Cowin:
We will use /v2/appointment/sessions/public/findByDistrict
but one can use other API as well and the logic will be same. This API takes in 2 query parameters:
-
district_id - To get the district_id, we need to hit the meta APIs from the swagger. Open the swagger link and hit get states API under Meta APIs - /v2/admin/location/states. Pick the state_id for your state. Then using this state_id hit, get list of districts under Meta APIs - /v2/admin/location/districts/{state_id}. Pick the
district_id
for your state. We will hardcode this value for out main API. For sample reference, we will use state as Delhi and district as South Delhi. The relevantstate_id is 9
anddistrict_id is 149
. -
date - The date in
DD-MM-YYYY
format for which we want slots.
We won't send any header value (I think the APIs are not consuming this header properly and giving incorrect response if you use them).
Now we have all data to get the slots. Using the https node module we will make a GET call to https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/calendarByDistrict?district_id={district_id}&date={date}
Sample Code for the same is:
https.get('https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/calendarByDistrict?district_id=149&date=16-05-2021', (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
processData(JSON.parse(data))
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
This will give us the API response in data
variable which we will pass to another function for processing.
Note: We need to call the api regularly at frequent intervals so as to get the slots as soon as they are available. The Cowin doc says API have limit of 100 calls per 5 minutes = One call per 3 second. We will use setInterval function for the same and clearInterval as soon as the slots are found.
Part 2: Processing the data
The response we have got is for all the centres of the district. Here is one sample response:
{
"centers": [
{
"center_id":701523,
"name":"P. SKV School Fatehpurberi S-4",
"address":"4 Church Wali Gali Fatehpur Beri New Delhi Delhi",
"state_name":"Delhi",
"district_name":"South Delhi",
"block_name":"Not Applicable",
"pincode":110074,
"lat":28,
"long":77,
"from":"09:00:00",
"to":"17:00:00",
"fee_type":"Free",
"sessions": [
{
"session_id":"23e393ea-a06e-42d7-860f-83ecd45edb5f",
"date":"16-05-2021",
"available_capacity":0,
"min_age_limit":18,
"vaccine":"COVISHIELD",
"slots": [
"09:00AM-11:00AM",
"11:00AM-01:00PM",
"01:00PM-03:00PM",
"03:00PM-05:00PM"
],
"available_capacity_dose1":0,
"available_capacity_dose2":0
}
]
}
]
}
The response contains a lot of info and we will write few conditions to filter the data. Note that each object under sessions array, contains available_capacity
key which tells the availability of the slots and min_age_limit
key tells the age limit for which slots are open. Based on these 2 keys and other factors such as pincode, let's filter out the results
const pincodes = [110030, 110062]
const centers = data.centers
for (let i = 0; i < centers.length; ++i) {
if (pincodes.indexOf(centers[i].pincode) >= 0) {
const sessions = centers[i].sessions
for (let j = 0; j < sessions.length; ++j) {
if (sessions[j].available_capacity > 0) {
slotFound = true
console.log(`Slots Found:
Pincode: ${centers[i].pincode}
Centre Name: ${centers[i].name}
Centre Address: ${centers[i].address}
Capacity Remaining: ${sessions[j].available_capacity}
`)
notify()
}
}
}
}
Once we have filtered out the results, we need a mechanism to notify us.
Part 3: The Notification
Since, I will be running this application locally in my laptop, I thought of using my Mac's audio player afplay
to notify me (Ubuntu equivalent for afplay is ffplay). We just need one audio file in our system and exec
from child_process
. Using exec, we can run bash commands in node. As soon as any slot is found, we can run the following command. It will start to play the music in our system thus alerting us (:D).
exec('afplay ./audio.mp3')
Stitching everything together, here is the full code:
Go ahead, save this file and run it in your system.
Next Steps
This is a working POC done in 30 mins and can be improved a lot. There are a lot of improvements that can be:
- Remove the hardcoding at various places and make the application generic for all states and districts
- Support to search for slots by different APIs
- Create UI and deploy the same on a website (and change the notification mechanism) to make it suitable for all users
Please comment for any valuable feedback, comment or criticism.
Thanks!
Top comments (2)
Hello,why the poll() method is not executing further to fetchDetails,if I opt to omit setInterval() ?
Hi,
setInterval repeatedly calls a function or executes a code snippet, with a fixed time delay between each call. Here, it is the one to call fetchSlots every 3 seconds. If that is removed, it means there is no function which is going to call fetchSlots again and again.
Hope it clarifies the doubt.