Skip to content

Commit

Permalink
Merge pull request #740 from Hari-Nagarajan/feature-buyitnow
Browse files Browse the repository at this point in the history
Feature buyitnow
  • Loading branch information
DakkJaniels committed Apr 30, 2021
2 parents f677789 + 10a58f3 commit 52faa55
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 51 deletions.
8 changes: 4 additions & 4 deletions cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,10 @@ def main():
help="Purge Amazon credentials and prompt for new credentials",
)
@click.option(
"--alt-offers",
"--alt-checkout",
is_flag=True,
default=False,
help="Directly hit the offers page. Preferred, but deprecated by Amazon.",
help="Use old add to cart method. Not preferred",
)
@click.option(
"--captcha-wait",
Expand All @@ -217,7 +217,7 @@ def amazon(
shipping_bypass,
clean_profile,
clean_credentials,
alt_offers,
alt_checkout,
captcha_wait,
):
notification_handler.sound_enabled = not disable_sound
Expand Down Expand Up @@ -250,7 +250,7 @@ def amazon(
encryption_pass=p,
log_stock_check=log_stock_check,
shipping_bypass=shipping_bypass,
alt_offers=alt_offers,
alt_checkout=alt_checkout,
wait_on_captcha_fail=captcha_wait,
)
try:
Expand Down
159 changes: 113 additions & 46 deletions stores/amazon.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

import utils.selenium_utils
from utils import discord_presence as presence
from utils.debugger import debug
from utils.logger import log
Expand Down Expand Up @@ -111,6 +112,7 @@ def __init__(
shipping_bypass=False,
alt_offers=False,
wait_on_captcha_fail=False,
alt_checkout=False,
):
self.notification_handler = notification_handler
self.asin_list = []
Expand Down Expand Up @@ -143,6 +145,7 @@ def __init__(
self.unknown_title_notification_sent = False
self.alt_offers = alt_offers
self.wait_on_captcha_fail = wait_on_captcha_fail
self.alt_checkout = alt_checkout

presence.enabled = not disable_presence

Expand Down Expand Up @@ -264,40 +267,46 @@ def run(self, delay=DEFAULT_REFRESH_DELAY, test=False):
while continue_stock_check:
self.unknown_title_notification_sent = False
asin = self.run_asins(delay)
# found something in stock and under reserve
# initialize loop limiter variables
self.try_to_checkout = True
self.checkout_retry = 0
self.order_retry = 0
loop_iterations = 0
self.great_success = False
while self.try_to_checkout:
try:
self.navigate_pages(test)
# if for some reason page transitions in the middle of checking elements, don't break the program
except sel_exceptions.StaleElementReferenceException:
pass
# if successful after running navigate pages, remove the asin_list from the list
if (
not self.try_to_checkout
and not self.single_shot
and self.great_success
):
self.remove_asin_list(asin)
# checkout loop limiters
elif self.checkout_retry > DEFAULT_MAX_PTC_TRIES:
self.try_to_checkout = False
self.fail_to_checkout_note()
elif self.order_retry > DEFAULT_MAX_PYO_TRIES:
self.try_to_checkout = False
self.fail_to_checkout_note()
loop_iterations += 1
if loop_iterations > DEFAULT_MAX_CHECKOUT_LOOPS:
self.fail_to_checkout_note()
self.try_to_checkout = False
# if no items left it list, let loop end
if not self.asin_list:
continue_stock_check = False
# New normal (buy it now)
if not self.alt_checkout:
self.remove_asin_list(asin)
if not self.asin_list or self.single_shot:
continue_stock_check = False
else:
# found something in stock and under reserve
# initialize loop limiter variables
self.try_to_checkout = True
self.checkout_retry = 0
self.order_retry = 0
loop_iterations = 0
self.great_success = False
while self.try_to_checkout:
try:
self.navigate_pages(test)
# if for some reason page transitions in the middle of checking elements, don't break the program
except sel_exceptions.StaleElementReferenceException:
pass
# if successful after running navigate pages, remove the asin_list from the list
if (
not self.try_to_checkout
and not self.single_shot
and self.great_success
):
self.remove_asin_list(asin)
# checkout loop limiters
elif self.checkout_retry > DEFAULT_MAX_PTC_TRIES:
self.try_to_checkout = False
self.fail_to_checkout_note()
elif self.order_retry > DEFAULT_MAX_PYO_TRIES:
self.try_to_checkout = False
self.fail_to_checkout_note()
loop_iterations += 1
if loop_iterations > DEFAULT_MAX_CHECKOUT_LOOPS:
self.fail_to_checkout_note()
self.try_to_checkout = False
# if no items left it list, let loop end
if not self.asin_list:
continue_stock_check = False
runtime = time.time() - self.start_time
log.info(f"FairGame bot ran for {runtime} seconds.")
time.sleep(10) # add a delay to shut stuff done
Expand Down Expand Up @@ -775,18 +784,28 @@ def check_stock(self, asin, reserve_min, reserve_max, retry=0):
if offering_id_elements:
log.info("Attempting Add To Cart with offer ID...")
offering_id = offering_id_elements[0].get_attribute("value")
if self.attempt_atc(
offering_id, max_atc_retries=DEFAULT_MAX_ATC_TRIES
):
return True
if not self.alt_checkout:
if self.buy_it_now(offering_id, max_atc_retries=20):
return True
else:
self.send_notification(
"Failed Buy it Now ",
"failed-BIN",
self.take_screenshots,
)
self.save_page_source("failed-atc")
return False
else:
self.send_notification(
"Failed Add to Cart after {max-atc-retries}",
"failed-atc",
self.take_screenshots,
)
self.save_page_source("failed-atc")
return False
if self.attempt_atc(offering_id):
return True
else:
self.send_notification(
"Failed ATC ",
"failed-ATC",
self.take_screenshots,
)
self.save_page_source("failed-atc")
return False
else:
log.error(
"Unable to find offering ID to add to cart. Using legacy mode."
Expand Down Expand Up @@ -854,6 +873,54 @@ def check_stock(self, asin, reserve_min, reserve_max, retry=0):
log.info(f"Offers exceed price range ({reserve_min:.2f}-{reserve_max:.2f})")
return in_stock

def buy_it_now(self, offering_id, max_atc_retries=DEFAULT_MAX_ATC_TRIES):
retry = 0
successful = False
while not successful:
buy_it_now_url = f"https://{self.amazon_website}/checkout/turbo-initiate?ref_=dp_start-bbf_1_glance_buyNow_2-1&pipelineType=turbo&weblab=RCX_CHECKOUT_TURBO_DESKTOP_NONPRIME_87784&temporaryAddToCart=1&offerListing.1={offering_id}&quantity.1=1"
with self.wait_for_page_content_change():
self.driver.get(buy_it_now_url)
timeout = self.get_timeout(5)
while self.driver.title == "" and time.time() < timeout:
time.sleep(0.5)
if self.driver.title != "Place Your Order - AmazonSmile Checkout":
retry += 1
if retry > max_atc_retries:
return False
continue
try:
place_order_button = self.driver.find_element_by_xpath(
"//input[@id='turbo-checkout-pyo-button' and @type='submit']"
)
except sel_exceptions.NoSuchElementException:
log.info("No PYO button found, don't ask why")
retry += 1
if retry > max_atc_retries:
return False
continue
if place_order_button:
try:
with self.wait_for_page_content_change():
place_order_button.click()
except sel_exceptions.WebDriverException:
log.info("Could not click button, don't ask why")
retry += 1
if retry > max_atc_retries:
return False
continue
timeout = self.get_timeout(5)
while self.driver.title == "" and time.time() < timeout:
time.sleep(0.5)
if self.driver.title in amazon_config["ORDER_COMPLETE_TITLES"]:
log.info("maybe this worked, check your orders")
self.save_screenshot("Order-Complete-Maybe")
successful = True
else:
log.info("maybe this didn't work, check your orders")
self.save_screenshot("Order-Maybe-Not-Complete")
successful = True
return True

def attempt_atc(self, offering_id, max_atc_retries=DEFAULT_MAX_ATC_TRIES):
# Open the add.html URL in Selenium
f = f"{AMAZON_URLS['ATC_URL']}?OfferListingId.1={offering_id}&Quantity.1=1"
Expand Down Expand Up @@ -1937,7 +2004,7 @@ def from_str(cls, label):


def get_item_condition(form_action) -> AmazonItemCondition:
""" Attempts to determine the Item Condition from the Add To Cart form action """
"""Attempts to determine the Item Condition from the Add To Cart form action"""
if "_new_" in form_action:
# log.debug(f"Item condition is new")
return AmazonItemCondition.New
Expand Down
2 changes: 1 addition & 1 deletion utils/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
# See https://www.python.org/dev/peps/pep-0440/ for specification
# See https://www.python.org/dev/peps/pep-0440/#examples-of-compliant-version-schemes for examples

__VERSION = "0.6.5"
__VERSION = "0.6.6"
version = Version(__VERSION)


Expand Down

0 comments on commit 52faa55

Please sign in to comment.