def check_stock(self, asin, reserve, retry=0): if retry > DEFAULT_MAX_ATC_TRIES: log.info("max add to cart retries hit, returning to asin check") return False if self.checkshipping: if self.used: f = furl(AMAZON_URLS["OFFER_URL"] + asin) else: f = furl(AMAZON_URLS["OFFER_URL"] + asin + "/ref=olp_f_new&f_new=true") else: if self.used: f = furl(AMAZON_URLS["OFFER_URL"] + asin + "/f_freeShipping=on") else: f = furl(AMAZON_URLS["OFFER_URL"] + asin + "/ref=olp_f_new&f_new=true&f_freeShipping=on") try: while True: try: try: searching_update() except Exception: pass self.driver.get(f.url) break except Exception: log.error( "Failed to get the URL, were in the exception now.") time.sleep(3) pass elements = self.driver.find_elements_by_xpath( '//*[@name="submit.addToCart"]') prices = self.driver.find_elements_by_xpath( '//*[@class="a-size-large a-color-price olpOfferPrice a-text-bold"]' ) shipping = self.driver.find_elements_by_xpath( '//*[@class="a-color-secondary"]') except Exception as e: log.error(e) return None in_stock = False for i in range(len(elements)): price = parse_price(prices[i].text) if SHIPPING_ONLY_IF in shipping[i].text: ship_price = parse_price("0") else: ship_price = parse_price(shipping[i].text) ship_float = ship_price.amount price_float = price.amount if price_float is None: return False if ship_float is None or not self.checkshipping: ship_float = 0 if (ship_float + price_float) <= reserve or math.isclose( (price_float + ship_float), reserve, abs_tol=0.01): log.info("Item in stock and under reserve!") log.info("clicking add to cart") try: buy_update() except: pass elements[i].click() time.sleep(self.page_wait_delay()) if self.driver.title in SHOPING_CART_TITLES: return True else: log.info("did not add to cart, trying again") log.debug(f"failed title was {self.driver.title}") if self.no_screenshots: self.notification_handler.send_notification( "failed-atc") else: self.save_screenshot("failed-atc") self.save_page_source("failed-atc") in_stock = self.check_stock(asin=asin, reserve=reserve, retry=retry + 1) return in_stock
def check_stock(self, asin, reserve_min, reserve_max, retry=0): if retry > DEFAULT_MAX_ATC_TRIES: log.info("max add to cart retries hit, returning to asin check") return False if self.checkshipping: if self.used: f = furl(AMAZON_URLS["OFFER_URL"] + asin) else: f = furl(AMAZON_URLS["OFFER_URL"] + asin + "/ref=olp_f_new&f_new=true") else: if self.used: f = furl(AMAZON_URLS["OFFER_URL"] + asin + "/f_freeShipping=on") else: f = furl( AMAZON_URLS["OFFER_URL"] + asin + "/ref=olp_f_new&f_new=true&f_freeShipping=on" ) fail_counter = 0 presence.searching_update() while True: try: self.get_page(f.url) break except Exception: fail_counter += 1 log.error(f"Failed to load the offer URL {fail_counter} times.") if fail_counter < DEFAULT_MAX_URL_FAIL: log.error( f"WebDriver will restart if it fails {DEFAULT_MAX_URL_FAIL} times. Retrying now..." ) time.sleep(3) else: log.info( "Attempting to delete and recreate current chrome instance" ) if not self.delete_driver(): log.error("Failed to delete chrome processes") log.error("Please restart bot") self.send_notification( message="Bot Failed, please restart bot", page_name="Bot Failed", take_screenshot=False, ) raise RuntimeError("Failed to restart bot") elif not self.create_driver(): log.error("Failed to recreate webdriver processes") log.error("Please restart bot") self.send_notification( message="Bot Failed, please restart bot", page_name="Bot Failed", take_screenshot=False, ) raise RuntimeError("Failed to restart bot") else: # deleted driver and recreated it succesfully log.info( "WebDriver recreated successfully. Returning back to stock check" ) return False timeout = self.get_timeout() while True: atc_buttons = self.driver.find_elements_by_xpath( '//*[@name="submit.addToCart"]' ) if atc_buttons: # Early out if we found buttons break test = None try: test = self.driver.find_element_by_xpath( '//*[@id="olpOfferList"]/div/p' ) except exceptions.NoSuchElementException: pass if test and (test.text in NO_SELLERS): return False if time.time() > timeout: log.info(f"failed to load page for {asin}, going to next ASIN") return False timeout = self.get_timeout() while True: prices = self.driver.find_elements_by_xpath( '//*[@class="a-size-large a-color-price olpOfferPrice a-text-bold"]' ) if prices: break if time.time() > timeout: log.info(f"failed to load prices for {asin}, going to next ASIN") return False shipping = [] if self.checkshipping: timeout = self.get_timeout() while True: shipping = self.driver.find_elements_by_xpath( '//*[@class="a-color-secondary"]' ) if shipping: break if time.time() > timeout: log.info(f"failed to load shipping for {asin}, going to next ASIN") return False in_stock = False for idx, atc_button in enumerate(atc_buttons): try: price = parse_price(prices[idx].text) except IndexError: log.debug("Price index error") return False try: if self.checkshipping: if SHIPPING_ONLY_IF in shipping[idx].text: ship_price = parse_price("0") else: ship_price = parse_price(shipping[idx].text) else: ship_price = parse_price("0") except IndexError: log.debug("shipping index error") return False ship_float = ship_price.amount price_float = price.amount if price_float is None: return False if ship_float is None or not self.checkshipping: ship_float = 0 if ( (ship_float + price_float) <= reserve_max or math.isclose((price_float + ship_float), reserve_max, abs_tol=0.01) ) and ( (ship_float + price_float) >= reserve_min or math.isclose((price_float + ship_float), reserve_min, abs_tol=0.01) ): log.info("Item in stock and in reserve range!") log.info("clicking add to cart") self.notification_handler.play_notify_sound() if self.detailed: self.send_notification( message=f"Found Stock ASIN:{asin}", page_name="Stock Alert", take_screenshot=self.take_screenshots, ) presence.buy_update() current_title = self.driver.title # log.info(f"current page title is {current_title}") try: atc_button.click() except IndexError: log.debug("Index Error") return False self.wait_for_page_change(current_title) # log.info(f"page title is {self.driver.title}") if self.driver.title in SHOPING_CART_TITLES: return True else: log.info("did not add to cart, trying again") log.debug(f"failed title was {self.driver.title}") self.send_notification( "Failed Add to Cart", "failed-atc", self.take_screenshots ) self.save_page_source("failed-atc") in_stock = self.check_stock( asin=asin, reserve_max=reserve_max, reserve_min=reserve_min, retry=retry + 1, ) return in_stock