Update cowin.py
This commit is contained in:
parent
742582b5f2
commit
a4cb3c239f
194
cowin.py
194
cowin.py
|
@ -1,50 +1,57 @@
|
||||||
from apscheduler.schedulers.blocking import BlockingScheduler
|
try:
|
||||||
from bs4 import BeautifulSoup
|
import schedule
|
||||||
from datetime import datetime
|
from bs4 import BeautifulSoup
|
||||||
import subprocess
|
from datetime import datetime
|
||||||
import requests
|
import subprocess
|
||||||
import hashlib
|
import requests
|
||||||
import base64
|
import hashlib
|
||||||
import time
|
import base64
|
||||||
import json
|
import time
|
||||||
import fire
|
import json
|
||||||
import sys
|
import fire
|
||||||
import re
|
import sys
|
||||||
import os
|
import re
|
||||||
|
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,
|
||||||
|
@ -180,11 +195,11 @@ class CoWinBook():
|
||||||
|
|
||||||
otp_fetching_mode = ""
|
otp_fetching_mode = ""
|
||||||
if self.otp == 'a':
|
if self.otp == 'a':
|
||||||
otp_fetching_mode = 'AutoMode'
|
otp_fetching_mode = 'Auto Mode'
|
||||||
elif self.otp == 's':
|
elif self.otp == 's':
|
||||||
otp_fetching_mode = 'SiteMode'
|
otp_fetching_mode = 'Site Mode'
|
||||||
else:
|
else:
|
||||||
otp_fetching_mode = "ManualMode"
|
otp_fetching_mode = "Manual Mode"
|
||||||
|
|
||||||
print(f"OTP Sent ({otp_fetching_mode}) 📲 ... ")
|
print(f"OTP Sent ({otp_fetching_mode}) 📲 ... ")
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
|
Reference in a new issue