|
| 1 | +#!/usr/bin/env python3 |
| 2 | +import requests |
| 3 | +import json |
| 4 | +from datetime import datetime |
| 5 | +from telegram_bot_rest_call_bot import * |
| 6 | +# from telegram_bot_test_env import * |
| 7 | +from fake_useragent import UserAgent |
| 8 | +from CenterDetails import CenterInfo |
| 9 | +import schedule |
| 10 | +import time |
| 11 | +import logging |
| 12 | +import argparse |
| 13 | +import pickle |
| 14 | + |
| 15 | +logging.basicConfig(filename='myappbUrban-prod.log', format='%(asctime)s : %(levelname)s - %(message)s', level=logging.INFO, |
| 16 | + datefmt='%m/%d/%Y %I:%M:%S %p') |
| 17 | + |
| 18 | +parser = argparse.ArgumentParser() |
| 19 | +parser.add_argument("district_id", type=int, help='an integer for district id ') |
| 20 | +parser.add_argument("age", type=int, help='an integer for the user age') |
| 21 | +parser.add_argument("--chatId", type=int, help='an optional integer for the telegram chat id ') |
| 22 | +args = parser.parse_args() |
| 23 | + |
| 24 | +save_state_timer = 0 |
| 25 | +centerList_Global = [] |
| 26 | + |
| 27 | + |
| 28 | +def cowinApiCall(district_id, age, chatId): |
| 29 | + age_group = "18 to 44" if age < 45 else "above 45" |
| 30 | + # default chatId (-1001172971393) - (cowin U45 Blore-Dev) if chatID is not provided |
| 31 | + channel_chatId = "-1001172971393" if chatId is None else chatId |
| 32 | + logging.info('-------xxxxxx------Started cowinApiCall ---------xxxxxxx------ for district id ' |
| 33 | + + str(district_id) + ' and age group ' + age_group + " chat id : " + str(channel_chatId) + '\n') |
| 34 | + temp_user_agent = UserAgent() |
| 35 | + browser_header = {'User-Agent': temp_user_agent.random} |
| 36 | + systemDate = datetime.today().strftime('%d-%m-%Y') |
| 37 | + # district_id = 294 # 294- BBMP |
| 38 | + centerList = [] |
| 39 | + global session_id |
| 40 | + global centerList_Global |
| 41 | + |
| 42 | + getStatesListUrl = "https://cdn-api.co-vin.in/api/v2/admin/location/states" |
| 43 | + calendarByDistrictUrl = "https://cdn-api.co-vin.in/api/v2/appointment/sessions/calendarByDistrict" |
| 44 | + |
| 45 | + queryparam = {'district_id': district_id, 'date': systemDate} |
| 46 | + try: |
| 47 | + response = requests.get(calendarByDistrictUrl, |
| 48 | + headers=browser_header, params=queryparam, timeout=4) |
| 49 | + logging.info('response: ' + str(response)) |
| 50 | + if response.ok: |
| 51 | + resp_json = response.json() |
| 52 | + if 'centers' in resp_json: |
| 53 | + logging.debug('Available on: ' + str(systemDate) + |
| 54 | + ' for ' + age_group + ' age group ,user age: ' + str(age)) |
| 55 | + for center in resp_json["centers"]: |
| 56 | + for session in center["sessions"]: |
| 57 | + if session["min_age_limit"] <= age: |
| 58 | + name = center["name"] |
| 59 | + block = center["block_name"] |
| 60 | + pincode = center["pincode"] |
| 61 | + feeType = center["fee_type"] |
| 62 | + capacity = session["available_capacity"] |
| 63 | + dose1 = session["available_capacity_dose1"] |
| 64 | + dose2 = session["available_capacity_dose2"] |
| 65 | + logging.debug('\t ' + center["name"]) |
| 66 | + logging.debug('\t ' + center["block_name"]) |
| 67 | + logging.debug('\t Price: ' + center["fee_type"]) |
| 68 | + logging.debug('\t Available Capacity: ' + |
| 69 | + str(session["available_capacity"])) |
| 70 | + logging.debug('\t Available Dose 1: ' + |
| 71 | + str(session["available_capacity_dose1"])) |
| 72 | + logging.debug('\t Available Dose 2: ' + |
| 73 | + str(session["available_capacity_dose2"])) |
| 74 | + sessionId = session["session_id"] |
| 75 | + logging.debug('\t session ID : ' + |
| 76 | + str(session["session_id"])) |
| 77 | + if (session["vaccine"] != ''): |
| 78 | + logging.debug('\t Vaccine: ' + session["vaccine"]) |
| 79 | + vaccine = session["vaccine"] |
| 80 | + logging.debug('\t min age limit : ' + |
| 81 | + str(session["min_age_limit"])) |
| 82 | + logging.debug('\t date: ' + |
| 83 | + str(session["date"])) |
| 84 | + ageLimit = session["min_age_limit"] |
| 85 | + date = session["date"] |
| 86 | + logging.debug('----------------------------------- \n\n ') |
| 87 | + centerList.append( |
| 88 | + CenterInfo(name, block, pincode, feeType, capacity, dose1, dose2, sessionId, vaccine, |
| 89 | + ageLimit, date)) |
| 90 | + else: |
| 91 | + logging.error("No available centers on ", systemDate) |
| 92 | + if centerList: |
| 93 | + for center in centerList: |
| 94 | + if isNotificationRequired(center): |
| 95 | + logging.info(' slots available - sending telegram msg: center name : ' + str(center.name) + |
| 96 | + ' sessionId: ' + str(center.sessionId)) |
| 97 | + telegram_bot_sendtext("Center : " + center.name + "\n" |
| 98 | + + "Block : " + center.blockName + "\n" |
| 99 | + + "pincode : " + str(center.pincode) + "\n" |
| 100 | + + "available capacity : " + str(center.capacity) + "\n" |
| 101 | + + "available Dose1 : " + str(center.dose1) + "\n" |
| 102 | + + "available Dose2 : " + str(center.dose2) + "\n" |
| 103 | + + "vaccine : " + str(center.vaccine) + "\n" |
| 104 | + + "age limit : " + str(age_group) + "\n" |
| 105 | + + "Date : " + str(center.date) + "\n", str(channel_chatId)) |
| 106 | + logging.info('-------------------------------------- \n\n ') |
| 107 | + else: |
| 108 | + # telegram_bot_sendtext("No vaccine available at center " + center.name) |
| 109 | + logging.debug("No vaccine available at center " + center.name) |
| 110 | + logging.debug('-------------------------------------- \n\n ') |
| 111 | + else: |
| 112 | + logging.error("No available centers on ", systemDate) |
| 113 | + saveGlobalListState() |
| 114 | + logging.debug('-------xxxxxxxx--------- END of cowinApiCall ----------xxxxx--------- \n\n ') |
| 115 | + |
| 116 | + except requests.exceptions.HTTPError as errh: |
| 117 | + logging.info("Http Error:", str(errh)) |
| 118 | + except ( |
| 119 | + requests.ConnectionError, |
| 120 | + requests.exceptions.ConnectionError, |
| 121 | + requests.exceptions.ReadTimeout, |
| 122 | + requests.exceptions.Timeout, |
| 123 | + requests.exceptions.ConnectTimeout |
| 124 | + ) as errc: |
| 125 | + logging.info("Error Connecting:", str(errc)) |
| 126 | + except requests.exceptions.Timeout as errt: |
| 127 | + logging.info("Timeout Error:", str(errt)) |
| 128 | + except requests.exceptions.RequestException as err: |
| 129 | + logging.info("OOps: Something Else", str(err)) |
| 130 | + |
| 131 | + |
| 132 | +def isNotificationRequired(center): |
| 133 | + global centerList_Global |
| 134 | + sentNotification = False |
| 135 | + logging.info("Start -- for centre: " + center.name + |
| 136 | + " for date : " + str(center.date) + " : session id : " + center.sessionId + |
| 137 | + " centerList_Global size: " + str(len(centerList_Global))) |
| 138 | + if centerList_Global: |
| 139 | + if center in centerList_Global: |
| 140 | + # if any(gl.sessionId == center.sessionId for gl in centerList_Global): |
| 141 | + saved_elements = getSavedCenter(center) |
| 142 | + logging.debug(" center present in global list: saved capacity : " |
| 143 | + + str(saved_elements.capacity) + " center capacity : " + str(center.capacity)) |
| 144 | + # global list contains center list |
| 145 | + # chk capacity if latest capacity > 1 then don't update the global list nor sent notification |
| 146 | + if center.capacity > 1: |
| 147 | + if center.capacity > saved_elements.capacity: |
| 148 | + logging.info("center capacity increased - Send Notification: updated global list") |
| 149 | + updateCapacity(center) |
| 150 | + sentNotification = True |
| 151 | + logging.debug("centerList_Global size after updating : " + str(len(centerList_Global))) |
| 152 | + else: |
| 153 | + logging.debug("new capacity not added - No Notification send ") |
| 154 | + sentNotification = False |
| 155 | + elif center.capacity == 0: |
| 156 | + logging.debug("capacity is 0 all slots booked , remove it from global list and wait for new slots") |
| 157 | + logging.debug("remove from global list: len before: " + str(len(centerList_Global))) |
| 158 | + centerList_Global.remove(center) |
| 159 | + logging.debug("remove from global list: len after: " + str(len(centerList_Global))) |
| 160 | + sentNotification = False |
| 161 | + else: |
| 162 | + # if not present in global list and capacity > 1 add in global list and send notification |
| 163 | + if center.capacity > 1: |
| 164 | + logging.debug("Not present in global list and capacity > 0 add in global list and send notification") |
| 165 | + centerList_Global.append(center) |
| 166 | + sentNotification = True |
| 167 | + else: |
| 168 | + logging.debug("Not present in global list and capacity is 0 No action required") |
| 169 | + else: |
| 170 | + # if global list is empty then send notification if capacity > 1 |
| 171 | + retrieveGlobalListState() |
| 172 | + if centerList_Global and center.capacity > 1: |
| 173 | + logging.debug("global list is empty then send notification for capacity > 0") |
| 174 | + sentNotification = True |
| 175 | + centerList_Global.append(center) |
| 176 | + logging.info("Notification for the centre :" + center.name + " is: " + str(sentNotification) + '\n') |
| 177 | + logging.debug('-- End checking notification for centre: -------------' + center.name) |
| 178 | + return sentNotification |
| 179 | + |
| 180 | + |
| 181 | +def getSavedCenter(center): |
| 182 | + for savedCenter in centerList_Global: |
| 183 | + if center == savedCenter: |
| 184 | + return savedCenter |
| 185 | + |
| 186 | + |
| 187 | +def updateCapacity(center): |
| 188 | + for savedCenter in centerList_Global: |
| 189 | + if center == savedCenter: |
| 190 | + savedCenter.capacity = center.capacity |
| 191 | + |
| 192 | + |
| 193 | +def saveGlobalListState(): |
| 194 | + global centerList_Global |
| 195 | + global save_state_timer |
| 196 | + # 2 hours |
| 197 | + if save_state_timer == 7200: |
| 198 | + outputFile = open('global_list_bUrban.dat', 'wb') |
| 199 | + pickle.dump(centerList_Global, outputFile) |
| 200 | + outputFile.close() |
| 201 | + logging.info("state saved saveGlobalList size: " + str(len(centerList_Global))) |
| 202 | + # reset the timer to zero |
| 203 | + save_state_timer = 0 |
| 204 | + save_state_timer += 5 |
| 205 | + |
| 206 | + |
| 207 | +def retrieveGlobalListState(): |
| 208 | + global centerList_Global |
| 209 | + inputFile = open('global_list_bUrban.dat', 'rb') |
| 210 | + endOfFile = False # It is used to indicate end of file |
| 211 | + while not endOfFile: |
| 212 | + try: |
| 213 | + list = pickle.load(inputFile) |
| 214 | + centerList_Global = list |
| 215 | + logging.info("retrieved Global list length : " + str(len(centerList_Global))) |
| 216 | + except EOFError: |
| 217 | + # When end of file has reached EOFError will be thrown |
| 218 | + # and we are setting endOfFile to True to end while loop |
| 219 | + endOfFile = True |
| 220 | + |
| 221 | + inputFile.close() # Close the file |
| 222 | + |
| 223 | + |
| 224 | +cowinApiCall(args.district_id, args.age, args.chatId) |
| 225 | + |
| 226 | +# scheduler to call cowin api after x sec |
| 227 | +schedule.every(30).seconds.do(cowinApiCall, args.district_id, args.age, args.chatId) |
| 228 | + |
| 229 | +while True: |
| 230 | + schedule.run_pending() |
| 231 | + time.sleep(1) |
0 commit comments