Covid Vaccine availability notifier

Covid Vaccine availability notifier - nerdyelectronics

Our country is overwhelmed right now. Covid vaccines are in short supply. Although there are ways to book a slot, we first need to know that slots are available. It is a lot of manual effort. Hence I decided to create and show a way how to do that automatically. The Covid Vaccine Availability Notifier runs on AWS Lambda and check for slots every two hours. If a slot is available, it will automatically send an email.

The application is based on Python3.8.

This entire Covid Vaccine Availability Notifier project is broken down into two parts:

  1. We will first create a python script to ping the API available to get the data and then see how to send an email notification.
  2. In part two of this tutorial, we will configure AWS Lambda so that it runs without manual efforts and keeps checking periodically – a true Covid Vaccine Availability Notifier

This project requires basic knowledge of python. With that, you will be able to customize the application as per your needs.

Even if you do not know basic python, you can install python, install the libraries and follow through the post. You will be able to do it.

Let’s get started then.

Import Necessary Libraries

We need a few libraries to help us achieve it. Following are the libraries required:

import requests # to send GET requests to the server
from datetime import date # to create the date string
import json #to parse the json response from server

Function to check for slots

We will now create a function that will do the following:

  1. Ping the URL
  2. Parse the data
  3. Check for available slots and create a message
  4. Enter information in the message if the slot is available
  5. Return the message

Let us have a look at the function.

def checkStatus():
    today = date.today() #get today's date from system
    target_date = str(today.day) + "-" + str(today.month) +"-" + str(today.year)
    payload = {'district_id':'8','date':target_date}	#payload with district ID and date
    
    headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36'}
    byDistrict_URL = "https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/calendarByDistrict"
    
    data = requests.get(byDistrict_URL,headers=headers,params = payload) # Send a GET request with the defined payload
    json_data=  data.json()
    message = ''

###Loop through the data###
    for i in range(len(json_data['centers'])): #loop for all centers
        center = 'center : ' + (json_data['centers'][i]['name']) + '<br />' + "District : " + json_data['centers'][i]['district_name'] + '<br />'+ 'address : ' + (json_data['centers'][i]['address'])

        for j in range(len(json_data['centers'][i]['sessions'])):  #loop for all sessions in a center
            capacity = json_data['centers'][i]['sessions'][j]['available_capacity'] #available capacity
            minAge = json_data['centers'][i]['sessions'][j]['min_age_limit']  #minimum age limit for vaccination in this center session


            if(capacity>0 and minAge == 18):  #add to message only if capacity is more than zero
                available_date = json_data['centers'][i]['sessions'][j]['date']
                message = message + center + "<br />"  + "Date : " + available_date + "<br />" + "Available Capacity : " + str(capacity) + "<br />" + "Minimum Age : " + str(minAge) + "<br /><br />"
    return(message)

Let us break down the checkStatus() function:

1. Create a date string:

The API requires the date for which it should check for availability. So, we need to send the date as a parameter in the URL. Past dates are of no use to us. Hence, we will check for today’s date and pass it to the server. To do that, we will read the current date from the system.

today = date.today() 

target_date = str(today.day) + "-" + str(today.month) +"-" + str(today.year)

2. Create the Header

For pinging the server, we use the “requests” library in python. The library provides a way to send headers. These headers tell the server about the kind of system which is pinging the server. Based on the header, the server decides the kind of response to be returned.

headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36'}

3. Create the URL

There are two parts to it.

The first one is the API that we wish to ping. This can be found in the API Setu portal for Co-Win. For this post, I am using the API that gives data for one week from today, district wise.

byDistrict_URL = "https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/calendarByDistrict"

In the second part, we need to tell the API the district ID and the date. To pass this information, we create a payload dictionary, and, will give this dictionary to the requests library

payload = {'district_id':'8','date':target_date}

These are like information to the URL server that we want to check for the district ID 8 and the date = today’s date

How to find your district ID?

The best and the simplest way is to use the Cowin portal. Follow these steps:

  • Open the Co-Win portal in a browser
  • From your browser settings, open the Developer tools (chrome) or Web Developer Tools (Firefox)
  • Select the “Network” tab
  • Select the Option “Search By District” on the website

cowin_search_by_district

  • Enter the State and the District and click on “Search”
  • In the Network tab, it will show the URL that was pinged. It will look something like this:

find_district_ID

In the above image, you can find the district ID in the marked area. This is the ID of your district which you need to mention in place of 8 in the code. In the image above, the district_id is 5

Once you get the URL ready for your district, you are ready to move on. In the next step, we will ping the URL.

Ping the URL

The response received from the URL is in JSON format. For this code, I am converting it to a python dictionary for further processing.

data = requests.get(byDistrict_URL,headers=headers, params = payload) #pass the URL, the header to ping the server, and the payload
json_data= data.json() #convert the JSON to dict

The data reply from the server is in the following format:

  • Centers
    • Center-ID 1
      • Session 0
        • Date = Today
        • Min_Age_Lim
        • Available Capacity
        • Vaccine Name
      • Session 1
        • Date = Today + 1
        • Min_Age_Lim
        • Available Capacity
        • Vaccine Name
    • Center-ID 2

And so on. So, what we will do is to loop through the data.

  1. Check for each center and for each center, check for all the sessions.
  2. If there is vaccine available, store the center name, address, date, capacity and minimum age in a string data holder.
  3. Repeat for all the centers

Finally, when we are done looping through the data, we will return the message. All we have to do now is to call this function.

print(checkStatus())

 

When you call this function, it is very likely that you don’t get any output. That can happen if there are no slots available for the mentioned minimum age. So, just for test, change the capacity to >= 0 and minAge==45

if(capacity>=0 and minAge == 45): 
     available_date = json_data['centers'][i]['sessions'][j]['date']
     message = message + center + "\n" + "Date : " + available_date + "\n" + "Available Capacity : " + str(capacity) + "\n" + "Minimum Age : " + str(minAge) + "\n\n"

 

Output:

center : Vada Cheepurupalli CVC Site
District : Visakhapatnam
address : Near Main Road Vada Cheepurupali
Date : 10-05-2021
Available Capacity : 0
Minimum Age : 45

center : Vada Cheepurupalli CVC Site
District : Visakhapatnam
address : Near Main Road Vada Cheepurupali
Date : 11-05-2021
Available Capacity : 0
Minimum Age : 45

center : Vada Cheepurupalli CVC Site
District : Visakhapatnam
address : Near Main Road Vada Cheepurupali
Date : 12-05-2021
Available Capacity : 0
Minimum Age : 45

center : Vada Cheepurupalli CVC Site
District : Visakhapatnam
address : Near Main Road Vada Cheepurupali
Date : 13-05-2021
Available Capacity : 0
Minimum Age : 45

vaccine notifier code output

At this point, we are able to successfully ping the server and get the vaccine information. We now need to send a notification if the vaccines are available.

Notify

For sending notifications, we will use an email service from AWS – Amazon Simple Email Service (SES). This service allows us to send emails from a verified email ID from a program, in our case, our python code.

To use this service, we need an AWS account and a verified email ID in SES. This post describes how to verify an email ID in SES. There are other SMTP libraries that will allow you to do that, but, they will fail when we move our entire code to cloud.

The notify function that will send an email if vaccines are available. This function takes two inputs

  1. The message to be sent – This is the message we created earlier after looping through the entire server response.
  2. The recipient email ID – This ID can be same as the sender email ID. If you want it to be different, you can register the other email ID as well in Amazon SES.

Include Necessary libraries:

To use Amazon SES in python, we need to include the AWS boto3 library. To do that, use the following statements:

from botocore.exceptions import ClientError # AWS communication errors
from datetime import date # to create the date string

Create the notify function:

We will now create the notify function.

def notify(message, RECIPIENT):
    CHARSET = "UTF-8"
    SUBJECT = "Vaccine available!!"
    # Create a new SES resource and specify a region.
    client = boto3.client('ses',region_name=AWS_REGION)

    # Try to send the email.
    try:
        #Provide the contents of the email.
        response = client.send_email(
            Destination={
                'ToAddresses': [
                    RECIPIENT,
                ],
            },
            Message={
                'Body': {
                    'Html': {
                        'Charset': CHARSET,
                        'Data': message,
                    },
                    'Text': {
                        'Charset': CHARSET,
                        'Data': message,
                    },
                },
                'Subject': {
                    'Charset': CHARSET,
                    'Data': SUBJECT,
                },
            },
            Source=SENDER,
        )
    # Display an error if something goes wrong.	
    except ClientError as e:
        print(e.response['Error']['Message'])
    else:
        print("Email sent! Message ID:"),
        print(response['MessageId'])

We will send an HTML message. To have a properly formatted email, the message that we create should be based on HTML. We don’t need anything fancy here. All the texts in the message are fine. It’s only the ‘newline’ character (“\n”) that need to be changed.

The “\n” causes the output to move to a new line. In HTML, the equivalent is “break” or “<br />”

To make this change, replace all the “\n” in the checkStatus() function with “<br />”

 

Covid Vaccine Availability Notifier – The main code:

This is the part that will execute all the functions we created so far. The comments in this section will explain the statements.

RECIPIENT = "vixxxxxxxxxxxxx@gmail.com" # receivers email ID. Can be same as sender
SENDER = "vixxxxxxxxxxxxx@gmail.com" # sender email ID
AWS_REGION = "ap-south-1" #Region where the SES email ID is verified. For me it was Mumbai, hence "ap-south-1"

BODY_TEXT = ((checkStatus())) # here we ping the server and get the status. The status is then stored in BODY_TEXT 

if(BODY_TEXT != ''):   # if BODY_TEXT is not empty means that there are some slots available. Notify only in that case
    notify(BODY_TEXT,RECIPIENT)  # if slots available, notify

At this point, you should be receiving emails if there are slots based on your criteria. Do not forget to change back the capacity to greater than zero.

Improvements to Covid Vaccine Availability Notifier :

  1. You can make changes to the code to include more information.
  2. You can encapsulate the entire code to run in a time loop to check periodically
  3. Instead of hard-coding the district ID, you can make is a parameter and pass it as argument while calling the function.

This part requires that the computer where this code is running is always ON and always connected to the internet. That is not a very ideal approach. So, in the next part, we will use AWS to run the code on the cloud without manual intervention.

Download the Code:

You can download the code from the github page – Covid Vaccine availability notifier

Sharing is Caring!!

Leave a Reply

Your email address will not be published. Required fields are marked *