try: import schedule from bs4 import BeautifulSoup from datetime import datetime import subprocess import requests import hashlib import base64 import time import json import fire import sys import re import os except ImportError: print("First run requirements instaling command") print("pip install -r requirements.txt") exit() OTP_SITE_URL = None OTP_VALID_DURATION_SECONDS = 180 ''' Add Worker Domain here in Double Quore example : "https://db.domain.workers.dev" Check this : https://github.com/truroshan/CloudflareCoWinDB ''' # scheduler = BlockingScheduler() def line_break(): print("-"*25) def clear_screen(): os.system('clear' if os.name =='posix' else 'cls') class CoWinBook(): def init( self, mobile_no, # --m pin = "Not Passed", # --p age = 18 , # --a vaccine = "ANY", # --v dose = 1, # --d otp = 'a', # --o time = 30, # --t bookToday = 1, # --b fee_type = "BOTH", # --f relogin = None # --r ): self.mobile_no = str(mobile_no) if relogin and os.path.exists(self.mobile_no): os.remove(self.mobile_no) # Cron Time global TIME TIME = time # Include today session for Booking Slot self.bookToday = 0 if bookToday is True else 1 self.center_id = [] # Selected Vaccination Centers self.user_id = [] # Selected Users for Vaccination # Vaccination Center id and Session id for Slot Booking self.vaccine = vaccine.upper() self.vacc_fee_type = fee_type.upper() self.vacc_center = None self.vacc_session = None self.slot_time = None # Dose 1 or Dose 2 ( default : 1) self.dose = 2 if dose >= 2 else 1 # OTP Fetching method self.otp = otp # User Age 18 or 45 self.age = 18 if age < 45 else 45 # Request Session self.session = requests.Session() self.requestStatus = None # Data for sending request self.data = {} # Token Recieved from CoWIN self.bearerToken = None # Session Token self.todayDate = datetime.now().strftime("%d-%m-%Y") # Login and Save Token in file( filename same as mobile no) self.getSession() self.checkByPincode = False if type(pin) is int: self.pin = pin # Area Pincode or District Id self.checkByPincode = True if len(str(pin)) == 6 else False else: self.pin = self.get_district_id() # Selecting Center and User self.setup_details() 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" 📲 XXXX{self.mobile_no[7:]} 💉 {self.vaccine} (Dose :{self.dose})") print(f"CoWin Auto Slot Booking 🔃\n{bottomBanner}") line_break() # Set Header in self.session = requests.Session() def set_headers(self): self.session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Mobile Safari/537.36', 'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'en-US,en;q=0.5', 'Content-Type': 'application/json', 'Origin': 'https://selfregistration.cowin.gov.in', 'Connection': 'keep-alive', 'Referer': 'https://selfregistration.cowin.gov.in/', 'TE': 'Trailers', }) # returning self.data def get_data(self): return json.dumps(self.data).encode('utf-8') # Save Token after login to CoWIN def putSession(self): with open(self.mobile_no, "w") as f: f.write(self.bearerToken) # Get Token saved in file for relogin and use def getSession(self): self.set_headers() try: with open(self.mobile_no, "r") as f: self.bearerToken = f.read() self.session.headers.update({ 'Authorization': 'Bearer {}'.format(self.bearerToken) }) self.fetch_beneficiaries().json() except (FileNotFoundError,json.decoder.JSONDecodeError): self.login_cowin() def checkToken(self): # Pause job of Checking Slot # scheduler.pause_job('slot') response = self.fetch_beneficiaries() try: response.json() except json.decoder.JSONDecodeError: self.login_cowin() # Resume job of Checking Slot # scheduler.resume_job('slot') # Login to selfregistration.cowin.gov.in/ def login_cowin(self): self.data = { "secret":"U2FsdGVkX1+gGN13ULaCVtLSWmsyZwAdXXTIAvLQp2HOXrIBCcq0yyOZQqzzfiFiEYs7KoAOTK2j4qPF/sEVww==", "mobile": self.mobile_no } response = self.session.post('https://cdn-api.co-vin.in/api/v2/auth/generateMobileOTP',data=self.get_data()) if self.otp == 's' and OTP_SITE_URL is not None: requests.delete(f"{OTP_SITE_URL}/{self.mobile_no}") otpSha265 = self.get_otp() try: txn_id = response.json()['txnId'] except json.decoder.JSONDecodeError: print("Wrong OTP Entered") return self.data = { "otp":otpSha265, "txnId": txn_id } response = self.session.post('https://cdn-api.co-vin.in/api/v2/auth/validateMobileOtp',data=self.get_data()) self.bearerToken = response.json()['token'] self.session.headers.update({ 'Authorization': 'Bearer {}'.format(self.bearerToken) }) self.putSession() # Request for OTP def get_otp(self): otp_fetching_mode = "" if self.otp == 'a': otp_fetching_mode = 'Auto Mode' elif self.otp == 's': otp_fetching_mode = 'Site Mode' else: otp_fetching_mode = "Manual Mode" print(f"OTP Sent ({otp_fetching_mode}) 📲 ... ") otp = "" try: curr_msg = self.get_msg() curr_msg_body = curr_msg.get("body") for i in reversed(range(30)): last_msg = self.get_msg() last_msg_body = last_msg.get("body",'') print(f'Waiting for OTP {i} sec') self.set_cursor() 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 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: otp = re.findall("(\d{6})",last_msg_body)[0] print("\nOTP Recieved : ",otp) break time.sleep(1) except (Exception,KeyboardInterrupt) as e: print(e) if not otp: otp = input("\nEnter OTP : ") return hashlib.sha256(otp.encode('utf-8')).hexdigest() # Get Mobile last msg for otp Checking def get_msg(self): msg = {} # Get OTP using Termux:API v0.31 if self.otp == 'a': msg = subprocess.Popen( 'termux-sms-list -l 1', stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE,shell=True).communicate()[0].decode('utf-8') try: msg = json.loads(msg)[0] return msg except KeyError: raise Exception("Install Termux:API from FDroid for Auto Mode ") # 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': if OTP_SITE_URL is None: raise Exception("First Setup DB on Cloudflare \nhttps://github.com/truroshan/CloudflareCoWinDB ") res = requests.get(f"{OTP_SITE_URL}/{self.mobile_no}").json() if res.get("status"): msg['body'] = res.get('data').get("message") requests.delete(f"{OTP_SITE_URL}/{self.mobile_no}") return msg # Lastly enter OTP Manually raise Exception # Request for Current Slot Deatails ( Private Request ) def request_slot(self): todayDate = datetime.now().strftime("%d-%m-%Y") if self.checkByPincode: response = self.session.get(f'https://cdn-api.co-vin.in/api/v2/appointment/sessions/calendarByPin?pincode={self.pin}&date={todayDate}') else: # Check by District response = self.session.get(f'https://cdn-api.co-vin.in/api/v2/appointment/sessions/calendarByDistrict?district_id={self.pin}&date={todayDate}') self.requestStatus = response.status_code if response.status_code == 200: self.check_slot(response.json()) elif response.status_code == 401: print("Re-login Account : " + datetime.now().strftime("%H:%M:%S") + " 🤳") self.checkToken() self.request_slot() # Check Slot availability def check_slot(self,response): centers = response.get('centers',[]) for center in centers: for session in center.get('sessions')[self.bookToday:]: self.vacc_center = center.get('center_id') self.vacc_session = session.get("session_id") center_name = center.get('name') capacity = session.get(f'available_capacity_dose{self.dose}') session_date = session.get('date') vaccine_name = session.get('vaccine') if capacity > 1 and \ (self.vaccine in vaccine_name or self.vaccine == "ANY") and \ session.get('min_age_limit') == self.age and \ center.get('center_id') in self.center_id: self.slot_time = session.get('slots')[0] MSG = f'💉 {capacity} #{vaccine_name} / {session_date} / {center_name} 📍{self.pin}' # Send Notification via Termux:API App os.system(f"termux-notification --content '{MSG}'") BOOKED = self.book_slot() if BOOKED: # scheduler.shutdown(wait=False) print("Shutting Down CoWin Script 👩‍💻 ") exit() # When last Checked print(f"Last Checked {self.requestStatus} ✅ : " + datetime.now().strftime("%H:%M:%S") + " 🕐") self.set_cursor() # Get Solved Captcha in String def get_captcha(self): model = "eyJNTExRTExRTExRTExMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTExRTExRWk1MTFFMTFFMTFFMTFFaIjogIjAiLCAiTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTFoiOiAiMSIsICJNTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExRTExMUUxMTFFMTFFaIjogIjIiLCAiTUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTExMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExMUUxMUUxMUUxMUUxMUUxMUUxMTExRTExRTExRTExRTExRTExRTExMTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVoiOiAiMyIsICJNTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRWk1MTFFMTExRTExRTExRTExRTExRTExRTExMUUxMTFFMTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRWiI6ICI0IiwgIk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMTExMUUxMTFFMTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTExRTExRTExRTExRTExRWiI6ICI1IiwgIk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRTExMTFFMTFFMTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaIjogIjYiLCAiTUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTExRTExRTExMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFaTUxMTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExMTExRTExRTExRTExRTExRTExMUUxMTFFMTFFMTFFMTExRWiI6ICI3IiwgIk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExMUUxMUUxMUUxMUUxMTExMUUxMUUxMUUxMUUxMTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExMUUxMUUxMUUxMUUxMUUxMUVoiOiAiOCIsICJNTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaIjogIjkiLCAiTUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUVpNTExMUUxMUUxMUUxMUUxMUUxMTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTExRWiI6ICJBIiwgIk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUVpNTExRTExRTExRTExRTExMUUxMUUxMUUxMUVpNTExMUUxMTExMUUxMTFFMTFFMTFFMTFFMTFFMTFFaIjogIkIiLCAiTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVoiOiAiQyIsICJNTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMTFFMTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFaIjogIkQiLCAiTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaIjogIkUiLCAiTUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUVoiOiAiRiIsICJNTExRTExRTExRTExMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExMUUxMWiI6ICJHIiwgIk1MTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWiI6ICJIIiwgIk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVoiOiAibCIsICJNTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWiI6ICJKIiwgIk1MTFFMTFFMTFFMTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMTExMUVpNTExRTExRTExRTExMUUxMUUxMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWiI6ICJLIiwgIk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVoiOiAiTCIsICJNTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExRWiI6ICJNIiwgIk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMWk1MTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVoiOiAiTiIsICJNTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRTExRWiI6ICJPIiwgIk1MTFFMTFFMTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFaIjogIlAiLCAiTUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTExRTExMUUxMUUxMUUxMUUxMUVpNTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTExMTFFMTFFMTFFaIjogIlEiLCAiTUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMTFFMTFFMTFFaTUxMTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFaTUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFaIjogIlIiLCAiTUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVoiOiAiUyIsICJNTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWiI6ICJUIiwgIk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaIjogIlUiLCAiTUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaIjogIlYiLCAiTUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUVoiOiAiVyIsICJNTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFaIjogIlgiLCAiTUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFoiOiAiWSIsICJNTExRTExRTExRTExRTExRTExRTExRTExRTExMUUxMTFFMTFFMTFFMTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRWiI6ICJaIiwgIk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExRTExRTExRTExRWk1MTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaIjogImEiLCAiTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRWiI6ICJiIiwgIk1MTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExMUUxMUUxMUVoiOiAiYyIsICJNTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVoiOiAiZCIsICJNTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTExRWk1MTFFMTFFMTFFMTFFMTFFaTUxMUUxMTExRTExRTExRWiI6ICJlIiwgIk1MTFFMTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFaTUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTExRTExRTExMUUxMTExRTExRTExMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaIjogImYiLCAiTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMTFFMTExRTExRTExRTExMUUxMUUxMUUxMUUxMTExRTExRTExRTExRTExRTExMUUxMTFFMTFFMTExRTExMUVpNTExRTExRTExRTExRTExRTExRTExRTExRWiI6ICJnIiwgIk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExRTExMUUxMUVoiOiAiaCIsICJNTExRTExMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTFpNTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUVpNTExMTFFMTFFMTFFMTFFMTFFMTFFMTFFaIjogImkiLCAiTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExMUUxMUUxMUUxMUUxMUUxMTFFMTExMUUxMUVpNTExMUUxMUUxMUUxMUUxMUUxMUUxMUVoiOiAiaiIsICJNTExRTExRTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVoiOiAiayIsICJNTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTExRTExRWk1MTExaIjogIm0iLCAiTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVoiOiAibiIsICJNTExRTExRTExRTExRTExRTExRTExRWk1MTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVoiOiAibyIsICJNTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExMUUxMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMTExMUUxMTFFMTFFMTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxaTUxMUUxMUUxMUUxMUUxMTFFMTExRTExMUUxMUVoiOiAicCIsICJNTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFaTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVoiOiAicSIsICJNTExRTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExaTUxMTFoiOiAiciIsICJNTExMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMTExRTExRTExRTExMUUxMUVoiOiAicyIsICJNTExRTExRTExRTExRTExMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFaTUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTExRTExRTExRWiI6ICJ0IiwgIk1MTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExRTExMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMTExMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaIjogInUiLCAiTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTExRTExMUVoiOiAidiIsICJNTExRTExMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFMTFFMTFFMTFFMTExRWk1MTFFMTFFMTFFMTFFMTFFMTExRTExRTExRTExRTExMUUxMTFFMTFFMTFFMTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMWiI6ICJ3IiwgIk1MTFFMTFFMTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRWk1MTFFMTFFMTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMTFFaIjogIngiLCAiTUxMUUxMUUxMUUxMUUxMUUxMUUxMUUxMTFFMTFFaTUxMUUxMTFFMTFFMTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExMUUxMUVoiOiAieSIsICJNTExRTExRTExRTExRTExRTExRTExRTExMUUxMUUxMUUxMUUxMUUxMUVpNTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExRTExMUUxMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFMTFFaIjogInoifQ==" # Send request for Captcha data = '{}' response = self.session.post('https://cdn-api.co-vin.in/api/v2/auth/getRecaptcha', data=data) if not response.ok: self.login_cowin() return self.get_captcha() # Get Captcha Data from Json svg_data = response.json()['captcha'] soup = BeautifulSoup(svg_data,'html.parser') model = json.loads(base64.b64decode(model.encode('ascii'))) CAPTCHA = {} for path in soup.find_all('path',{'fill' : re.compile("#")}): ENCODED_STRING = path.get('d').upper() INDEX = re.findall('M(\d+)',ENCODED_STRING)[0] ENCODED_STRING = re.findall("([A-Z])", ENCODED_STRING) ENCODED_STRING = "".join(ENCODED_STRING) CAPTCHA[int(INDEX)] = model.get(ENCODED_STRING) CAPTCHA = sorted(CAPTCHA.items()) CAPTCHA_STRING = '' for char in CAPTCHA: CAPTCHA_STRING += char[1] return CAPTCHA_STRING # Book Slot for Vaccination def book_slot(self): captcha = self.get_captcha() self.data = { "center_id":self.vacc_center , "session_id":self.vacc_session, "beneficiaries":self.user_id, "slot":self.slot_time, "captcha": captcha, "dose": self.dose } response = self.session.post('https://cdn-api.co-vin.in/api/v2/appointment/schedule',data=self.get_data()) status = response.status_code if status == 200: print("🏥 Appointment scheduled successfully! 🥳 ") return True elif status == 409: 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: self.login_cowin() self.book_slot() else: print("Error in Booking Slot") print(f'{status} : {response.json()}') # Booking Method def book_now(self): self.request_slot() # Set details about Vaacination Center and User Id def setup_details(self): self.select_center() self.select_beneficiaries() # Get District Id def get_district_id(self): response = self.session.get("https://cdn-api.co-vin.in/api/v2/admin/location/states").json() print("Select State : ") for state in response.get("states",): state_id = state.get("state_id") state_name = state.get('state_name') print(f"{state_id} : {state_name}") index = input("Enter Index : ") clear_screen() response = self.session.get(f"https://cdn-api.co-vin.in/api/v2/admin/location/districts/{index}").json() print("Select District : ") for dist in response.get("districts"): dist_id = dist.get("district_id") dist_name = dist.get('district_name') print(f"{dist_id} : {dist_name}") index = input("Enter Index : ") clear_screen() return index def fetch_center(self): if self.checkByPincode: response = self.session.get( f'https://cdn-api.co-vin.in/api/v2/appointment/sessions/calendarByPin?pincode={self.pin}&date={self.todayDate}' ) else: # Check by District response = self.session.get( f'https://cdn-api.co-vin.in/api/v2/appointment/sessions/calendarByDistrict?district_id={self.pin}&date={self.todayDate}' ) return response # Select Center for Vaccination def select_center(self): response = self.fetch_center() while response.status_code != 200: print(f'Trying to fetch center detail. Please wait...') self.set_cursor() time.sleep(5) response = self.fetch_center() clear_screen() response = response.json() CENTERS = {} 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") counter = 1 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'): vaccine_name = session.get("vaccine") 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') INDEX_S.append(counter) counter += 1 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() line_break() print(""" * Select One Center input : 1 * Select Mutiple with Space input : 1 2 3 4 * Select All Center Hit Enter without Input **pass --f paid or free **pass --v vacc_name \n""") line_break() input_index = input("Enter Index's : ") if input_index != '': INDEX_S = re.findall("(\d+)",input_index) clear_screen() CENTER_ID = [] for index in INDEX_S: if CENTERS.get(int(index)): CENTER_ID.append(CENTERS.get(int(index))) self.center_id = CENTER_ID def fetch_beneficiaries(self): return self.session.get('https://cdn-api.co-vin.in/api/v2/appointment/beneficiaries') # Select User to Book Slot def select_beneficiaries(self): response = self.fetch_beneficiaries() while response.status_code != 200: print(f'Please wait...') self.set_cursor() time.sleep(5) response = self.fetch_beneficiaries() response = response.json() USERS = {} INDEX_S = [] print(f"Select User for Vaccination 👩‍👦‍👦 \n") if not response.get('beneficiaries',[]): print("No beneficiaries added in Account") exit() counter = 1 for user in response.get('beneficiaries'): if not user.get(f'dose{self.dose}_date'): print(f'{counter} : {user.get("name")}') USERS[counter] = user.get('beneficiary_reference_id') INDEX_S.append(counter) counter += 1 if counter == 1: # clear_screen() print(f"No beneficiaries available for Dose {self.dose}.") self.shutting_down() exit() print() line_break() print(""" * Select One User input : 1 * Select Mutiple User with Space input : 1 2 3 4 * Select All User Hit Enter without Input\n""") line_break() input_index = input("Enter Index's : ") if input_index != '': INDEX_S = re.findall("(\d)",input_index) clear_screen() USER_ID = [] for index in INDEX_S: if USERS.get(int(index)): USER_ID.append(USERS.get(int(index))) 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__': clear_screen() cowin = CoWinBook() fire.Fire(cowin.init) # Check for Slot # 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 # scheduler.add_job(cowin.checkToken, 'cron',id ="login", minute = f'*/3',misfire_grace_time= 30) schedule.every(3).minutes.do(cowin.checkToken) # scheduler.start() while True: schedule.run_pending() time.sleep(1)