From d0cc567de07956c218a3d8882e853f170a8a307e Mon Sep 17 00:00:00 2001 From: BeranPro Date: Wed, 3 Mar 2021 20:30:31 +0100 Subject: [PATCH 1/2] added login file to handle the instagram cookies --- login_util.py | 694 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 694 insertions(+) create mode 100644 login_util.py diff --git a/login_util.py b/login_util.py new file mode 100644 index 0000000..afe5a95 --- /dev/null +++ b/login_util.py @@ -0,0 +1,694 @@ +"""Module only used for the login part of the script""" +# import built-in & third-party modules +import pickle +import socket +import os +import json +import random + +from selenium.webdriver.common.action_chains import ActionChains +from selenium.webdriver.common.keys import Keys + +# import InstaPy modules +from .time_util import sleep +from .util import update_activity +from .util import web_address_navigator +from .util import explicit_wait +from .util import click_element +from .util import check_authorization +from .util import reload_webpage +from .xpath import read_xpath + +# import exceptions +from selenium.common.exceptions import NoSuchElementException +from selenium.common.exceptions import WebDriverException +from selenium.common.exceptions import MoveTargetOutOfBoundsException + + +def bypass_suspicious_login( + browser, logger, logfolder, bypass_security_challenge_using +): + """ Bypass suspicious loggin attempt verification. """ + + # close sign up Instagram modal if available + dismiss_get_app_offer(browser, logger) + dismiss_notification_offer(browser, logger) + dismiss_this_was_me(browser) + + option = None + if bypass_security_challenge_using == "sms": + try: + option = browser.find_element_by_xpath( + read_xpath(bypass_suspicious_login.__name__, "bypass_with_sms_option") + ) + except NoSuchElementException: + logger.warning( + "Unable to choose ({}) option to bypass the challenge".format( + bypass_security_challenge_using.upper() + ) + ) + + if bypass_security_challenge_using == "email": + try: + option = browser.find_element_by_xpath( + read_xpath(bypass_suspicious_login.__name__, "bypass_with_email_option") + ) + except NoSuchElementException: + logger.warning( + "Unable to choose ({}) option to bypass the challenge".format( + bypass_security_challenge_using.upper() + ) + ) + + # click on your option + (ActionChains(browser).move_to_element(option).click().perform()) + # next button click will miss the DOM reference for this element, so -> + option_text = option.text + + # click on security code + send_security_code_button = browser.find_element_by_xpath( + read_xpath(bypass_suspicious_login.__name__, "send_security_code_button") + ) + (ActionChains(browser).move_to_element(send_security_code_button).click().perform()) + + # update server calls + update_activity(browser, state=None) + + logger.info("Instagram detected an unusual login attempt") + logger.info('Check Instagram App for "Suspicious Login attempt" prompt') + logger.info("A security code was sent to your {}".format(option_text)) + + security_code = None + try: + path = "{}state.json".format(logfolder) + data = {} + # check if file exists and has content + if os.path.isfile(path) and os.path.getsize(path) > 0: + # load JSON file + with open(path, "r") as json_file: + data = json.load(json_file) + + # update connection state + security_code = data["challenge"]["security_code"] + except Exception: + logger.info("Security Code not present in {}state.json file".format(logfolder)) + + if security_code is None: + security_code = input("Type the security code here: ") + + security_code_field = browser.find_element_by_xpath( + read_xpath(bypass_suspicious_login.__name__, "security_code_field") + ) + + ( + ActionChains(browser) + .move_to_element(security_code_field) + .click() + .send_keys(security_code) + .perform() + ) + + # update server calls for both 'click' and 'send_keys' actions + for _ in range(2): + update_activity(browser, state=None) + + submit_security_code_button = browser.find_element_by_xpath( + read_xpath(bypass_suspicious_login.__name__, "submit_security_code_button") + ) + + ( + ActionChains(browser) + .move_to_element(submit_security_code_button) + .click() + .perform() + ) + + # update server calls + update_activity(browser, state=None) + + try: + sleep(3) + # locate wrong security code message + wrong_login = browser.find_element_by_xpath( + read_xpath(bypass_suspicious_login.__name__, "wrong_login") + ) + + if wrong_login is not None: + wrong_login_msg = "Wrong security code! Please check the code Instagram sent you and try again." + update_activity( + browser, + action=None, + state=wrong_login_msg, + logfolder=logfolder, + logger=logger, + ) + logger.warning(wrong_login_msg) + + except NoSuchElementException: + # correct security code + pass + + +def check_browser(browser, logfolder, logger, proxy_address): + # set initial state to offline + update_activity( + browser, + action=None, + state="trying to connect", + logfolder=logfolder, + logger=logger, + ) + + # check connection status + try: + logger.info("-- Connection Checklist [1/2] (Internet Connection Status)") + browser.get("view-source:https://ip4.seeip.org/geoip") + pre = browser.find_element_by_tag_name("pre").text + current_ip_info = json.loads(pre) + if ( + proxy_address is not None + and socket.gethostbyname(proxy_address) != current_ip_info["ip"] + ): + logger.warning("- Proxy is set, but it's not working properly") + logger.warning( + '- Expected Proxy IP is "{}", and the current IP is "{}"'.format( + proxy_address, current_ip_info["ip"] + ) + ) + logger.warning("- Try again or disable the Proxy Address on your setup") + logger.warning("- Aborting connection...") + return False + else: + logger.info("- Internet Connection Status: ok") + logger.info( + '- Current IP is "{}" and it\'s from "{}/{}"'.format( + current_ip_info["ip"], + current_ip_info["country"], + current_ip_info["country_code"], + ) + ) + update_activity( + browser, + action=None, + state="Internet connection is ok", + logfolder=logfolder, + logger=logger, + ) + except Exception: + logger.warning("- Internet Connection Status: error") + update_activity( + browser, + action=None, + state="There is an issue with the internet connection", + logfolder=logfolder, + logger=logger, + ) + return False + + # check if hide-selenium extension is running + logger.info("-- Connection Checklist [2/2] (Hide Selenium Extension)") + webdriver = browser.execute_script("return window.navigator.webdriver") + logger.info("- window.navigator.webdriver response: {}".format(webdriver)) + if webdriver: + logger.warning("- Hide Selenium Extension: error") + else: + logger.info("- Hide Selenium Extension: ok") + + # everything is ok, then continue(True) + return True + + +def login_user( + browser, + username, + password, + logger, + logfolder, + proxy_address, + security_code_to_phone, + security_codes, + want_check_browser, +): + """Logins the user with the given username and password""" + assert username, "Username not provided" + assert password, "Password not provided" + + # Hotfix - this check crashes more often than not -- plus in not necessary, + # I can verify my own connection + if want_check_browser: + if not check_browser(browser, logfolder, logger, proxy_address): + return False + + ig_homepage = "https://www.instagram.com" + web_address_navigator(browser, ig_homepage) + + cookie_file = "{0}{1}_cookie.pkl".format(logfolder, username) + cookie_loaded = None + login_state = None + + # try to load cookie from username + try: + for cookie in pickle.load(open(cookie_file, "rb")): + # SameSite = Strict, your cookie will only be sent in a + # first-party context. In user terms, the cookie will only be sent + # if the site for the cookie matches the site currently shown in + # the browser's URL bar. + if "sameSite" in cookie and cookie["sameSite"] == "None": + cookie["sameSite"] = "Strict" + + browser.add_cookie(cookie) + + sleep(4) + cookie_loaded = True + logger.info("- Cookie file for user '{}' loaded...".format(username)) + + # force refresh after cookie load or check_authorization() will FAIL + reload_webpage(browser) + sleep(4) + + # cookie has been LOADED, so the user SHOULD be logged in + login_state = check_authorization( + browser, username, "activity counts", logger, False + ) + sleep(4) + + except (WebDriverException, OSError, IOError): + # Just infor the user, not an error + logger.info("- Cookie file not found, creating cookie...") + + if login_state and cookie_loaded: + # Cookie loaded and joined IG, dismiss following features if availables + dismiss_notification_offer(browser, logger) + dismiss_save_information(browser, logger) + accept_igcookie_dialogue(browser, logger) + return True + + # This fix comes from comment in #6060 If not necessary we can remove it + accept_igcookie_dialogue(browser, logger) + + # if user is still not logged in, then there is an issue with the cookie + # so go create a new cookie. + if cookie_loaded: + logger.warning( + "- Issue with cookie for user '{}'. Creating new cookie...".format(username) + ) + + # Error could be faced due to "