示例#1
0
def likers_from_post(browser, logger, Selectors, amount=20):
    """ Get the list of users from the 'Likes' dialog of a photo """

    liked_counter_button = '//form/div/div/div/div/div/span/span/a[@role="button"]'

    try:
        liked_this = browser.find_elements_by_xpath(liked_counter_button)
        element_to_click = liked_this[0]

        sleep(1)
        click_element(browser, Settings, element_to_click)
        logger.info("opening likes")
        # update server calls
        # update_activity(Settings)

        sleep(1)

        # get a reference to the 'Likes' dialog box
        dialog = browser.find_element_by_xpath(
            Selectors.likes_dialog_body_xpath)

        # scroll down the page
        previous_len = -1
        browser.execute_script(
            "arguments[0].scrollTop = arguments[0].scrollHeight", dialog)
        update_activity(Settings)
        sleep(1)

        start_time = time.time()
        user_list = []

        while (not user_list or (len(user_list) != previous_len) and
               (len(user_list) < amount)):

            previous_len = len(user_list)
            scroll_bottom(browser, dialog, 2)

            user_list = get_users_from_dialog(user_list, dialog, logger)

            # write & update records at Progress Tracker
            progress_tracker(len(user_list), amount, start_time, None)

            if previous_len + 10 >= amount:
                logger.info("Scrolling finished")
                sleep(1)
                break

        random.shuffle(user_list)
        sleep(1)

        close_dialog_box(browser)

        logger.info("Got {} likers shuffled randomly whom you can follow:\n{}"
                    "\n".format(len(user_list), user_list))
        return user_list

    except Exception as exc:
        logger.Error("Some problem occured!\n\t{}".format(
            str(exc).encode("utf-8")))
        return []
示例#2
0
def is_commenting_enabled(browser, logger):
    """ Find out if commenting on the post is enabled """

    try:
        comments_disabled = browser.execute_script(
            "return window._sharedData.entry_data."
            "PostPage[0].graphql.shortcode_media.comments_disabled")

    except WebDriverException:
        try:
            browser.execute_script("location.reload()")
            update_activity(Settings)

            comments_disabled = browser.execute_script(
                "return window._sharedData.entry_data."
                "PostPage[0].graphql.shortcode_media.comments_disabled")

        except Exception as e:
            msg = ("Failed to check comments' status for verification!\n\t{}"
                   .format(str(e).encode("utf-8")))
            return False, "Failure"

    if comments_disabled is True:
        msg = "Comments are disabled for this post."
        return False, msg

    return True, "Success"
示例#3
0
def get_following_status(browser, track, username, person, person_id, logger,
                         logfolder):
    """ Verify if you are following the user in the loaded page """
    if track == "profile":
        ig_homepage = "https://www.medium.com/"
        web_address_navigator(browser, ig_homepage + person, Settings)

    follow_button_XP = (
        '//*[@id="page-container"]/div/div/ul/li/div/div/span/button[@type="button"]/span[text()="Follow"]'
    )
    failure_msg = "--> Unable to detect the following status of '{}'!"
    # user_inaccessible_msg = (
    #     "Couldn't access the profile page of '{}'!\t~might have changed the"
    #     " username".format(person))

    # check if the page is available
    # valid_page = is_page_available(browser, logger, Settings)
    # if not valid_page:
    #     logger.warning(user_inaccessible_msg)
    #     person_new = verify_username_by_id(browser,
    #                                        username,
    #                                        person,
    #                                        None,
    #                                        logger,
    #                                        logfolder)
    #     if person_new:
    #         web_address_navigator( browser, ig_homepage + person_new, Settings)
    #         valid_page = is_page_available(browser, logger, Settings)
    #         if not valid_page:
    #             logger.error(failure_msg.format(person_new.encode("utf-8")))
    #             return "UNAVAILABLE", None
    #     else:
    #         logger.error(failure_msg.format(person.encode("utf-8")))
    #         return "UNAVAILABLE", None

    # wait until the follow button is located and visible, then get it
    follow_button = explicit_wait(browser, "VOEL", [follow_button_XP, "XPath"],
                                  logger, 7, False)
    logger.info("follow_button =  {}".format(follow_button))

    if not follow_button:
        browser.execute_script("location.reload()")
        update_activity(Settings)

        follow_button = explicit_wait(browser, "VOEL",
                                      [follow_button_XP, "XPath"], logger, 14,
                                      False)
        logger.info("follow_button retried =  {}".format(follow_button))

        if not follow_button:
            # cannot find the any of the expected buttons
            logger.error(failure_msg.format(person.encode("utf-8")))
            return None, None

    # get follow status
    following_status = follow_button.text
    logger.info("following_status returned =  {}".format(following_status))

    return following_status, follow_button
示例#4
0
def comment_image(browser, username, comments, blacklist, logger, logfolder, Settings):
    """Checks if it should comment on the image"""
    # check action availability
    if quota_supervisor(Settings, "comments") == "jump":
        return False, "jumped"

    rand_comment = random.choice(comments).format(username)
    rand_comment = emoji.demojize(rand_comment)
    rand_comment = emoji.emojize(rand_comment, use_aliases=True)

    open_comment_section(browser, logger)
    comment_input = get_comment_input(browser)

    try:
        if len(comment_input) > 0:
            comment_input[0].clear()
            comment_input = get_comment_input(browser)
            # below, an extra space is added to force
            # the input box to update the reactJS core
            comment_to_be_sent = rand_comment + " "

            browser.execute_script(
                "arguments[0].value = arguments[1];",
                comment_input[0],
                comment_to_be_sent,
            )
            # below, it also will remove that extra space added above
            # COS '\b' is a backspace char in ASCII
            comment_input[0].send_keys("\b")
            comment_input = get_comment_input(browser)
            comment_input[0].submit()
            update_activity(Settings, "comments")

            if blacklist["enabled"] is True:
                action = "commented"
                add_user_to_blacklist(
                    username, blacklist["campaign"], action, logger, logfolder
                )
        else:
            logger.warning(
                "--> Comment Action Likely Failed!" "\t~comment Element was not found"
            )
            return False, "commenting disabled"

    except InvalidElementStateException:
        logger.warning(
            "--> Comment Action Likely Failed!"
            "\t~encountered `InvalidElementStateException` :/"
        )
        return False, "invalid element state"

    logger.info("--> Commented: {}".format(rand_comment.encode("utf-8")))

    # get the post-comment delay time to sleep
    naply = get_action_delay("comment", Settings)
    sleep(naply)

    return True, "success"
示例#5
0
def friend_user(browser, track, login, userid_to_friend, times, blacklist,
                logger, logfolder):
    """ Friend a user either from the profile page or post page or dialog
    box """
    # list of available tracks to friend in: ["profile", "post" "dialog"]

    # check action availability
    if quota_supervisor(Settings, "friends") == "jump":
        return False, "jumped"

    # check URL of the webpage, if it already is user's profile
    # page, then do not navigate to it again
    if friend_restriction("read", userid_to_friend, 1, logger):
        logger.info("Already connected {} or more times".format(times))
        return False, "already friended"

    user_link = "https://www.facebook.com/{}/".format(userid_to_friend)
    web_address_navigator(browser, user_link, logger, Settings)

    # find out CURRENT friending status
    friending_status, friend_button = get_friending_status(
        browser, track, login, userid_to_friend, None, logger, logfolder)
    logger.info(friending_status)
    if friending_status in ["Add Friend"]:
        click_visibly(browser, Settings, friend_button)  # click to friend
        friend_state, msg = verify_action(browser, "friend", track, login,
                                          userid_to_friend, None, logger,
                                          logfolder)
        if friend_state is not True:
            return False, msg
    elif friending_status is None:
        # TODO:BUG:2nd login has to be fixed with userid of loggedin user
        sirens_wailing, emergency_state = emergency_exit(
            browser, Settings, "https://facebook.com", login, login, logger,
            logfolder)
        if sirens_wailing is True:
            return False, emergency_state

        else:
            logger.warning(
                "--> Add Friend button not present '{}'!\t~unexpected failure".
                format(userid_to_friend))
            return False, "unexpected failure"

    # general tasks after a successful friend
    logger.info("--> Friended '{}'!".format(userid_to_friend.encode("utf-8")))
    update_activity(Settings, 'friendeds')

    logtime = datetime.now().strftime('%Y-%m-%d %H:%M')
    log_friended_pool(login, userid_to_friend, logger, logfolder, logtime,
                      userid_to_friend)

    friend_restriction("write", userid_to_friend, None, logger)

    return True, "success"
示例#6
0
def get_friending_status(browser, track, username, person, person_id, logger,
                         logfolder):
    """ Verify if you are friending the user in the loaded page """
    if track == "profile":
        ig_homepage = "https://www.facebook.com/"
        web_address_navigator( browser, ig_homepage + person, Settings)

    friend_button_XP = ("//div[@id='fbTimelineHeadline']/div/div/div/div/button[@type='button'][text()='Add Friend']")
    failure_msg = "--> Unable to detect the friending status of '{}'!"
    user_inaccessible_msg = (
        "Couldn't access the profile page of '{}'!\t~might have changed the"
        " username".format(person))

    # check if the page is available
    valid_page = is_page_available(browser, logger, Settings)
    if not valid_page:
        logger.warning(user_inaccessible_msg)
        person_new = verify_username_by_id(browser,
                                           username,
                                           person,
                                           None,
                                           logger,
                                           logfolder)
        if person_new:
            web_address_navigator( browser, ig_homepage + person_new, Settings)
            valid_page = is_page_available(browser, logger, Settings)
            if not valid_page:
                logger.error(failure_msg.format(person_new.encode("utf-8")))
                return "UNAVAILABLE", None

        else:
            logger.error(failure_msg.format(person.encode("utf-8")))
            return "UNAVAILABLE", None

    # wait until the friend button is located and visible, then get it
    friend_button = explicit_wait(browser, "VOEL", [friend_button_XP, "XPath"],
                                  logger, 7, False)
    if not friend_button:
        browser.execute_script("location.reload()")
        update_activity(Settings)

        friend_button = explicit_wait(browser, "VOEL",
                                      [friend_button_XP, "XPath"], logger, 14,
                                      False)
        if not friend_button:
            # cannot find the any of the expected buttons
            logger.error(failure_msg.format(person.encode("utf-8")))
            return None, None

    # get friend status
    friending_status = friend_button.text

    return friending_status, friend_button
示例#7
0
def verify_liking(browser, max, min, logger):
    """ Get the amount of existing existing likes and compare it against max
    & min values defined by user """
    try:
        likes_count = browser.execute_script(
            "return window._sharedData.entry_data."
            "PostPage[0].graphql.shortcode_media.edge_media_preview_like"
            ".count")

    except WebDriverException:
        try:
            browser.execute_script("location.reload()")
            update_activity(Settings)

            likes_count = browser.execute_script(
                "return window._sharedData.entry_data."
                "PostPage[0].graphql.shortcode_media.edge_media_preview_like"
                ".count")

        except WebDriverException:
            try:
                likes_count = (browser.find_element_by_css_selector(
                    "section._1w76c._nlmjy > div > a > span").text)

                if likes_count:
                    likes_count = format_number(likes_count)
                else:
                    logger.info(
                        "Failed to check likes' count  ~empty string\n")
                    return True

            except NoSuchElementException:
                logger.info("Failed to check likes' count\n")
                return True

    if max is not None and likes_count > max:
        logger.info(
            "Not liked this post! ~more likes exist off maximum limit at "
            "{}".format(likes_count))
        return False
    elif min is not None and likes_count < min:
        logger.info(
            "Not liked this post! ~less likes exist off minumum limit "
            "at {}".format(likes_count)
        )
        return False

    return True
示例#8
0
def like_image(browser, username, blacklist, logger, logfolder, Settings):
    """Likes the browser opened image"""
    # check action availability
    if quota_supervisor(Settings, "likes") == "jump":
        return False, "jumped"

    like_xpath = "//section/span/button/span[@aria-label='Like']"
    unlike_xpath = "//section/span/button/span[@aria-label='Unlike']"

    # find first for like element
    like_elem = browser.find_elements_by_xpath(like_xpath)

    if len(like_elem) == 1:
        # sleep real quick right before clicking the element
        sleep(2)
        click_element(browser, Settings, like_elem[0])
        # check now we have unlike instead of like
        liked_elem = browser.find_elements_by_xpath(unlike_xpath)

        if len(liked_elem) == 1:
            logger.info('--> Image Liked!')
            update_activity(Settings, 'likes')

            if blacklist['enabled'] is True:
                action = 'liked'
                add_user_to_blacklist(username, blacklist['campaign'], action,
                                      logger, logfolder)

            # get the post-like delay time to sleep
            naply = get_action_delay("like", Settings)
            sleep(naply)
            return True, "success"

        else:
            # if like not seceded wait for 2 min
            logger.info('--> Image was not able to get Liked! maybe blocked ?')
            sleep(120)

    else:
        liked_elem = browser.find_elements_by_xpath(unlike_xpath)
        if len(liked_elem) == 1:
            logger.info('--> Image already liked!')
            return False, "already liked"

    logger.info('--> Invalid Like Element!')

    return False, "invalid element"
示例#9
0
def login_user(
    browser,
    username,
    userid,
    password,
    logger,
    logfolder,
    switch_language=True,
    bypass_suspicious_attempt=False,
    bypass_with_mobile=False,
):
    """Logins the user with the given username and password"""
    assert username, "Username not provided"
    assert password, "Password not provided"

    ig_homepage = "https://www.facebook.com"
    web_address_navigator(browser, ig_homepage, logger, Settings)
    cookie_loaded = False

    # try to load cookie from username
    try:
        for cookie in pickle.load(
                open("{0}{1}_cookie.pkl".format(logfolder, username), "rb")):
            browser.add_cookie(cookie)
            cookie_loaded = True
    except (WebDriverException, OSError, IOError):
        logger.info("Cookie file not found, creating cookie...")

    # include time.sleep(1) to prevent getting stuck on google.com
    time.sleep(1)

    # changes facebook website language to english to use english xpaths
    if switch_language:
        links = browser.find_elements_by_xpath('//*[@id="pageFooter"]/ul/li')
        for link in links:
            if link.get_attribute("title") == "English (UK)":
                click_element(browser, Settings, link)

    web_address_navigator(browser, ig_homepage, logger, Settings)
    reload_webpage(browser, Settings)

    # cookie has been LOADED, so the user SHOULD be logged in
    # check if the user IS logged in
    login_state = check_authorization(
        browser,
        Settings,
        "https://www.facebook.com/",
        username,
        userid,
        "activity counts",
        logger,
        logfolder,
        True,
    )
    logger.info("check_authorization: {}".format(login_state))
    if login_state is True:
        # dismiss_notification_offer(browser, logger)
        return True

    # 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.info(
            "Issue with cookie for user {}. Creating new cookie...".format(
                username))

    # wait until the 'username' input element is located and visible
    input_username_XP = '//*[@id="email"]'
    # explicit_wait(browser, "VOEL", [input_username_XP, "XPath"], logger)

    input_username = browser.find_element_by_xpath(input_username_XP)

    logger.info("moving to input_username")
    logger.info("entering input_username")
    (ActionChains(browser).move_to_element(input_username).click().send_keys(
        username).perform())

    # update server calls for both 'click' and 'send_keys' actions
    for i in range(2):
        update_activity(Settings)

    sleep(1)

    #  password
    input_password = browser.find_elements_by_xpath('//*[@id="pass"]')

    if not isinstance(password, str):
        password = str(password)

    logger.info("entering input_password")
    (ActionChains(browser).move_to_element(
        input_password[0]).click().send_keys(password).perform())

    # update server calls for both 'click' and 'send_keys' actions
    for i in range(2):
        update_activity(Settings)

    sleep(1)

    logger.info("submitting login_button")
    login_button = browser.find_element_by_xpath('//*[@type="submit"]')

    (ActionChains(browser).move_to_element(login_button).click().perform())

    # update server calls
    update_activity(Settings)

    sleep(1)

    if bypass_suspicious_attempt is True:
        bypass_suspicious_login(browser, bypass_with_mobile, logger)

    # Check if user is logged-in (If there's two 'nav' elements)
    nav = browser.find_elements_by_xpath('//div[@role="navigation"]')
    if len(nav) == 2:
        # create cookie for username
        logger.info("logged in")
        pickle.dump(
            browser.get_cookies(),
            open("{0}{1}_cookie.pkl".format(logfolder, username), "wb"),
        )
        return True
    else:
        return False
示例#10
0
def check_link(browser, post_link, dont_like, mandatory_words,
               mandatory_language, mandatory_character, is_mandatory_character,
               check_character_set, ignore_if_contains, logger):
    """
    Check the given link if it is appropriate

    :param browser: The selenium webdriver instance
    :param post_link:
    :param dont_like: hashtags of inappropriate phrases
    :param mandatory_words: words of appropriate phrases
    :param ignore_if_contains:
    :param logger: the logger instance
    :return: tuple of
        boolean: True if inappropriate,
        string: the username,
        boolean: True if it is video media,
        string: the message if inappropriate else 'None',
        string: set the scope of the return value
    """

    # Check URL of the webpage, if it already is post's page, then do not
    # navigate to it again
    web_address_navigator(browser, post_link, logger, Settings)
    """Check if the Post is Valid/Exists"""
    try:
        post_page = browser.execute_script(
            "return window._sharedData.entry_data.PostPage")

    except WebDriverException:  # handle the possible `entry_data` error
        try:
            browser.execute_script("location.reload()")
            update_activity(Settings)

            post_page = browser.execute_script(
                "return window._sharedData.entry_data.PostPage")

        except WebDriverException:
            post_page = None

    if post_page is None:
        logger.warning('Unavailable Page: {}'.format(
            post_link.encode('utf-8')))
        return True, None, None, 'Unavailable Page', "Failure"
    """Gets the description of the post's link and checks for the dont_like
    tags"""
    graphql = 'graphql' in post_page[0]
    if graphql:
        media = post_page[0]['graphql']['shortcode_media']
        is_video = media['is_video']
        user_name = media['owner']['username']
        image_text = media['edge_media_to_caption']['edges']
        image_text = image_text[0]['node']['text'] if image_text else None
        location = media['location']
        location_name = location['name'] if location else None
        media_edge_string = get_media_edge_comment_string(media)
        # double {{ allows us to call .format here:
        owner_comments = browser.execute_script(
            '''
            latest_comments = window._sharedData.entry_data.PostPage[
            0].graphql.shortcode_media.{}.edges;
            if (latest_comments === undefined) {{
                latest_comments = Array();
                owner_comments = latest_comments
                    .filter(item => item.node.owner.username == arguments[0])
                    .map(item => item.node.text)
                    .reduce((item, total) => item + '\\n' + total, '');
                return owner_comments;}}
            else {{
                return null;}}
        '''.format(media_edge_string), user_name)

    else:
        media = post_page[0]['media']
        is_video = media['is_video']
        user_name = media['owner']['username']
        image_text = media['caption']
        owner_comments = browser.execute_script(
            '''
            latest_comments = window._sharedData.entry_data.PostPage[
            0].media.comments.nodes;
            if (latest_comments === undefined) {
                latest_comments = Array();
                owner_comments = latest_comments
                    .filter(item => item.user.username == arguments[0])
                    .map(item => item.text)
                    .reduce((item, total) => item + '\\n' + total, '');
                return owner_comments;}
            else {
                return null;}
        ''', user_name)

    if owner_comments == '':
        owner_comments = None
    """Append owner comments to description as it might contain further tags"""
    if image_text is None:
        image_text = owner_comments

    elif owner_comments:
        image_text = image_text + '\n' + owner_comments
    """If the image still has no description gets the first comment"""
    if image_text is None:
        if graphql:
            media_edge_string = get_media_edge_comment_string(media)
            image_text = media[media_edge_string]['edges']
            image_text = image_text[0]['node']['text'] if image_text else None

        else:
            image_text = media['comments']['nodes']
            image_text = image_text[0]['text'] if image_text else None

    if image_text is None:
        image_text = "No description"

    logger.info('Image from: {}'.format(user_name.encode('utf-8')))
    logger.info('Link: {}'.format(post_link.encode('utf-8')))
    logger.info('Description: {}'.format(image_text.encode('utf-8')))
    """Check if mandatory character set, before adding the location to the
    text"""
    if mandatory_language:
        if not check_character_set(image_text):
            return True, user_name, is_video, 'Mandatory language not ' \
                                              'fulfilled', "Not mandatory " \
                                                           "language"
    """Append location to image_text so we can search through both in one
    go."""
    if location_name:
        logger.info('Location: {}'.format(location_name.encode('utf-8')))
        image_text = image_text + '\n' + location_name

    if mandatory_words:
        if not any((word in image_text for word in mandatory_words)):
            return True, user_name, is_video, 'Mandatory words not ' \
                                              'fulfilled', "Not mandatory " \
                                                           "likes"

    image_text_lower = [x.lower() for x in image_text]
    ignore_if_contains_lower = [x.lower() for x in ignore_if_contains]
    if any((word in image_text_lower for word in ignore_if_contains_lower)):
        return False, user_name, is_video, 'None', "Pass"

    dont_like_regex = []

    for dont_likes in dont_like:
        if dont_likes.startswith("#"):
            dont_like_regex.append(dont_likes + "([^\d\w]|$)")
        elif dont_likes.startswith("["):
            dont_like_regex.append("#" + dont_likes[1:] + "[\d\w]+([^\d\w]|$)")
        elif dont_likes.startswith("]"):
            dont_like_regex.append("#[\d\w]+" + dont_likes[1:] + "([^\d\w]|$)")
        else:
            dont_like_regex.append("#[\d\w]*" + dont_likes +
                                   "[\d\w]*([^\d\w]|$)")

    for dont_likes_regex in dont_like_regex:
        quash = re.search(dont_likes_regex, image_text, re.IGNORECASE)
        if quash:
            quashed = \
                (((quash.group(0)).split('#')[1]).split(' ')[0]).split('\n')[
                    0].encode(
                    'utf-8')  # dismiss possible space and newlines
            iffy = (
                (re.split(r'\W+', dont_likes_regex))[3]
                if dont_likes_regex.endswith('*([^\\d\\w]|$)')
                else  # 'word' without format
                (re.split(r'\W+', dont_likes_regex))[1]
                if dont_likes_regex.endswith('+([^\\d\\w]|$)') else  # '[word'
                (re.split(r'\W+', dont_likes_regex))[3]
                if dont_likes_regex.startswith('#[\\d\\w]+') else  # ']word'
                (re.split(r'\W+', dont_likes_regex))[1])  # '#word'
            inapp_unit = 'Inappropriate! ~ contains "{}"'.format(
                quashed if iffy ==
                quashed else '" in "'.join([str(iffy), str(quashed)]))
            return True, user_name, is_video, inapp_unit, "Undesired word"

    return False, user_name, is_video, 'None', "Success"
示例#11
0
def get_links_for_username(browser,
                           username,
                           person,
                           amount,
                           logger,
                           logfolder,
                           randomize=False,
                           media=None,
                           taggedImages=False):
    """Fetches the number of links specified
    by amount and returns a list of links"""
    if media is None:
        # All known media types
        media = ['', 'Post', 'Video']
    elif media == 'Photo':
        # Include posts with multiple images in it
        media = ['', 'Post']
    else:
        # Make it an array to use it in the following part
        media = [media]

    logger.info('Getting {} image list...'.format(person))

    user_link = "https://www.facebook.com/{}/".format(person)
    if taggedImages:
        user_link = user_link + 'tagged/'

    # Check URL of the webpage, if it already is user's profile page,
    # then do not navigate to it again
    web_address_navigator(browser, user_link, logger, Settings)

    if "Page Not Found" in browser.title:
        logger.error(
            'Facebook error: The link you followed may be broken, or the '
            'page may have been removed...')
        return False

    # if private user, we can get links only if we following
    following, follow_button = get_following_status(browser, 'profile',
                                                    username, person, None,
                                                    logger, logfolder)
    if following == 'Following':
        following = True
    is_private = is_private_profile(Settings, browser, logger, following)
    if (is_private is None) or (is_private is True
                                and not following) or (following == 'Blocked'):
        return False

    # Get links
    links = []
    main_elem = browser.find_element_by_tag_name('article')
    posts_count = get_number_of_posts(browser)
    attempt = 0

    if posts_count is not None and amount > posts_count:
        logger.info(
            "You have requested to get {} posts from {}'s profile page BUT"
            " there only {} posts available :D".format(amount, person,
                                                       posts_count))
        amount = posts_count

    while len(links) < amount:
        initial_links = links
        browser.execute_script(
            "window.scrollTo(0, document.body.scrollHeight);")
        # update server calls after a scroll request
        update_activity(Settings)
        sleep(0.66)

        # using `extend`  or `+=` results reference stay alive which affects
        # previous assignment (can use `copy()` for it)
        links = links + get_links(browser, person, logger, media, main_elem)
        links = sorted(set(links), key=links.index)

        if len(links) == len(initial_links):
            if attempt >= 7:
                logger.info(
                    "There are possibly less posts than {} in {}'s profile "
                    "page!".format(amount, person))
                break
            else:
                attempt += 1
        else:
            attempt = 0

    if randomize is True:
        random.shuffle(links)

    return links[:amount]
示例#12
0
def unfollow_user(browser, track, username, userid, person, person_id, button,
                  relationship_data, logger, logfolder, Settings):
    """ Unfollow a user either from the profile or post page or dialog box """
    # list of available tracks to unfollow in: ["profile", "post" "dialog"]

    # check action availability
    if quota_supervisor(Settings, "unfollows") == "jump":
        return False, "jumped"

    if track in ["profile", "post"]:
        """ Method of unfollowing from a user's profile page or post page """
        if track == "profile":
            user_link = "https://www.facebook.com/{}/".format(person)
            web_address_navigator(browser, user_link, Settings)

        # find out CURRENT follow status
        following_status, follow_button = get_following_status(
            browser, track, username, person, person_id, logger, logfolder)

        if following_status in ["Following", "Requested"]:
            click_element(browser, Settings,
                          follow_button)  # click to unfollow
            sleep(4)  # TODO: use explicit wait here
            confirm_unfollow(browser)
            unfollow_state, msg = verify_action(browser, "unfollow", track,
                                                username, person, person_id,
                                                logger, logfolder)
            if unfollow_state is not True:
                return False, msg

        elif following_status in ["Follow", "Follow Back"]:
            logger.info("--> Already unfollowed '{}'! or a private user that "
                        "rejected your req".format(person))
            post_unfollow_cleanup(["successful", "uncertain"], username,
                                  person, relationship_data, person_id, logger,
                                  logfolder)
            return False, "already unfollowed"

        elif following_status in ["Unblock", "UNAVAILABLE"]:
            if following_status == "Unblock":
                failure_msg = "user is in block"

            elif following_status == "UNAVAILABLE":
                failure_msg = "user is inaccessible"

            logger.warning("--> Couldn't unfollow '{}'!\t~{}".format(
                person, failure_msg))
            post_unfollow_cleanup("uncertain", username, person,
                                  relationship_data, person_id, logger,
                                  logfolder)
            return False, following_status

        elif following_status is None:
            sirens_wailing, emergency_state = emergency_exit(
                browser, Settings, username, userid, logger, logfolder)
            if sirens_wailing is True:
                return False, emergency_state

            else:
                logger.warning(
                    "--> Couldn't unfollow '{}'!\t~unexpected failure".format(
                        person))
                return False, "unexpected failure"
    elif track == "dialog":
        """  Method of unfollowing from a dialog box """
        click_element(browser, Settings, button)
        sleep(4)  # TODO: use explicit wait here
        confirm_unfollow(browser)

    # general tasks after a successful unfollow
    logger.info("--> Unfollowed '{}'!".format(person))
    update_activity(Settings, 'unfollows')
    post_unfollow_cleanup("successful", username, person, relationship_data,
                          person_id, logger, logfolder)

    # get the post-unfollow delay time to sleep
    naply = get_action_delay("unfollow", Settings)
    sleep(naply)

    return True, "success"
示例#13
0
def follow_user(browser, track, login, userid_to_follow, button, blacklist,
                logger, logfolder, Settings):
    """ Follow a user either from the profile page or post page or dialog
    box """
    # list of available tracks to follow in: ["profile", "post" "dialog"]

    # check action availability
    if quota_supervisor(Settings, "follows") == "jump":
        return False, "jumped"

    if track in ["profile", "post"]:
        if track == "profile":
            # check URL of the webpage, if it already is user's profile
            # page, then do not navigate to it again
            user_link = "https://www.facebook.com/{}/".format(userid_to_follow)
            web_address_navigator(browser, user_link, Settings)

        # find out CURRENT following status
        following_status, follow_button = \
            get_following_status(browser,
                                 track,
                                 login,
                                 userid_to_follow,
                                 None,
                                 logger,
                                 logfolder)
        if following_status in ["Follow", "Follow Back"]:
            click_visibly(browser, Settings, follow_button)  # click to follow
            follow_state, msg = verify_action(browser, "follow", track, login,
                                              userid_to_follow, None, logger,
                                              logfolder)
            if follow_state is not True:
                return False, msg

        elif following_status in ["Following", "Requested"]:
            if following_status == "Following":
                logger.info(
                    "--> Already following '{}'!\n".format(userid_to_follow))

            elif following_status == "Requested":
                logger.info("--> Already requested '{}' to follow!\n".format(
                    userid_to_follow))

            sleep(1)
            return False, "already followed"

        elif following_status in ["Unblock", "UNAVAILABLE"]:
            if following_status == "Unblock":
                failure_msg = "user is in block"

            elif following_status == "UNAVAILABLE":
                failure_msg = "user is inaccessible"

            logger.warning("--> Couldn't follow '{}'!\t~{}".format(
                userid_to_follow, failure_msg))
            return False, following_status

        elif following_status is None:
            # TODO:BUG:2nd login has to be fixed with userid of loggedin user
            sirens_wailing, emergency_state = emergency_exit(
                browser, Settings, "https://www.facebook.com", login, login,
                logger, logfolder)
            if sirens_wailing is True:
                return False, emergency_state

            else:
                logger.warning(
                    "--> Couldn't unfollow '{}'!\t~unexpected failure".format(
                        userid_to_follow))
                return False, "unexpected failure"
    elif track == "dialog":
        click_element(browser, Settings, button)
        sleep(3)

    # general tasks after a successful follow
    logger.info("--> Followed '{}'!".format(userid_to_follow.encode("utf-8")))
    update_activity(Settings, 'follows')

    # get user ID to record alongside username
    user_id = get_user_id(browser, track, userid_to_follow, logger)

    logtime = datetime.now().strftime('%Y-%m-%d %H:%M')
    log_followed_pool(login, userid_to_follow, logger, logfolder, logtime,
                      user_id)

    follow_restriction("write", userid_to_follow, None, logger)

    if blacklist['enabled'] is True:
        action = 'followed'
        add_user_to_blacklist(userid_to_follow, blacklist['campaign'], action,
                              logger, logfolder)

    # get the post-follow delay time to sleep
    naply = get_action_delay("follow", Settings)
    sleep(naply)

    return True, "success"
示例#14
0
def login_user(browser,
               username,
               userid,
               password,
               logger,
               logfolder,
               switch_language=True,
               bypass_suspicious_attempt=False,
               bypass_with_mobile=False):
    """Logins the user with the given username and password"""
    assert username, 'Username not provided'
    assert password, 'Password not provided'

    print(username, password)
    ig_homepage = "https://accounts.google.com/ServiceLogin?continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Fhl%3Den%26feature%3Dcomment%26app%3Ddesktop%26next%3D%252Fall_comments%253Fv%253DLAr6oAKieHk%26action_handle_signin%3Dtrue&uilel=3&service=youtube&passive=true&hl=en"
    web_address_navigator(browser, ig_homepage, Settings)
    cookie_loaded = False

    # try to load cookie from username
    try:
        for cookie in pickle.load(
                open('{0}{1}_cookie.pkl'.format(logfolder, username), 'rb')):
            browser.add_cookie(cookie)
            cookie_loaded = True
    except (WebDriverException, OSError, IOError):
        print("Cookie file not found, creating cookie...")

    # include time.sleep(1) to prevent getting stuck on google.com
    time.sleep(1)

    web_address_navigator(browser, ig_homepage, Settings)
    reload_webpage(browser, Settings)

    # try:
    #     profile_pic = browser.find_element_by_xpath('//header/div[8]/details/summary/img')
    #     if profile_pic:
    #         login_state = True
    #     else:
    #         login_state = False
    # except Exception as e:
    #     print(e)
    #     login_state = False

    # print('login_state:', login_state)

    # if login_state is True:
    #     # dismiss_notification_offer(browser, logger)
    #     return True

    # if user is still not logged in, then there is an issue with the cookie
    # so go create a new cookie..
    if cookie_loaded:
        print("Issue with cookie for user {}. Creating "
              "new cookie...".format(username))

    # wait until the 'username' input element is located and visible
    input_username_XP = '//*[@id="identifierId"]'
    # explicit_wait(browser, "VOEL", [input_username_XP, "XPath"], logger)

    input_username = browser.find_element_by_xpath(input_username_XP)

    print('moving to input_username')
    print('entering input_username')
    (ActionChains(browser).move_to_element(input_username).click().send_keys(
        username).perform())

    sleep(1)

    (ActionChains(browser).send_keys(Keys.ENTER).perform())
    # update server calls for both 'click' and 'send_keys' actions
    for i in range(2):
        update_activity(Settings)

    sleep(1)

    #  password
    input_password = browser.find_elements_by_xpath(
        "//*[@id='password']/div[1]/div/div[1]/input")
    if not isinstance(password, str):
        password = str(password)

    print('entering input_password')
    (ActionChains(browser).move_to_element(
        input_password[0]).click().send_keys(password).perform())

    sleep(1)

    (ActionChains(browser).send_keys(Keys.ENTER).perform())
    # update server calls for both 'click' and 'send_keys' actions
    for i in range(2):
        update_activity(Settings)

    sleep(1)

    print('submitting (ie just pres enter)')
    (ActionChains(browser).send_keys(Keys.ENTER).perform())

    # update server calls
    update_activity(Settings)

    sleep(1)

    # wait until page fully load
    explicit_wait(browser, "PFL", [], logger, 5)

    try:
        profile_pic = browser.find_element_by_xpath('//*[@id="img"]')
        if profile_pic:
            login_state = True
            print('logged in')
            pickle.dump(
                browser.get_cookies(),
                open('{0}{1}_cookie.pkl'.format(logfolder, username), 'wb'))
        else:
            login_state = False
    except Exception as e:
        print(e)
        login_state = False

    return login_state
示例#15
0
def login_user(browser, username, password, userid, logger, logfolder):
    """Logins the user with the given username and password"""
    assert username, 'Username not provided'
    assert password, 'Password not provided'

    print(username, password)
    homepage = "https://www.medium.com/"
    web_address_navigator(browser, homepage, Settings)
    cookie_loaded = False

    # try to load cookie from username
    try:
        for cookie in pickle.load(
                open('{0}{1}_cookie.pkl'.format(logfolder, username), 'rb')):
            browser.add_cookie(cookie)
            cookie_loaded = True
    except (WebDriverException, OSError, IOError):
        print("Cookie file not found, creating cookie...")

    # include time.sleep(1) to prevent getting stuck on google.com
    time.sleep(1)

    web_address_navigator(browser, homepage, Settings)
    reload_webpage(browser, Settings)

    # if user is still not logged in, then there is an issue with the cookie
    # so go create a new cookie..

    # cookie has been LOADED, so the user SHOULD be logged in
    # check if the user IS logged in
    if cookie_loaded:
        login_state = check_authorization(browser, Settings,
                                          "https://www.medium.com", username,
                                          userid, "activity counts", logger,
                                          logfolder, True)
        print('check_authorization:', login_state)
        if login_state is True:
            # dismiss_notification_offer(browser, logger)
            return True
        else:
            print("Issue with cookie for user {}. Creating "
                  "new cookie...".format(username))

    input_username_XP = '//div[2]/div[1]/input[@name="email"]'
    input_usernames = browser.find_elements_by_xpath(
        input_username_XP)  #TODO : Two tags found just take the last one

    print('moving to input_username')
    print('entering input_username: {}'.format(username))
    #email login doesn't reprompt
    (ActionChains(browser).move_to_element(
        input_usernames[-1]).click().send_keys(username).perform())

    # update server calls for both 'click' and 'send_keys' actions
    for i in range(2):
        update_activity(Settings)

    sleep(1)

    #  password
    input_passeord_XP = '//div[2]/div[2]/input[@name="password"]'
    input_passwords = browser.find_elements_by_xpath(input_passeord_XP)

    print('entering input_password')
    (ActionChains(browser).move_to_element(
        input_passwords[-1]).click().send_keys(password).perform())

    # update server calls for both 'click' and 'send_keys' actions
    for i in range(2):
        update_activity(Settings)

    sleep(1)

    print('submitting login_button')
    login_button_XP = '//div[2]/div[3]/input'
    login_button = browser.find_element_by_xpath(login_button_XP)

    (ActionChains(browser).move_to_element(login_button).click().perform())

    # update server calls
    update_activity(Settings)

    sleep(2)

    # wait until page fully load
    explicit_wait(browser, "PFL", [], logger, 5)

    # Check if user is logged-in (If there's two 'nav' elements)
    login_state = check_authorization(browser, Settings,
                                      "https://www.medium.com/login", username,
                                      userid, "activity counts", logger,
                                      logfolder, True)
    print('check_authorization again:', login_state)
    return login_state
示例#16
0
def login_user(browser,
               username,
               userid,
               password,
               logger,
               logfolder,
               switch_language=True,
               bypass_suspicious_attempt=False,
               bypass_with_mobile=False):
    """Logins the user with the given username and password"""
    assert username, 'Username not provided'
    assert password, 'Password not provided'

    print(username, password)
    ig_homepage = "https://www.facebook.com"
    web_address_navigator(browser, ig_homepage, Settings)
    cookie_loaded = False

    # try to load cookie from username
    try:
        for cookie in pickle.load(
                open('{0}{1}_cookie.pkl'.format(logfolder, username), 'rb')):
            browser.add_cookie(cookie)
            cookie_loaded = True
    except (WebDriverException, OSError, IOError):
        print("Cookie file not found, creating cookie...")

    # include time.sleep(1) to prevent getting stuck on google.com
    time.sleep(1)

    # changes facebook website language to english to use english xpaths
    if switch_language:
        links = browser.find_elements_by_xpath('//*[@id="pageFooter"]/ul/li')
        for link in links:
            if link.get_attribute('title') == "English (UK)":
                click_element(browser, Settings, link)

    web_address_navigator(browser, ig_homepage, Settings)
    reload_webpage(browser, Settings)

    # cookie has been LOADED, so the user SHOULD be logged in
    # check if the user IS logged in
    login_state = check_authorization(browser, Settings,
                                      "https://www.facebook.com/", username,
                                      userid, "activity counts", logger,
                                      logfolder, True)
    print('check_authorization:', login_state)
    if login_state is True:
        # dismiss_notification_offer(browser, logger)
        return True

    # if user is still not logged in, then there is an issue with the cookie
    # so go create a new cookie..
    if cookie_loaded:
        print("Issue with cookie for user {}. Creating "
              "new cookie...".format(username))

    # # Check if the first div is 'Create an Account' or 'Log In'
    # login_elem = browser.find_element_by_xpath(
    #     '//*[@id="email"]'
    #     )

    # if login_elem is not None:
    #     try:
    #         (ActionChains(browser)
    #          .move_to_element(login_elem)
    #          .click()
    #          .perform())
    #     except MoveTargetOutOfBoundsException:
    #         login_elem.click()

    #     # update server calls
    #     update_activity(Settings)

    # Enter username and password and logs the user in
    # Sometimes the element name isn't 'Username' and 'Password'
    # (valid for placeholder too)

    # wait until it navigates to the login page
    # login_page_title = "Login"
    # explicit_wait(browser, "TC", login_page_title, logger)

    # wait until the 'username' input element is located and visible
    input_username_XP = '//*[@id="email"]'
    # explicit_wait(browser, "VOEL", [input_username_XP, "XPath"], logger)

    input_username = browser.find_element_by_xpath(input_username_XP)

    print('moving to input_username')
    print('entering input_username')
    (ActionChains(browser).move_to_element(input_username).click().send_keys(
        username).perform())

    # update server calls for both 'click' and 'send_keys' actions
    for i in range(2):
        update_activity(Settings)

    sleep(1)

    #  password
    input_password = browser.find_elements_by_xpath('//*[@id="pass"]')

    if not isinstance(password, str):
        password = str(password)

    print('entering input_password')
    (ActionChains(browser).move_to_element(
        input_password[0]).click().send_keys(password).perform())

    # update server calls for both 'click' and 'send_keys' actions
    for i in range(2):
        update_activity(Settings)

    sleep(1)

    print('submitting login_button')
    login_button = browser.find_element_by_xpath('//*[@type="submit"]')

    (ActionChains(browser).move_to_element(login_button).click().perform())

    # update server calls
    update_activity(Settings)

    sleep(1)

    # dismiss_get_app_offer(browser, logger)
    # dismiss_notification_offer(browser, logger)

    if bypass_suspicious_attempt is True:
        bypass_suspicious_login(browser, bypass_with_mobile)

    # wait until page fully load
    # explicit_wait(browser, "PFL", [], logger, 5)

    # Check if user is logged-in (If there's two 'nav' elements)
    nav = browser.find_elements_by_xpath('//div[@role="navigation"]')
    if len(nav) == 2:
        # create cookie for username
        print('logged in')
        pickle.dump(
            browser.get_cookies(),
            open('{0}{1}_cookie.pkl'.format(logfolder, username), 'wb'))
        return True
    else:
        return False
示例#17
0
def likers_from_post(browser, logger, Selectors, amount=20):
    """ Get the list of users from the 'Likes' dialog of a photo """

    liked_counter_button = \
        '//form/div/div/div/div/div/span/span/a[@role="button"]'

    try:
        liked_this = browser.find_elements_by_xpath(liked_counter_button)
        element_to_click = liked_this[0]
        # print('element_to_click:', element_to_click)
        # likers = []

        # for liker in liked_this:
        #     if " like this" not in liker.text:
        #         likers.append(liker.text)

        # if check_exists_by_xpath(browser, liked_counter_button):
        #     if " others" in liked_this[-1].text:
        #         element_to_click = liked_this[-1]

        #     elif " likes" in liked_this[0].text:
        #         element_to_click = liked_this[0]

        #     else:
        #         print("Few likes, not guaranteed you don't follow these"
        #               " likers already.\nGot photo likers: {}\n"
        #               .format(likers))
        #         return likers

        # else:
        #     print("Couldn't find liked counter button. May be a video.")
        #     print("Moving on..")
        #     return []

        sleep(1)
        click_element(browser, Settings, element_to_click)
        print("opening likes")
        # update server calls
        # update_activity(Settings)

        sleep(1)

        # get a reference to the 'Likes' dialog box
        dialog = browser.find_element_by_xpath(
            Selectors.likes_dialog_body_xpath)

        # scroll down the page
        previous_len = -1
        browser.execute_script(
            "arguments[0].scrollTop = arguments[0].scrollHeight", dialog)
        update_activity(Settings)
        sleep(1)

        start_time = time.time()
        user_list = []

        while (not user_list or (len(user_list) != previous_len) and
               (len(user_list) < amount)):

            previous_len = len(user_list)
            scroll_bottom(browser, dialog, 2)

            user_list = get_users_from_dialog(user_list, dialog, logger)
            # print('user_list (loop):')
            # print(user_list)

            # write & update records at Progress Tracker
            progress_tracker(len(user_list), amount, start_time, None)

            if previous_len + 10 >= amount:
                print("\nScrolling finished")
                sleep(1)
                break

        print('\n')
        # print('user_list:')
        # print(user_list)
        random.shuffle(user_list)
        sleep(1)

        close_dialog_box(browser)

        print("Got {} likers shuffled randomly whom you can follow:\n{}"
              "\n".format(len(user_list), user_list))
        return user_list

    except Exception as exc:
        print("Some problem occured!\n\t{}".format(str(exc).encode("utf-8")))
        return []
示例#18
0
def bypass_suspicious_login(browser, bypass_with_mobile):
    """Bypass suspicious loggin attempt verification. This should be only
    enabled
    when there isn't available cookie for the username, otherwise it will and
    shows "Unable to locate email or phone button" message, folollowed by
    CRITICAL - Wrong login data!"""
    # close sign up Facebook modal if available
    try:
        close_button = browser.find_element_by_xpath("[text()='Close']")

        (ActionChains(browser).move_to_element(close_button).click().perform())

        # update server calls
        update_activity(Settings)

    except NoSuchElementException:
        pass

    try:
        # click on "This was me" button if challenge page was called
        this_was_me_button = browser.find_element_by_xpath(
            "//button[@name='choice'][text()='This Was Me']")

        (ActionChains(browser).move_to_element(
            this_was_me_button).click().perform())

        # update server calls
        update_activity(Settings)

    except NoSuchElementException:
        # no verification needed
        pass

    try:
        choice = browser.find_element_by_xpath("//label[@for='choice_1']").text

    except NoSuchElementException:
        try:
            choice = browser.find_element_by_xpath(
                "//label[@class='_q0nt5']").text

        except Exception:
            try:
                choice = browser.find_element_by_xpath(
                    "//label[@class='_q0nt5 _a7z3k']").text

            except Exception:
                print("Unable to locate email or phone button, maybe "
                      "bypass_suspicious_login=True isn't needed anymore.")
                return False

    if bypass_with_mobile:
        choice = browser.find_element_by_xpath("//label[@for='choice_0']").text

        mobile_button = browser.find_element_by_xpath(
            "//label[@for='choice_0']")

        (ActionChains(browser).move_to_element(
            mobile_button).click().perform())

        sleep(5)

    send_security_code_button = browser.find_element_by_xpath(
        "//button[text()='Send Security Code']")

    (ActionChains(browser).move_to_element(
        send_security_code_button).click().perform())

    # update server calls
    update_activity(Settings)

    print('Facebook detected an unusual login attempt')
    print('A security code was sent to your {}'.format(choice))
    security_code = input('Type the security code here: ')

    security_code_field = browser.find_element_by_xpath(
        ("//input[@id='security_code']"))

    (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 i in range(2):
        update_activity(Settings)

    submit_security_code_button = browser.find_element_by_xpath(
        "//button[text()='Submit']")

    (ActionChains(browser).move_to_element(
        submit_security_code_button).click().perform())

    # update server calls
    update_activity(Settings)

    try:
        sleep(5)
        # locate wrong security code message
        wrong_login = browser.find_element_by_xpath(
            ("//p[text()='Please check the code we sent you and try "
             "again.']"))

        if wrong_login is not None:
            print(('Wrong security code! Please check the code Facebook'
                   'sent you and try again.'))

    except NoSuchElementException:
        # correct security code
        pass