def clear_bucket_and_send_OTP(storage_url, mobile, request_header):
    print("clearing OTP bucket: " + storage_url)
    response = requests.put(storage_url, data={})
    data = {
        "mobile":
        mobile,
        "secret":
        "U2FsdGVkX1+z/4Nr9nta+2DrVJSv7KS6VoQUSQ1ZXYDx/CJUkWxFYG6P3iM/VW+6jLQ9RDQVzp/RcZ8kbT41xw==",
    }
    print(f"Requesting OTP with mobile number {mobile}..")
    txnId = requests.post(
        url="https://cdn-api.co-vin.in/api/v2/auth/generateMobileOTP",
        json=data,
        headers=request_header,
    )

    if txnId.status_code == 200:
        txnId = txnId.json()["txnId"]
    else:
        print("Unable to Create OTP")
        print(txnId.text)
        if txnId.status_code == 403 or txnId.status_code == 429:
            handle_rate_limited()
        time.sleep(5)  # Saftey net againt rate limit
        txnId = None

    return txnId
def book_appointment(request_header,
                     details,
                     mobile,
                     generate_captcha_pref="n"):
    """
    This function
        1. Takes details in json format
        2. Attempts to book an appointment using the details
        3. Returns True or False depending on Token Validity
           a) 0 - when token is expired
           b) 1 - when token is OK but unable to book due to selected center is completely booked
           c) 2 - when token is OK but unable to book due to any other reason
    """
    try:
        valid_captcha = True
        while valid_captcha:
            # captcha = generate_captcha(request_header, generate_captcha_pref)
            # details["captcha"] = captcha

            print(
                "================================= ATTEMPTING BOOKING =================================================="
            )
            if len(details) == 5:
                resp = requests.post(BOOKING_URL,
                                     headers=request_header,
                                     json=details)
                print(f"Booking Response Code: {resp.status_code}")
                print(f"Booking Response : {resp.text}")
            else:
                resp = requests.post(RESCHEDULE_URL,
                                     headers=request_header,
                                     json=details)
                print(f"Booking Response Code: {resp.status_code}")
                print(f"Booking Response : {resp.text}")

            if (resp.status_code == 200) or (resp.status_code == 204):
                beep(WARNING_BEEP_DURATION[0], WARNING_BEEP_DURATION[1])
                print(
                    "##############    BOOKED!  ############################    BOOKED!  ##############"
                )
                print(
                    "                        Hey, Hey, Hey! It's your lucky day!                       "
                )

                try:
                    appSlipBase = (
                        APPOINTMENT_SLIP_URL +
                        f"?appointment_id={resp.json()['appointment_confirmation_no']}"
                    )
                    appslip = requests.get(appSlipBase, headers=request_header)
                    with open(
                            f"{mobile}_{resp.json()['appointment_confirmation_no']}.pdf",
                            "wb",
                    ) as appSlipPdf:
                        appSlipPdf.write(appslip.content)
                    if os.path.exists(
                            f"{mobile}_{resp.json()['appointment_confirmation_no']}.pdf"
                    ):
                        print(
                            "\nDownload Successful. Check the Current Working Directory for the Appointment Slip."
                        )
                    else:
                        print("\nAppointment Slip Download Failed...")

                except Exception as e:
                    print(str(e))

                print("\nPress any key thrice to exit program.")
                os.system("pause")
                os.system("pause")
                os.system("pause")
                sys.exit()
            elif resp.status_code == 403 or resp.status_code == 429:
                handle_rate_limited()
                pass

            elif resp.status_code == 401:
                print("TOKEN INVALID")
                return 0

            elif resp.status_code == 409:
                print(f"Response: {resp.status_code} : {resp.text}")
                try:
                    data = resp.json()
                    # Response: 409 : {"errorCode":"APPOIN0040","error":"This vaccination center is completely booked for the selected date. Please try another date or vaccination center."}
                    if data.get("errorCode", "") == "APPOIN0040":
                        return 1
                except Exception as e:
                    print(str(e))
                return 2
            elif resp.status_code == 400:
                print(f"Response: {resp.status_code} : {resp.text}")
                # Response: 400 : {"errorCode":"APPOIN0044", "error":"Please enter valid security code"}
                pass
            elif resp.status_code >= 500:
                print(f"Response: {resp.status_code} : {resp.text}")
                # Server error at the time of high booking
                # Response: 500 : {"message":"Throughput exceeds the current capacity of your table or index.....","code":"ThrottlingException","statusCode":400,"retryable":true}
                pass
            else:
                print(f"Response: {resp.status_code} : {resp.text}")
                return 2

    except Exception as e:
        print(str(e))
        beep(WARNING_BEEP_DURATION[0], WARNING_BEEP_DURATION[1])
def check_by_pincode(
    find_option,
    request_header,
    vaccine_type,
    location_dtls,
    start_date,
    minimum_slots,
    min_age_booking,
    fee_type,
    dose_num,
):
    """
    This function
        1. Takes details required to check vaccination calendar
        2. Filters result by minimum number of slots available
        3. Returns False if token is invalid
        4. Returns list of vaccination centers & slots if available
    """
    try:
        print(
            "==================================================================================="
        )
        today = datetime.datetime.today()
        base_url = CALENDAR_URL_PINCODE if find_option == 1 else FIND_URL_PINCODE

        if vaccine_type:
            base_url += f"&vaccine={vaccine_type}"

        options = []
        for location in location_dtls:
            resp = requests.get(base_url.format(location["pincode"],
                                                start_date),
                                headers=request_header)

            if resp.status_code == 403 or resp.status_code == 429:
                handle_rate_limited()
                return False

            elif resp.status_code == 401:
                print("TOKEN INVALID")
                return False

            elif resp.status_code == 200:
                resp = resp.json()

                if find_option == 2:
                    resp = correct_schema(resp)

                resp = filter_centers_by_age(resp, min_age_booking)

                if "centers" in resp:
                    print(
                        f"Centers available in {location['pincode']} {'from' if find_option == 1 else 'for'} {start_date} as of {today.strftime('%Y-%m-%d %H:%M:%S')}: {len(resp['centers'])}"
                    )
                    options += viable_options(resp, minimum_slots,
                                              min_age_booking, fee_type,
                                              dose_num)

            else:
                print(resp.status_code)
                print(resp.headers)
                print(resp.text)

        for location in location_dtls:
            if int(location["pincode"]) in [
                    option["pincode"] for option in options
            ]:
                for _ in range(2):
                    beep(location["alert_freq"], 150)

        return options

    except Exception as e:
        print(str(e))
        beep(WARNING_BEEP_DURATION[0], WARNING_BEEP_DURATION[1])
def generate_token_OTP_manual(mobile, request_header):
    """
    This function generate OTP and returns a new token
    """

    if not mobile:
        print("Mobile number cannot be empty")
        os.system("pause")
        sys.exit()

    valid_token = False
    while not valid_token:
        try:
            data = {
                "mobile":
                mobile,
                "secret":
                "U2FsdGVkX1+z/4Nr9nta+2DrVJSv7KS6VoQUSQ1ZXYDx/CJUkWxFYG6P3iM/VW+6jLQ9RDQVzp/RcZ8kbT41xw==",
            }
            txnId = requests.post(url=OTP_PRO_URL,
                                  json=data,
                                  headers=request_header)

            if txnId.status_code == 200:
                print(
                    f"Successfully requested OTP for mobile number {mobile} at {datetime.datetime.today()}.."
                )
                txnId = txnId.json()["txnId"]

                OTP = input(
                    "Enter OTP (If this takes more than 2 minutes, press Enter to retry): "
                )
                if OTP:
                    data = {
                        "otp": sha256(str(OTP).encode("utf-8")).hexdigest(),
                        "txnId": txnId,
                    }
                    print(f"Validating OTP..")

                    token = requests.post(
                        url=
                        "https://cdn-api.co-vin.in/api/v2/auth/validateMobileOtp",
                        json=data,
                        headers=request_header,
                    )
                    if token.status_code == 200:
                        token = token.json()["token"]
                        print(f"Token Generated: {token}")
                        valid_token = True
                        return token

                    else:
                        print("Unable to Validate OTP")
                        print(f"Response: {token.text}")

                        retry = input(
                            f"Retry with {mobile} ? (y/n Default y): ")
                        retry = retry if retry else "y"
                        if retry == "y":
                            pass
                        else:
                            sys.exit()

            else:
                print("Unable to Generate OTP")
                print(txnId.status_code, txnId.text)
                if txnId.status_code == 403 or txnId.status_code == 429:
                    handle_rate_limited()

                retry = input(f"Retry with {mobile} ? (y/n Default y): ")
                retry = retry if retry else "y"
                if retry == "y":
                    pass
                else:
                    sys.exit()

        except Exception as e:
            print(str(e))