Update cowin.py

This commit is contained in:
roShan 2021-06-02 14:55:47 +05:30 committed by GitHub
parent 742582b5f2
commit a4cb3c239f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

156
cowin.py
View file

@ -1,4 +1,5 @@
from apscheduler.schedulers.blocking import BlockingScheduler try:
import schedule
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from datetime import datetime from datetime import datetime
import subprocess import subprocess
@ -11,40 +12,46 @@ import fire
import sys import sys
import re import re
import os import os
except ImportError:
print("First run requirements instaling command")
print("pip install -r requirements.txt")
exit()
OTP_SITE_URL = None OTP_SITE_URL = None
OTP_VALID_DURATION_SECONDS = 180 OTP_VALID_DURATION_SECONDS = 180
''' '''
Add Worker Domain here example : https://db.domain.workers.dev Add Worker Domain here in Double Quore example : "https://db.domain.workers.dev"
Check this : https://github.com/truroshan/CloudflareCoWinDB Check this : https://github.com/truroshan/CloudflareCoWinDB
''' '''
scheduler = BlockingScheduler() # scheduler = BlockingScheduler()
def line_break(): print("-"*25) def line_break(): print("-"*25)
def clear_screen(): os.system("clear") def clear_screen(): os.system('clear' if os.name =='posix' else 'cls')
class CoWinBook(): class CoWinBook():
def init( def init(
self, self,
mobile_no, mobile_no, # --m
pin = "Not Passed", pin = "Not Passed", # --p
age = 18 , age = 18 , # --a
vaccine = "ANY", vaccine = "ANY", # --v
dose = 1, dose = 1, # --d
otp = 'a', otp = 'a', # --o
time = 30, time = 30, # --t
bookToday = 1, bookToday = 1, # --b
relogin = None ): fee_type = "BOTH", # --f
relogin = None # --r
):
self.mobile_no = str(mobile_no) self.mobile_no = str(mobile_no)
if relogin and os.path.exists(self.mobile_no): os.remove(self.mobile_no) if relogin and os.path.exists(self.mobile_no): os.remove(self.mobile_no)
# Cron Time # Cron Time
global TIME global TIME
TIME = time TIME = 8 if time < 10 else time
# Include today session for Booking Slot # Include today session for Booking Slot
self.bookToday = 0 if bookToday is True else 1 self.bookToday = 0 if bookToday is True else 1
@ -55,6 +62,7 @@ class CoWinBook():
# Vaccination Center id and Session id for Slot Booking # Vaccination Center id and Session id for Slot Booking
self.vaccine = vaccine.upper() self.vaccine = vaccine.upper()
self.vacc_fee_type = fee_type.upper()
self.vacc_center = None self.vacc_center = None
self.vacc_session = None self.vacc_session = None
self.slot_time = None self.slot_time = None
@ -96,7 +104,7 @@ class CoWinBook():
bottomBanner = "for Today and Day After 📆 ..." if self.bookToday == 0 else "for Tomorrow and Day After 📆 ..." bottomBanner = "for Today and Day After 📆 ..." if self.bookToday == 0 else "for Tomorrow and Day After 📆 ..."
print(f" 📍 {self.pin} 💉 {age}+ ⌛️ {TIME} Seconds") print(f" 📍 {self.pin} 💉 {age}+ ⌛️ {TIME} Seconds")
print(f" 📲 xxxx{self.mobile_no[7:]} 💉 {self.vaccine} (Dose :{self.dose})") print(f" 📲 XXXX{self.mobile_no[7:]} 💉 {self.vaccine} (Dose :{self.dose})")
print(f"CoWin Auto Slot Booking 🔃\n{bottomBanner}") print(f"CoWin Auto Slot Booking 🔃\n{bottomBanner}")
line_break() line_break()
@ -138,12 +146,16 @@ class CoWinBook():
def checkToken(self): def checkToken(self):
# Pause job of Checking Slot # Pause job of Checking Slot
scheduler.pause_job('slot') # scheduler.pause_job('slot')
self.getSession() response = self.fetch_beneficiaries()
try:
response.json()
except json.decoder.JSONDecodeError:
self.login_cowin()
# Resume job of Checking Slot # Resume job of Checking Slot
scheduler.resume_job('slot') # scheduler.resume_job('slot')
# Login to selfregistration.cowin.gov.in/ # Login to selfregistration.cowin.gov.in/
def login_cowin(self): def login_cowin(self):
@ -155,11 +167,14 @@ class CoWinBook():
response = self.session.post('https://cdn-api.co-vin.in/api/v2/auth/generateMobileOTP',data=self.get_data()) response = self.session.post('https://cdn-api.co-vin.in/api/v2/auth/generateMobileOTP',data=self.get_data())
if self.otp == 's': requests.delete(f"{OTP_SITE_URL}/{self.mobile_no}") if self.otp == 's' and OTP_SITE_URL is not None: requests.delete(f"{OTP_SITE_URL}/{self.mobile_no}")
otpSha265 = self.get_otp() otpSha265 = self.get_otp()
try:
txn_id = response.json()['txnId'] txn_id = response.json()['txnId']
except json.decoder.JSONDecodeError:
print("Wrong OTP Entered")
return
self.data = { self.data = {
"otp":otpSha265, "otp":otpSha265,
@ -200,9 +215,9 @@ class CoWinBook():
last_msg_body = last_msg.get("body",'') last_msg_body = last_msg.get("body",'')
print(f'Waiting for OTP {i} sec') print(f'Waiting for OTP {i} sec')
sys.stdout.write("\033[F") self.set_cursor()
d1 = datetime.strptime(last_msg.get("received"), '%Y-%m-%d %H:%M:%S') d1 = datetime.strptime(last_msg.get("received","2019-12-01 09:09:09"), '%Y-%m-%d %H:%M:%S')
d2 = datetime.now() # current date and time d2 = datetime.now() # current date and time
diff = (d2 - d1).total_seconds() diff = (d2 - d1).total_seconds()
if (curr_msg_body != last_msg_body and "cowin" in last_msg_body.lower()) or diff <= OTP_VALID_DURATION_SECONDS: if (curr_msg_body != last_msg_body and "cowin" in last_msg_body.lower()) or diff <= OTP_VALID_DURATION_SECONDS:
@ -233,14 +248,15 @@ class CoWinBook():
msg = json.loads(msg)[0] msg = json.loads(msg)[0]
return msg return msg
except KeyError: except KeyError:
raise Exception("Install Termux:API 0.31 Version for AutoMode ") raise Exception("Install Termux:API from FDroid for Auto Mode ")
# Get OTP using DB hosted on Cloudflare and Attached with https://play.google.com/store/apps/details?id=com.gawk.smsforwarder
# Get OTP using DB hosted on Cloudflare and Configure with https://play.google.com/store/apps/details?id=com.gawk.smsforwarder
elif self.otp == 's': elif self.otp == 's':
if OTP_SITE_URL is None: if OTP_SITE_URL is None:
raise Exception("First Setup DB on Cloudflare \nhttps://github.com/truroshan/CloudflareCoWinDB ") raise Exception("First Setup DB on Cloudflare \nhttps://github.com/truroshan/CloudflareCoWinDB ")
res = requests.get(f"{OTP_SITE_URL}/{self.mobile_no}",timeout=3).json() res = requests.get(f"{OTP_SITE_URL}/{self.mobile_no}").json()
if res.get("status"): if res.get("status"):
msg['body'] = res.get('data').get("message") msg['body'] = res.get('data').get("message")
@ -262,12 +278,7 @@ class CoWinBook():
self.requestStatus = response.status_code self.requestStatus = response.status_code
if response.status_code == 200: if response.status_code == 200:
# CoWIN server may respond back with HTTP 204 so response.ok
# will not be right to depend upon. The content will be empty
# and so it will crash if we try to get the JSON body.
self.check_slot(response.json()) self.check_slot(response.json())
elif response.ok: # We have received ok response but without content
self.request_slot()
elif response.status_code == 401: elif response.status_code == 401:
print("Re-login Account : " + datetime.now().strftime("%H:%M:%S") + " 🤳") print("Re-login Account : " + datetime.now().strftime("%H:%M:%S") + " 🤳")
self.checkToken() self.checkToken()
@ -276,7 +287,8 @@ class CoWinBook():
# Check Slot availability # Check Slot availability
def check_slot(self,response): def check_slot(self,response):
for center in response.get('centers',[]): centers = response.get('centers',[])
for center in centers:
for session in center.get('sessions')[self.bookToday:]: for session in center.get('sessions')[self.bookToday:]:
@ -287,12 +299,13 @@ class CoWinBook():
capacity = session.get(f'available_capacity_dose{self.dose}') capacity = session.get(f'available_capacity_dose{self.dose}')
session_date = session.get('date') session_date = session.get('date')
vaccine_name = session.get('vaccine') + "ANY" vaccine_name = session.get('vaccine')
if capacity > 1 and \ if capacity > 1 and \
self.vaccine in vaccine_name and \ (self.vaccine in vaccine_name or self.vaccine == "ANY") and \
session.get('min_age_limit') == self.age and \ session.get('min_age_limit') == self.age and \
center.get('center_id') in self.center_id: center.get('center_id') in self.center_id:
self.slot_time = session.get('slots')[0] self.slot_time = session.get('slots')[0]
MSG = f'💉 {capacity} #{vaccine_name} / {session_date} / {center_name} 📍{self.pin}' MSG = f'💉 {capacity} #{vaccine_name} / {session_date} / {center_name} 📍{self.pin}'
@ -302,13 +315,13 @@ class CoWinBook():
BOOKED = self.book_slot() BOOKED = self.book_slot()
if BOOKED: if BOOKED:
scheduler.shutdown(wait=False) # scheduler.shutdown(wait=False)
print("Shutting Down CoWin Script 👩‍💻 ") print("Shutting Down CoWin Script 👩‍💻 ")
return exit()
# When last Checked # When last Checked
print(f"Last Checked ✅ : " + datetime.now().strftime("%H:%M:%S") + " 🕐") print(f"Last Checked {self.requestStatus} ✅ : " + datetime.now().strftime("%H:%M:%S") + " 🕐")
sys.stdout.write("\033[F") self.set_cursor()
# Get Solved Captcha in String # Get Solved Captcha in String
def get_captcha(self): def get_captcha(self):
@ -373,6 +386,8 @@ class CoWinBook():
return True return True
elif status == 409: elif status == 409:
print("This vaccination center is completely booked for the selected date 😥") print("This vaccination center is completely booked for the selected date 😥")
elif status == 400:
print("Minimum age criteria is 45 years for this center")
elif status == 401: elif status == 401:
self.login_cowin() self.login_cowin()
self.book_slot() self.book_slot()
@ -430,31 +445,48 @@ class CoWinBook():
def select_center(self): def select_center(self):
response = self.fetch_center() response = self.fetch_center()
# CoWIN server may respond back with HTTP 204 so response.ok
# will not be right to depend upon. The content will be empty
# and so it will crash if we try to get the JSON body.
while response.status_code != 200: while response.status_code != 200:
print(f'Trying to fetch center detail. Please wait...') print(f'Trying to fetch center detail. Please wait...')
sys.stdout.write("\033[F") self.set_cursor()
time.sleep(1) time.sleep(5)
response = self.fetch_center() response = self.fetch_center()
clear_screen()
response = response.json() response = response.json()
CENTERS = {} CENTERS = {}
INDEX_S = [] INDEX_S = []
if not response.get('centers'):
print("No Centers Available at this location")
print("Shutting Down CoWin Script 👩‍💻 ")
exit()
print(f"Select Vaccination Center ({self.pin}) 💉 \n") print(f"Select Vaccination Center ({self.pin}) 💉 \n")
counter = 1 counter = 1
for center in response.get('centers',[]): for center in response.get('centers',[]):
vaccine_fee_type = center.get("fee_type").upper()
vaccine__fee_emoji = '🆓' if "FREE" in vaccine_fee_type else '💰'
for session in center.get('sessions'): for session in center.get('sessions'):
if session.get('min_age_limit') == self.age: vaccine_name = session.get("vaccine")
print(f'{counter} : {center.get("name")}')
if session.get('min_age_limit') == self.age \
and (self.vaccine in vaccine_name or self.vaccine == 'ANY') \
and (self.vacc_fee_type in vaccine_fee_type or self.vacc_fee_type == "BOTH" ):
print(f'{counter} : {center.get("name")} {vaccine__fee_emoji}')
CENTERS[counter] = center.get('center_id') CENTERS[counter] = center.get('center_id')
INDEX_S.append(counter) INDEX_S.append(counter)
counter += 1 counter += 1
break break
if counter == 1:
# clear_screen()
print(f"No Center available Vaccine : ( 💉{self.vaccine}) Fee Type : ({self.vacc_fee_type}).")
self.shutting_down()
exit()
print() print()
line_break() line_break()
@ -464,7 +496,10 @@ class CoWinBook():
* Select Mutiple with Space * Select Mutiple with Space
input : 1 2 3 4 input : 1 2 3 4
* Select All Center * Select All Center
Hit Enter without Input\n""") Hit Enter without Input
**pass --f paid or free
**pass --v vacc_name \n""")
line_break() line_break()
@ -490,7 +525,7 @@ class CoWinBook():
response = self.fetch_beneficiaries() response = self.fetch_beneficiaries()
while response.status_code != 200: while response.status_code != 200:
print(f'Please wait...') print(f'Please wait...')
sys.stdout.write("\033[F") self.set_cursor()
time.sleep(5) time.sleep(5)
response = self.fetch_beneficiaries() response = self.fetch_beneficiaries()
@ -502,8 +537,8 @@ class CoWinBook():
print(f"Select User for Vaccination 👩‍👦‍👦 \n") print(f"Select User for Vaccination 👩‍👦‍👦 \n")
if not response.get('beneficiaries',[]): if not response.get('beneficiaries',[]):
print("No user added in beneficiaries") print("No beneficiaries added in Account")
return exit()
counter = 1 counter = 1
for user in response.get('beneficiaries'): for user in response.get('beneficiaries'):
@ -513,6 +548,13 @@ class CoWinBook():
INDEX_S.append(counter) INDEX_S.append(counter)
counter += 1 counter += 1
if counter == 1:
# clear_screen()
print(f"No beneficiaries available for Dose {self.dose}.")
self.shutting_down()
exit()
print() print()
line_break() line_break()
print(""" print("""
@ -539,6 +581,12 @@ class CoWinBook():
self.user_id = USER_ID self.user_id = USER_ID
def shutting_down(self):
print("Shutting Down CoWin Script 👩‍💻 ")
def set_cursor(self):
sys.stdout.write("\033[F")
if __name__ == '__main__': if __name__ == '__main__':
@ -549,9 +597,15 @@ if __name__ == '__main__':
fire.Fire(cowin.init) fire.Fire(cowin.init)
# Check for Slot # Check for Slot
scheduler.add_job(cowin.book_now, 'interval',id = "slot",seconds = TIME, misfire_grace_time=2) # scheduler.add_job(cowin.book_now, 'interval',id = "slot",seconds = TIME, misfire_grace_time=2,replace_existing=True)
schedule.every(TIME).seconds.do(cowin.book_now)
# Check Token every 3 min # Check Token every 3 min
scheduler.add_job(cowin.checkToken, 'cron',id ="login", minute = f'*/3',misfire_grace_time= 30) # scheduler.add_job(cowin.checkToken, 'cron',id ="login", minute = f'*/3',misfire_grace_time= 30)
schedule.every(3).minutes.do(cowin.checkToken)
scheduler.start() # scheduler.start()
while True:
schedule.run_pending()
time.sleep(1)