Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 55 additions & 6 deletions vaccinewatcher/watcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def __init__(self):
self.chrome_options = webdriver.ChromeOptions()
self.chrome_options.add_argument("--disable-gpu")
self.chrome_options.add_argument("--disable-software-rasterizer")
self.chrome_options.add_argument("--headless")
#self.chrome_options.add_argument("--headless")
self.chrome_options.add_argument("--disable-dev-shm-usage")
self.chrome_options.add_argument("--window-size=1920x1080")
self.chrome_options.add_argument("--disable-setuid-sandbox")
Expand Down Expand Up @@ -100,25 +100,27 @@ class Config:
]
_avail_links = {
'cvs': 'https://www.cvs.com//vaccine/intake/store/cvd-schedule.html?icid=coronavirus-lp-vaccine-sd-statetool',
'wg': 'https://www.walgreens.com/findcare/vaccination/covid-19?ban=covid_scheduler_brandstory_main_March2021'
'wg': 'https://www.walgreens.com/findcare/vaccination/covid-19?ban=covid_scheduler_brandstory_main_March2021',
'kroger': 'https://www.kroger.com/rx/covid-eligibility'
}

class VaccineWatcher:
def __init__(self, config, freq_secs=600, hook=None, check_walgreens=True, check_cvs=True, send_data=True, always_send=False, verbose=False):
def __init__(self, config, freq_secs=600, hook=None, check_walgreens=True, check_cvs=True, check_kroger=True, send_data=True, always_send=False, verbose=False):
self.config = Config(**config)
self.freq = freq_secs
self.send_data = send_data
self.always_send = always_send
self.hook = hook
self.verbose = verbose
self._last_status = {'walgreens': {'available': False, 'data': None, 'timestamp': None}, 'cvs': {'available': False, 'data': None, 'timestamp': None}}
self._last_status = {'walgreens': {'available': False, 'data': None, 'timestamp': None}, 'cvs': {'available': False, 'data': None, 'timestamp': None}, 'kroger': {'available': False, 'data': None, 'timestamp': None}}
self._check_wg = check_walgreens
self._check_cvs = check_cvs
self._check_kroger = check_kroger
self.api = Browser()
self.browser = self.api.browser
self.alive = True
self.dactive = False
logger.log(f'Initialized VaccineWatcher with {self.config}. Will Check every {self.freq} secs. Walgreens: {self._check_wg}. CVS: {self._check_cvs}\nCall .run() to start daemon')
logger.log(f'Initialized VaccineWatcher with {self.config}. Will Check every {self.freq} secs. Walgreens: {self._check_wg}. CVS: {self._check_cvs}. Kroger: {self._check_kroger}.\nCall .run() to start daemon')

def _wg_parser(self, resp):
data = json.loads(resp.body.decode('utf-8'))
Expand Down Expand Up @@ -180,6 +182,49 @@ def check_cvs(self):
return self._cvs_parser(r.response)
return None

def _kroger_parser(self):
data = json.loads(resp.body.decode('utf-8'))['responsePayloadData']['data'][self.config.state_abbr]
for item in data:
if item['city'] == self.config.city.upper():
self._last_status['cvs']['data'] = item
if item['status'] == 'Available':
msg = f'Kroger has Available Appointments in {item["city"]}, {item["state"]}'
msg += f'\nPlease Visit: {_avail_links["kroger"]} to schedule.'
self._call_hook(msg)
logger.log(msg)
return True
if self.verbose:
msg = f'Results for Kroger: {item}'
logger.log(msg)
return False

def check_kroger(self):
self.browser.visit('https://www.kroger.com/rx/covid-eligibility')
time.sleep(3)
self.browser.get_element(text='I Agree').click()
time.sleep(3)
self.browser.get_element(text='No').click()
time.sleep(3)
self.browser.get_element(class_name="kds-Select").get_element(value=self.config.state_abbr).select()
time.sleep(2)
self.browser.get_element(name="Date of Birth").fill("01/01/1980")
time.sleep(1)
self.browser.get_button(text="Submit").click()
time.sleep(2)
self.browser.get_element(class_name="Attachment-ButtonGroup.not-allowed").get_button(text='No').click() # Not able to click the "No" button. =/
time.sleep(1)
self.browser.get_element(class_name="Attachment-ButtonGroup", wait=10).click()
time.sleep(2)
self.browser.get_element(class_name="Attachment-ButtonGroup").click() # clicking the submit button takes you to a new url https://www.kroger.com/rx/covid-vaccine
time.sleep(2)
self.browser.get_element(class_name="kds-Input").fill(self.config.zipcode)
time.sleep(2)
self.browser.get_element(class_name="SearchOverlay").click() #found this to be "SearchOverlay" based on error message, but I am not sure how to verify.
time.sleep(5) #increased timeout to see if that makes a difference
if self.browser.get_element(class_name="MultipleLocationScheduler-sortingButton") == True: #stuck here
return self._kroger_parser()
return None

def run(self):
if not self.dactive:
t = threading.Thread(target=self._daemon, daemon=True)
Expand Down Expand Up @@ -211,6 +256,9 @@ def _daemon(self):
if self._check_wg:
self._last_status['walgreens']['available'] = self.check_wg()
self._last_status['walgreens']['timestamp'] = create_timestamp()
if self._check_kroger:
self._last_status['kroger']['available'] = self.check_kroger()
self._last_status['kroger']['timestamp'] = create_timestamp()
self._call_hook()
self.api.should_reset()
time.sleep(self.freq)
Expand Down Expand Up @@ -286,13 +334,14 @@ def cli():

parser.add_argument('--no-cvs', dest='cvs', default=True, action='store_false', help='Disable CVS Search.')
parser.add_argument('--no-wg', dest='wg', default=True, action='store_false', help='Disable Walgreens Search.')
parser.add_argument('--no-kroger', dest='kroger', default=True, action='store_false', help='Disable Kroger Search.')
parser.add_argument('--verbose', dest='verbose', default=False, action='store_true', help='Enable verbosity. Will log results regardless of status')
args = parser.parse_args()
params = {'city': args.city.capitalize(), 'state': args.state.capitalize(), 'state_abbr': args.state_abbr.upper(), 'zipcode': args.zipcode}
hook = None
if args.zapierhook:
hook = ZapierWebhook(args.zapierhook)
watcher = get_vaccine_watcher(config=params, freq_secs=args.freq, hook=hook, check_walgreens=args.wg, check_cvs=args.cvs, verbose=args.verbose)
watcher = get_vaccine_watcher(config=params, freq_secs=args.freq, hook=hook, check_walgreens=args.wg, check_cvs=args.cvs, check_kroger=args.kroger, verbose=args.verbose)
watcher.run()
while True:
try:
Expand Down