async def get_updates(): session = get_session(request) fetch_time: float = time.time() form: dict = await request.form if not is_logged_in(session): return _response({"error": "not_authenticated"}, code=403) chat_id: str = form.get("chat_id") fetch_from: int = form.get("fetch_from") full_fetch: bool = fetch_from == 0 or fetch_from == "0" _chat_data: chatData = check_chat_data(id_=chat_id) chats: dict = _chat_data.chats updates: dict = _chat_data.updates for k, v in chats.items(): if v.get("sender") != session["user"] and not v.get("rstamp"): chats[k]["read"] = True stamp: float = time.time() * 1000 chats[k]["rstamp"] = stamp _chat_data.chats = chats flag_modified(_chat_data, "chats") # pylint: disable=E1101 db.session.merge(_chat_data) db.session.commit() # pylint: enable=E1101 data: dict = get_data_from(chats, fetch_from, session["user"], "messages") return _response({ "update_data": updates, "message_data": data, "newest_message_id": fetch_from, "full_fetch": full_fetch, "sp": time.time() - fetch_time, })
async def cred_check(self, _session: dict) -> bool: if not is_logged_in(_session): await self.send_message( {"error": "Not Authenticated..did you clear your cookies?"}) return False self.user: str = _session["user"] return True
def wrapper(*args, **kwargs): agent_name = request.headers.get('X-API-USER', None) authorization = request.headers.get('X-API-TOKEN', 'Acdlsdksl') if authorization and is_logged_in(agent_name, authorization): return method(*args, **kwargs) else: return unauthenticated()
async def api_tools(): session = get_session(request) if not is_logged_in(session): return _response("__error__", headers={"content-type": "data/plain"}, code=403) return _response(f')}}]{session["user"]}', headers={"content-type": "data/plain"})
def main_loop(driver, args): log.info('Reading slot preferences from conf') slot_prefs = get_prefs_from_conf() log.info('Navigating to ' + config.BASE_URL) driver.get(config.BASE_URL) if args.force_login or not os.path.exists(config.PKL_PATH): # Login and capture Amazon session data... wait_for_auth(driver) else: # ...or load from storage load_session_data(driver) driver.refresh() if is_logged_in(driver): log.info('Successfully logged in via stored session data') else: log.error('Error logging in with stored session data') wait_for_auth(driver) site_config = config.SiteConfig(args.service) # Navigate to slot select build_route(site_config, 'SLOT_SELECT').navigate(driver) slots = slots_available(driver, slot_prefs) if slots: annoy() alert('Delivery slots available. What do you need me for?', 'Sosumi') while not slots: log.info('No slots found :( waiting...') jitter(25) driver.refresh() slots = slots_available(driver, slot_prefs) if slots: alert('Delivery slots found') message_body = generate_message(slots, args.service, args.checkout) send_sms(message_body) send_telegram(message_body) if not args.checkout: break checked_out = False log.info('Attempting to select slot and checkout') while not checked_out: try: log.info('Selecting slot: ' + slots[0].full_name) slots[0].select(driver) build_route(site_config, 'CHECKOUT').navigate(driver) checked_out = True alert('Checkout complete', 'Hero') except RouteRedirectException: log.warning('Checkout failed: Redirected to slot select') slots = slots_available(driver, slot_prefs) if not slots: break
async def make_notif(): form = await request.form session = get_session(request) if not is_logged_in(session) or not form.get("token"): return "NO" token = form.get("token") user = userData.query.filter( func.lower(userData.user) == func.lower(session["user"])).first() if not user: return "ERROR:USER NOT IN DB", 500 user.notification_id = token # pylint: disable=E1101 db.session.commit() # pylint: enable=E1101 return "OK"
async def get_chat_ids(): session = get_session(request) form = await request.form idx = form.get("chat_id") if not idx or not is_logged_in(session): return _response({"error": "Invalid Credentials"}, code=401) data = check_chat_data(id_=idx) if not data: return _response({"error": "Invalid ID"}, code=403) if session["user"] not in (data.user1, data.user2): return _response({"error": "InvalidID"}, code=403) user1 = data.user1 if not data.user1 == session["user"] else data.user2 chat_id = data.id_ _socket = sockets_get(user1) userHasSocket: str = "online" if _socket else "offline" return _response({ "is_online": userHasSocket, "chat_id": chat_id, "chat_with": user1, "HERE": session["user"], })
async def instants(): form = await request.get_json() session = get_session(request) if not is_logged_in(session): return "{}", 403 details = form.get("details") _chat_id = details.get("chat_id") _data = details.get("data") _new_msg_id = alter_chat_data(_data, _chat_id, True) ws_obj = sockets_get(_data.get("receiver")) if ws_obj: await ws_obj.send( json.dumps({ "meta": { "from": session.get("user"), "sessid": secrets.token_urlsafe(10), }, "data": { "msgid": _new_msg_id }, "type": "get-update", })) return _response({"type": "new_message", "data": _new_msg_id})
def web_automation(driver, merchant: Merchant, amount): driver.get( 'https://www.easypaymetrocard.com/vector/forte/cgi_bin/forteisapi.dll?ServiceName=ETCAccountWebSO&TemplateName=accounts/PrePaidPayment.html' ) time.sleep(5) # wait for page to load or redirect to login page logged_in = utils.is_logged_in(driver, timeout=90, logged_out_element=(By.ID, 'iPassword'), logged_in_element=(By.ID, 'securitycode')) if not logged_in: time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants try: # some websites will have the username auto-filled in due to a previous login if hasattr(merchant, 'usr'): driver.find_element_by_id('username').send_keys(merchant.usr) except ElementNotInteractableException: pass try: # only one of .usr and .accountnumber should exist if hasattr(merchant, 'accountnumber'): driver.find_element_by_id('iAccountNumber').send_keys( merchant.accountnumber) except ElementNotInteractableException: pass time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants driver.find_element_by_id('iPassword').send_keys(merchant.psw) time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants driver.find_element_by_xpath("//input[@type='submit']").click() WebDriverWait(driver, 30).until( expected_conditions.element_to_be_clickable( (By.LINK_TEXT, 'One Time Payment'))) driver.get( 'https://www.easypaymetrocard.com/vector/forte/cgi_bin/forteisapi.dll?ServiceName=ETCAccountWebSO&TemplateName=accounts/PrePaidPayment.html' ) assert merchant.card in [ "Primary", "Secondary" ], "Only supports existing Primary or Secondary card" card_xpath = "//input[@value='{}']".format(merchant.card) driver.find_element_by_xpath(card_xpath).click() time.sleep(2) driver.find_element_by_id("securitycode").send_keys(merchant.cvv) time.sleep(2) driver.find_element_by_id("iAmount").send_keys(utils.cents_to_str(amount)) time.sleep(2) driver.find_element_by_id("Address1").send_keys(merchant.address1) time.sleep(2) driver.find_element_by_id("Address2").send_keys(merchant.address2) time.sleep(2) driver.find_element_by_id("City").send_keys(merchant.city) time.sleep(2) driver.find_element_by_id("usStates").send_keys(merchant.state) time.sleep(2) driver.find_element_by_id("iZip").send_keys(merchant.zip) time.sleep(2) driver.find_element_by_xpath("//input[@type='submit']").click() try: WebDriverWait(driver, 30).until( expected_conditions.presence_of_element_located( (By.XPATH, "//*[contains(text(),'successfully processed')]"))) except TimeoutException: return Result.unverified # Purchase command was executed, yet we are unable to verify that it was successfully executed. # since debbit may have spent money but isn't sure, we log the error and stop any further payments for this merchant until the user intervenes time.sleep( 5) # sleep for a bit to show user that payment screen is reached return Result.success
def web_automation(driver, merchant, amount): driver.get('http://payments.xfinity.com/') logged_in = utils.is_logged_in(driver, timeout=90, logged_out_element=(By.ID, 'user'), logged_in_element=(By.ID, 'customAmount')) if not logged_in: driver.find_element_by_id('user').send_keys(merchant.usr) driver.find_element_by_id('passwd').send_keys(merchant.psw) driver.find_element_by_id('sign_in').click() try: # first time run captcha WebDriverWait(driver, 5).until( expected_conditions.element_to_be_clickable( (By.ID, 'nucaptcha-answer'))) LOGGER.info('captcha detected') input(''' Detected first time run captcha. Please follow these one-time steps. Future runs won't need this. 1. Open the Firefox window that debbit created. 2. Enter your user, pass, and the moving characters manually. 3. Click the "Sign In" button. 4. Click on this terminal window and hit "Enter" to continue running debbit. ''') except TimeoutException: pass WebDriverWait(driver, 90).until( expected_conditions.element_to_be_clickable( (By.ID, 'customAmount'))) if driver.find_elements_by_id('no'): # survey pop-up driver.find_element_by_id('no').click() cur_balance = driver.find_element_by_xpath( "//span[contains(text(), '$')]").text if utils.str_to_cents(cur_balance) == 0: LOGGER.error('xfinity balance is zero, will try again later.') return Result.skipped elif utils.str_to_cents(cur_balance) < amount: amount = utils.str_to_cents(cur_balance) driver.find_element_by_id('customAmount').send_keys( utils.cents_to_str(amount)) driver.find_element_by_xpath("//span[contains(text(),'nding in " + merchant.card[-4:] + "')]").click() driver.find_element_by_xpath("//span[contains(text(),'nding in " + merchant.card[-4:] + "')]").click() driver.find_element_by_xpath( "//button[contains(text(),'Continue')]").click() driver.find_element_by_xpath( "//button[contains(text(),'Submit Payment')]").click() try: WebDriverWait(driver, 90).until( expected_conditions.presence_of_element_located( (By.XPATH, "//*[contains(text(),'Your payment was successful')]"))) except TimeoutException: return Result.unverified return Result.success
log.info('Reading slot preferences from conf') slot_prefs = get_prefs_from_conf() log.info('Invoking Selenium Chrome webdriver') driver = webdriver.Chrome() log.info('Navigating to ' + config.BASE_URL) driver.get(config.BASE_URL) if args.force_login or not os.path.exists(config.PKL_PATH): # Login and capture Amazon session data... wait_for_auth(driver) else: # ...or load from storage load_session_data(driver) driver.refresh() if is_logged_in(driver): log.info('Successfully logged in via stored session data') else: log.error('Error logging in with stored session data') wait_for_auth(driver) # v-- Change this dynamically when more site configs exist site_config = config.WholeFoods # Navigate from BASE_URL to SLOT_URL site_config.Routes.SLOT_SELECT.navigate(driver) # Check for delivery slots slots = slots_available(driver, site_config, slot_prefs) if slots: annoy() alert('Delivery slots available. What do you need me for?', 'Sosumi') while not slots: log.info('No slots found :( waiting...')
def web_automation(driver, merchant, amount): driver.get('https://www.optimum.net/pay-bill/payment-options/') logged_in = utils.is_logged_in(driver, timeout=90, logged_out_element=(By.ID, 'loginPagePassword'), logged_in_element=(By.ID, 'otherAmountInput')) if not logged_in: try: # if first run, fill in username. If subsequent run, username may already be filled in. driver.find_element_by_id('loginPageUsername').send_keys( merchant.usr) except ElementNotInteractableException: pass driver.find_element_by_id('loginPagePassword').send_keys(merchant.psw) driver.find_element_by_xpath( "//button[contains(text(),'Sign in to Optimum.net')]").click() WebDriverWait(driver, 90).until( expected_conditions.element_to_be_clickable( (By.ID, 'otherAmountInput'))) cur_balance = driver.find_element_by_xpath( "//span[@class='payment--radio--bold ng-binding']").text LOGGER.info('Current Optimum balance is ' + cur_balance) if utils.str_to_cents(cur_balance) < 100: LOGGER.warning( 'Optimum account balance is less than minimum $1 payment, will try again later.' ) return Result.skipped elif utils.str_to_cents(cur_balance) < amount: LOGGER.info('Adjusting spend to ' + utils.str_to_cents(cur_balance) + ' cents since current balance is less than ' + amount + ' cents') amount = utils.str_to_cents(cur_balance) driver.find_element_by_id('otherAmountInput').send_keys( utils.cents_to_str(amount)) # Enter the amount driver.find_element_by_xpath( "//span[contains(text(),'Other amount')]/preceding-sibling::div" ).click() # Select the radio button driver.find_element_by_xpath( "//div[contains(text(),'Payment Method')]/following-sibling::div" ).click() # Open the selector dropdown box try: driver.find_element_by_xpath( "//span[contains(text(),'" + merchant.card + "')]").click() # Select the payment method except common.exceptions.NoSuchElementException: LOGGER.error('Failed to find payment method with name ' + merchant.card) return Result.failed button_str = driver.find_element_by_id('otpSubmit').get_attribute('value') expect_str = "Pay $" + utils.cents_to_str( amount) + " now with " + merchant.card if button_str == expect_str: driver.find_element_by_id('otpSubmit').click() LOGGER.info('Submitting purchase: ' + button_str) else: LOGGER.error('Failed to find valid pay button.') LOGGER.info('Detected: ' + button_str) LOGGER.info('Expected: ' + expect_str) return Result.failed # Check if the payment succeeded. try: WebDriverWait(driver, 90).until( expected_conditions.presence_of_element_located( (By.XPATH, "//*[contains(text(),'Confirmation Number:')]"))) LOGGER.info("Successful payment: " + driver.find_element_by_xpath( "//*[contains(text(),'Confirmation Number:')]").text) return Result.success except TimeoutException: # Check if there was an error, if so log the error. try: WebDriverWait(driver, 5).until( expected_conditions.presence_of_element_located( (By.XPATH, "//*[contains(text(),'unable')]"))) LOGGER.error("Failed payment: " + driver.find_element_by_xpath( "//*[contains(text(),'unable')]").text) except TimeoutException: return Result.unverified return Result.unverified
def web_automation(driver, merchant, amount): driver.get('https://www.amazon.com/asv/reload/order') logged_in = utils.is_logged_in( driver, timeout=30, logged_out_element=( By.XPATH, "//button[contains(text(),'Sign In to Continue')]"), logged_in_element=(By.XPATH, "//button[contains(text(),'Reload $')]")) if not logged_in: try: driver.find_element_by_xpath( "//button[contains(text(),'Sign In to Continue')]").click() except ElementClickInterceptedException: # spinner blocking button time.sleep(3) driver.find_element_by_xpath( "//button[contains(text(),'Sign In to Continue')]").click() driver.find_element_by_id('ap_email').send_keys(merchant.usr) try: # a/b tested new UI flow driver.find_element_by_id( 'continue').click() # if not exists, exception is raised except common.exceptions.NoSuchElementException: # a/b tested old UI flow pass WebDriverWait(driver, 30).until( expected_conditions.element_to_be_clickable( (By.ID, 'ap_password'))) driver.find_element_by_id('ap_password').send_keys(merchant.psw) driver.find_element_by_id('signInSubmit').click() try: # OTP email validation WebDriverWait(driver, 3).until( expected_conditions.element_to_be_clickable( (By.XPATH, "//*[contains(text(),'One Time Password')]"))) otp_flow = True except TimeoutException: otp_flow = False try: driver.find_element_by_xpath( "//*[contains(text(),'one-time pass')]").click() otp_flow = True except common.exceptions.NoSuchElementException: pass if otp_flow: driver.find_element_by_id('continue').click() WebDriverWait(driver, 5).until( expected_conditions.element_to_be_clickable( (By.XPATH, "//input"))) sent_to_text = driver.find_element_by_xpath( "//*[contains(text(),'@')]").text LOGGER.info(sent_to_text) LOGGER.info('Enter OTP here:') otp = input() elem = driver.find_element_by_xpath("//input") elem.send_keys(otp) elem.send_keys(Keys.TAB) elem.send_keys(Keys.ENTER) WebDriverWait(driver, 30).until( expected_conditions.element_to_be_clickable( (By.ID, 'asv-manual-reload-amount'))) driver.find_element_by_id('asv-manual-reload-amount').send_keys( utils.cents_to_str(amount)) driver.find_element_by_xpath("//span[contains(text(),'ending in " + merchant.card[-4:] + "')]").click() driver.find_element_by_xpath("//button[contains(text(),'Reload $" + utils.cents_to_str(amount) + "')]").click() time.sleep(10) # give page a chance to load if 'thank-you' not in driver.current_url: WebDriverWait(driver, 30).until( expected_conditions.element_to_be_clickable( (By.XPATH, "//input[@placeholder='ending in " + merchant.card[-4:] + "']"))) elem = driver.find_element_by_xpath( "//input[@placeholder='ending in " + merchant.card[-4:] + "']") elem.send_keys(merchant.card) elem.send_keys(Keys.TAB) elem.send_keys(Keys.ENTER) WebDriverWait(driver, 30).until( expected_conditions.element_to_be_clickable( (By.XPATH, "//button[contains(text(),'Reload $" + utils.cents_to_str(amount) + "')]"))) time.sleep(1) driver.find_element_by_xpath("//button[contains(text(),'Reload $" + utils.cents_to_str(amount) + "')]").click() time.sleep(10) # give page a chance to load if 'thank-you' not in driver.current_url: return Result.unverified return Result.success
def web_automation(driver, merchant, amount): driver.get( 'https://jakehilborn.github.io/debbit/example-merchant/login.html') logged_in = utils.is_logged_in(driver, timeout=90, logged_out_element=(By.ID, 'password'), logged_in_element=(By.ID, 'submit-payment')) if not logged_in: time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants try: # some websites will have the username auto-filled in due to a previous login driver.find_element_by_id('username').send_keys(merchant.usr) except ElementNotInteractableException: pass time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants driver.find_element_by_id('password').send_keys(merchant.usr) time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants driver.find_element_by_id('login').click() WebDriverWait(driver, 30).until( expected_conditions.element_to_be_clickable( (By.ID, 'submit-payment'))) cur_balance = driver.find_element_by_xpath( "//span[contains(text(), '$')]").text if utils.str_to_cents(cur_balance) == 0: LOGGER.error('example_merchant balance is zero, will try again later.') return Result.skipped elif utils.str_to_cents(cur_balance) < amount: amount = utils.str_to_cents(cur_balance) time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants driver.find_element_by_xpath("//*[contains(text(), 'card ending in " + merchant.card + "')]").click() time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants driver.find_element_by_id('amount').send_keys(utils.cents_to_str(amount)) time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants driver.find_element_by_id('submit-payment').click() try: WebDriverWait(driver, 30).until( expected_conditions.presence_of_element_located( (By.XPATH, "//*[contains(text(),'Thank you!')]"))) except TimeoutException: return Result.unverified # Purchase command was executed, yet we are unable to verify that it was successfully executed. # since debbit may have spent money but isn't sure, we log the error and stop any further payments for this merchant until the user intervenes time.sleep( 5) # sleep for a bit to show user that payment screen is reached return Result.success
def web_automation(driver, merchant, amount): driver.get('https://www.amazon.com/asv/reload/order') logged_in = utils.is_logged_in( driver, timeout=30, logged_out_element=( By.XPATH, "//button[contains(text(),'Sign In to Continue')]"), logged_in_element=(By.XPATH, "//button[starts-with(text(),'Reload')]")) time.sleep(1 + random.random() * 2) # slow down automation randomly to help avoid bot detection if not logged_in: try: driver.find_element_by_xpath( "//button[contains(text(),'Sign In to Continue')]").click() time.sleep(1 + random.random() * 2) except ElementClickInterceptedException: # spinner blocking button time.sleep(3) driver.find_element_by_xpath( "//button[contains(text(),'Sign In to Continue')]").click() time.sleep(1 + random.random() * 2) WebDriverWait(driver, 30).until( utils.AnyExpectedCondition( expected_conditions.element_to_be_clickable( (By.ID, 'ap_email')), # first time login expected_conditions.element_to_be_clickable( (By.XPATH, "//*[contains(text(),'" + merchant.usr + "')]")) # username found on page )) if driver.find_elements_by_xpath("//*[contains(text(),'" + merchant.usr + "')]"): driver.find_element_by_xpath( "//*[contains(text(),'" + merchant.usr + "')]").click( ) # click username in case we're on the Switch Accounts page WebDriverWait(driver, 30).until( expected_conditions.element_to_be_clickable( (By.ID, 'signInSubmit'))) time.sleep(1 + random.random() * 2) if driver.find_elements_by_id( 'ap_email' ): # if first run, fill in email. If subsequent run, nothing to fill in driver.find_element_by_id('ap_email').send_keys(merchant.usr) time.sleep(1 + random.random() * 2) if driver.find_elements_by_id('continue'): # a/b tested new UI flow driver.find_element_by_id('continue').click() WebDriverWait(driver, 5).until( expected_conditions.element_to_be_clickable( (By.ID, 'ap_password'))) time.sleep(1 + random.random() * 2) driver.find_element_by_id('ap_password').send_keys(merchant.psw) time.sleep(1 + random.random() * 2) driver.find_element_by_id('signInSubmit').click() time.sleep(1 + random.random() * 2) handle_anti_automation_challenge(driver, merchant) try: # OTP text message WebDriverWait(driver, 5).until( expected_conditions.element_to_be_clickable( (By.XPATH, "//*[contains(text(),'phone number ending in')]"))) if driver.find_elements_by_id('auth-mfa-remember-device'): driver.find_element_by_id('auth-mfa-remember-device').click() sent_to_text = driver.find_element_by_xpath( "//*[contains(text(),'phone number ending in')]").text LOGGER.info(sent_to_text) LOGGER.info('Enter OTP here:') otp = input() driver.find_element_by_id('auth-mfa-otpcode').send_keys(otp) time.sleep(1 + random.random() * 2) driver.find_element_by_id('auth-signin-button').click() time.sleep(1 + random.random() * 2) except TimeoutException: pass try: # OTP email validation WebDriverWait(driver, 5).until( expected_conditions.element_to_be_clickable( (By.XPATH, "//*[contains(text(),'One Time Pass')]"))) otp_email = True except TimeoutException: otp_email = False try: driver.find_element_by_xpath( "//*[contains(text(),'one-time pass')]").click() time.sleep(1 + random.random() * 2) otp_email = True except common.exceptions.NoSuchElementException: pass if otp_email: if driver.find_elements_by_id('continue'): driver.find_element_by_id('continue').click() time.sleep(1 + random.random() * 2) handle_anti_automation_challenge(driver, merchant) try: # User may have manually advanced to gift card screen or stopped at OTP input. Handle OTP input if on OTP screen. WebDriverWait(driver, 5).until( expected_conditions.element_to_be_clickable( (By.XPATH, "//*[contains(text(),'Enter OTP')]"))) sent_to_text = driver.find_element_by_xpath( "//*[contains(text(),'@')]").text LOGGER.info(sent_to_text) LOGGER.info('Enter OTP here:') otp = input() elem = driver.find_element_by_xpath("//input") elem.send_keys(otp) time.sleep(1 + random.random() * 2) elem.send_keys(Keys.TAB) time.sleep(1 + random.random() * 2) elem.send_keys(Keys.ENTER) time.sleep(1 + random.random() * 2) except TimeoutException: pass try: WebDriverWait(driver, 5).until( expected_conditions.element_to_be_clickable( (By.XPATH, "//*[contains(text(),'Not now')]"))) driver.find_element_by_xpath( "//*[contains(text(),'Not now')]").click() time.sleep(1 + random.random() * 2) except TimeoutException: # add mobile number page pass WebDriverWait(driver, 30).until( expected_conditions.element_to_be_clickable( (By.ID, 'asv-manual-reload-amount'))) driver.find_element_by_id('asv-manual-reload-amount').send_keys( utils.cents_to_str(amount)) time.sleep(1 + random.random() * 2) for element in driver.find_elements_by_xpath( "//span[contains(text(),'ending in " + merchant.card[-4:] + "')]"): try: # Amazon has redundant non-clickable elements. This will try each one until one works. element.click() time.sleep(1 + random.random() * 2) break except WebDriverException: pass driver.find_element_by_xpath( "//button[starts-with(text(),'Reload') and contains(text(),'" + utils.cents_to_str(amount) + "')]").click() time.sleep(1 + random.random() * 2) time.sleep(10) # give page a chance to load if 'thank-you' not in driver.current_url: WebDriverWait(driver, 30).until( expected_conditions.element_to_be_clickable( (By.XPATH, "//input[@placeholder='ending in " + merchant.card[-4:] + "']"))) elem = driver.find_element_by_xpath( "//input[@placeholder='ending in " + merchant.card[-4:] + "']") time.sleep(1 + random.random() * 2) elem.send_keys(merchant.card) time.sleep(1 + random.random() * 2) elem.send_keys(Keys.TAB) time.sleep(1 + random.random() * 2) elem.send_keys(Keys.ENTER) WebDriverWait(driver, 30).until( expected_conditions.element_to_be_clickable( (By.XPATH, "//button[contains(text(),'Reload $" + utils.cents_to_str(amount) + "')]"))) time.sleep(1 + random.random() * 2) driver.find_element_by_xpath( "//button[starts-with(text(),'Reload') and contains(text(),'" + utils.cents_to_str(amount) + "')]").click() time.sleep(10) # give page a chance to load if 'thank-you' not in driver.current_url: return Result.unverified return Result.success