예제 #1
0
def unfollow(self, track: str, person: str, button: Union[WebElement, None]):
    """ 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 self.quota_supervisor.jump_unfollow():
        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.instagram.com/{}/".format(person)
            if not check_if_in_correct_page(self, user_link):
                nf_go_to_user_page(self, person)

        for _ in range(3):
            following_status, follow_button = get_following_status(
                self, track, person)
            if following_status in ["Following", "Requested"]:
                nf_click_center_of_element(self, follow_button)
                sleep(3)
                confirm_unfollow(self)
                sleep(1)
                following_status, follow_button = get_following_status(
                    self, track, person)
                if following_status in ["Follow", "Follow Back"]:
                    break
            elif following_status in ["Follow", "Follow Back"]:
                self.logger.info(
                    "Already unfollowed '{}' or is a private user that "
                    "rejected your request".format(person))
                return False, "already unfollowed"
            elif following_status == "Unblock":
                self.logger.warning(
                    "Couldn't unfollow '{}', is blocked".format(person))
                return False, "blocked"
            elif following_status == "UNAVAILABLE":
                self.logger.warning(
                    "Couldn't unfollow '{}', is unavailable".format(person))
                return False, "unavailable"
            elif following_status is None:
                sirens_wailing, emergency_state = emergency_exit(self)
                if sirens_wailing is True:
                    return False, emergency_state
            else:
                self.logger.warning(
                    "Couldn't unfollow '{}', unexpected failure".format(
                        person))
                return False, "unexpected failure"
    elif track == "dialog" and button is not None:
        # Method of unfollowing from a dialog box
        nf_click_center_of_element(self, button)
        sleep(4)
        confirm_unfollow(self)

    self.logger.info("Unfollowed '{}'".format(person))
    self.quota_supervisor.add_unfollow()
    user, _ = InstaUser.objects.get_or_create(username=person)
    self.instauser.remove_following(user)
    return True, "success"
예제 #2
0
def get_following_status(
    self, track: str, person: str
) -> Tuple[str, Union[WebElement, None]]:  # following_status, follow_button
    """ Verify if you are following the user in the loaded page """
    if person == self.username:
        return "OWNER", None

    if track == "profile":
        user_link = "https://www.instagram.com/{}/".format(person)
        if not check_if_in_correct_page(self, user_link):
            nf_go_to_user_page(self, person)

    # check if the page is available
    valid_page = is_page_available(self)
    if not valid_page:
        self.logger.error(
            "Couldn't access the profile page of '{}', might have changed the"
            " username".format(person))
        return "UNAVAILABLE", None
    # wait until the follow button is located and visible, then get it
    try:
        self.browser.find_element_by_xpath(XP.FOLLOW_BUTTON_XP)
    except NoSuchElementException:
        try:
            follow_button = self.browser.find_element_by_xpath(
                XP.FOLLOW_SPAN_XP_FOLLOWING)
            return "Following", follow_button
        except:
            return "UNAVAILABLE", None

    follow_button = explicit_wait(self, "VOEL", [XP.FOLLOW_BUTTON_XP, "XPath"],
                                  7, False)

    if not follow_button:
        self.browser.execute_script(JS.RELOAD)
        self.quota_supervisor.add_server_call()
        follow_button = explicit_wait(self, "VOEL",
                                      [XP.FOLLOW_BUTTON_XP, "XPath"], 7, False)
        if not follow_button:
            # cannot find the any of the expected buttons
            self.logger.error(
                "Unable to detect the following status of '{}'".format(person))
            return "UNAVAILABLE", None

    # get follow status
    following_status = follow_button.text
    return following_status, follow_button
예제 #3
0
def interact_with_post(
    self,
    link: str,
    user_validated: bool = False,
) -> Tuple[str, Interactions]:  # msg, post_interactions
    interactions = Interactions()
    try:
        self.logger.debug("Checking post")
        if verify_liked_image(self):
            interactions.already_liked += 1
            return "already liked", interactions
        else:
            inappropriate, user_name, is_video, image_links, reason, scope = check_post(
                self, link)
        if not inappropriate:
            sleep(1)
            if user_validated:
                valid = True
                details = "User already validated"
            else:
                self.logger.debug("Validating user")
                valid, details = nf_validate_user_call(
                    self, user_name, self.quota_supervisor.LIKE, link)
                self.logger.info("'{}' is{} a valid user{}".format(
                    user_name, "" if valid else " not",
                    "" if valid else ": {}".format(details)))

            if not valid:
                interactions.not_valid_users += 1
                return "Not valid user", interactions

            # try to like
            self.logger.debug("Liking post")
            sleep(1)
            like_state, msg = like_image(self, user_name)

            if like_state is True:
                interactions.liked_img += 1
                # reset jump counter after a successful like
                self.jumps.likes = 0

                checked_img = True
                temp_comments = []

                commenting = random.randint(
                    0, 100) <= self.settings.comment_percentage
                following = random.randint(
                    0, 100) <= self.settings.follow_percentage
                interact = random.randint(
                    0, 100) <= self.settings.user_interact_percentage

                if self.settings.use_image_analysis and commenting:
                    try:
                        checked_img, temp_comments, image_analysis_tags = self.ImgAn.image_analysis(
                            image_links, logger=self.logger)
                    except Exception as err:
                        self.logger.error(
                            "Image analysis error: {}".format(err))

                # comment
                if (self.settings.do_comment and checked_img and commenting
                        and user_name not in self.settings.dont_include):
                    comments = self.settings.comments
                    comments.append(self.settings.video_comments if is_video
                                    else self.settings.photo_comments)
                    # TODO: util_comment
                    # success = process_comments(self, user_name, comments, temp_comments)
                    # if success:
                    #     interactions.commented += 1
                else:
                    if self.settings.do_comment:
                        self.logger.info("Not commented")
                    sleep(1)

                # follow or interact only of user not previously validated to avoid recursion
                if not user_validated:
                    # follow
                    if (self.settings.do_follow and checked_img and following
                            and user_name not in self.settings.dont_include
                            and not is_follow_restricted(self, user_name)):
                        self.logger.debug("Following user")
                        follow_state, msg = follow_user(
                            self, "post", user_name, None)
                        if follow_state is True:
                            interactions.followed += 1
                        elif msg == "already followed":
                            interactions.already_followed += 1
                        sleep(1)

                    # interact
                    if self.settings.do_like and interact:
                        self.logger.info(
                            "Interacting with user '{}'".format(user_name))
                        user_link = "https://www.instagram.com/{}/".format(
                            user_name)
                        if not check_if_in_correct_page(self, user_link):
                            nf_go_from_post_to_profile(self, user_name)
                        interactions += like_loop(
                            self, "Interact with user '{}'".format(user_name),
                            user_link, self.settings.user_interact_amount,
                            True)

            elif msg == "already liked":
                interactions.already_liked += 1
                return msg, interactions

            elif msg == "block on likes":
                return msg, interactions

            elif msg == "jumped":
                # will break the loop after certain consecutive jumps
                self.jumps.likes += 1

            return "success", interactions

        else:
            self.logger.info("Image not liked: {}\n{}".format(reason, scope))
            interactions.inap_img += 1
            return "inap_img", interactions

    except NoSuchElementException as err:
        self.logger.error("Invalid Page: {}".format(err))
        return "Invalid Page", interactions
    except Exception as err:
        self.logger.error("Unexpected Exception: {}".format(err))
        return "Unexpected Exception", interactions
예제 #4
0
def db_store_comments(self, posts: List[Post], post_link: str):
    """Stores all comments of open post then goes back to post page"""
    try:
        comments_button = self.browser.find_elements_by_xpath(
            '//article//div[2]/div[1]//a[contains(@href,"comments")]')
        if comments_button:
            nf_scroll_into_view(self, comments_button[0])
            nf_click_center_of_element(self, comments_button[0])
            sleep(2)
            comments_link = post_link + 'comments/'
            if not check_if_in_correct_page(self, comments_link):
                self.logger.error(
                    "Failed to go to comments page, navigating there")
                # TODO: retry to get there naturally
                web_address_navigator(self.browser, comments_link)
            more_comments = self.browser.find_elements_by_xpath(
                '//span[@aria-label="Load more comments"]')
            counter = 1
            while more_comments and counter <= 10:
                self.logger.info("Loading comments ({}/10)...".format(counter))
                nf_scroll_into_view(self, more_comments[0])
                self.browser.execute_script("arguments[0].click();",
                                            more_comments[0])
                more_comments = self.browser.find_elements_by_xpath(
                    '//span[@aria-label="Load more comments"]')
                counter += 1

            comments = self.browser.find_elements_by_xpath(
                '/html/body/div[1]/section/main/div/ul/ul[@class="Mr508"]')
            for comment in comments:
                inner_container = comment.find_element_by_xpath(
                    './/div[@class="C4VMK"]')
                username = inner_container.find_element_by_xpath(
                    './/h3/div/a').text
                text, _ = deform_emojis(
                    inner_container.find_element_by_xpath('.//span').text)
                post_date = inner_container.find_element_by_xpath(
                    './/time').get_attribute('datetime')
                post_date = datetime.fromisoformat(post_date[:-1])

                user = db_get_or_create_user(self, username)
                self.db.session.add(user)
                self.db.session.commit()

                for post in posts:
                    comment = Comment(
                        date_posted=post_date,
                        text=text,
                        user=user,
                        post=post,
                    )
                    self.db.session.add(comment)
                    self.db.session.commit()
        else:
            self.logger.error("No comments found")
    except SQLAlchemyError:
        self.db.session.rollback()
        raise
    finally:
        self.db.session.commit()
        nf_find_and_press_back(self, post_link)
예제 #5
0
def follow_user_follow(
        self,
        follow: str,
        usernames: List[str],
        amount: int = 10,
        randomize: bool = False
):
    if self.aborting:
        return self

    valid = {"followers", "followings"}
    if follow not in valid:
        raise ValueError(
            "nf_follow_user_follow: follow must be one of %r." % valid)

    self.logger.info("Starting to follow user {}".format(follow))

    for index, username in enumerate(usernames):
        state = {
            'liked_img': 0,
            'already_liked': 0,
            'inap_img': 0,
            'commented': 0,
            'followed': 0,
            'not_valid_users': 0,
        }

        self.logger.info("User [{}/{}]".format(index + 1, len(usernames)))
        self.logger.info("--> {}".format(username.encode("utf-8")))

        nf_go_to_user_page(self, username)
        sleep(1)

        # TODO: get follow count
        follow_count = 10
        actual_amount = amount
        if follow_count < amount:
            actual_amount = follow_count

        self.logger.info("About to go to {} page".format(follow))
        nf_go_to_follow_page(self, follow, username)
        sleep(2)

        sc_rolled = 0
        scroll_nap = 1.5
        already_interacted_links = []
        random_chance = 50
        try:
            while state['followed'] in range(0, actual_amount):
                if self.quotient_breach:
                    self.logger.warning(
                        "--> Follow quotient reached its peak!"
                        "\t~leaving Follow-User-Follow_ activity\n"
                    )
                    break

                if sc_rolled > 100:
                    self.logger.info("Scrolled too much! ~ sleeping 10 minutes")
                    sleep(600)
                    sc_rolled = 0

                users = nf_get_all_users_on_element(self)

                # Interact with links instead of just storing them
                for user in users:
                    link = user.get_attribute("href")
                    if link not in already_interacted_links:
                        msg = ""
                        try:
                            self.logger.info("about to scroll to user")
                            sleep(1)
                            nf_scroll_into_view(self, user)
                            self.logger.info("about to click to user")
                            sleep(1)
                            nf_click_center_of_element(self, user)
                            sleep(2)
                            valid = False
                            if (
                                    user.text not in self.dont_include
                                    and not follow_restriction(
                                        "read", user.text, self.follow_times, self.logger
                                    and random.randint(0, 100) <= random_chance
                                    )
                            ):
                                valid, details = nf_validate_user_call(self, user.text)
                                self.logger.info("Valid User: {}, details: {}".format(valid, details))
                            if valid:
                                self.logger.info("about to follow user")
                                follow_state, msg = follow_user(
                                    self.browser,
                                    "profile",
                                    self.username,
                                    user.text,
                                    None,
                                    self.blacklist,
                                    self.logger,
                                    self.logfolder,
                                )
                                if follow_state is True:
                                    state['followed'] += 1
                                    self.logger.info("user followed")
                                else:
                                    self.logger.info("--> Not following")
                                    sleep(1)
                                if random.randint(0, 100) <= self.user_interact_percentage:
                                    self.logger.info(
                                        "--> User gonna be interacted: '{}'".format(
                                            user.text
                                        )
                                    )
                                # disable re-validating user in like_by_users
                                like_by_users(
                                    self,
                                    [user.text],
                                    None,
                                    True,
                                )
                            else:
                                state["not_valid_users"] += 1

                        finally:
                            sleep(5)
                            user_link = "https://www.instagram.com/{}".format(username)
                            follow_link = "https://www.instagram.com/{}/{}".format(username, follow)
                            nf_find_and_press_back(self, follow_link)
                            sleep(3)
                            if check_if_in_correct_page(self, user_link):
                                nf_go_to_follow_page(self, follow, username)
                            already_interacted_links.append(link)
                            if msg == "block on follow":
                                pass  # TODO deal with block on follow
                            break
                else:
                    # For loop ended means all users in screen has been interacted with
                    scrolled_to_bottom = self.browser.execute_script(
                        "return window.scrollMaxY == window.scrollY"
                    )
                    if scrolled_to_bottom and randomize and random_chance < 100:
                        random_chance += 25
                        self.browser.execute_script(
                            "window.scrollTo(0, 0);"
                        )
                        update_activity(self.browser, state=None)
                        sc_rolled += 1
                        sleep(scroll_nap)
                    elif scrolled_to_bottom:
                        # already followed all possibles users
                        break
                    # will scroll the screen a bit and reload
                    for i in range(3):
                        self.browser.execute_script(
                            "window.scrollTo(0, document.body.scrollHeight);"
                        )
                        update_activity(self.browser, state=None)
                        sc_rolled += 1
                        sleep(scroll_nap)

        except Exception:
            raise

        sleep(4)

        self.logger.info("User [{}/{}]".format(index + 1, len(usernames)))
        self.logger.info("Liked: {}".format(state['liked_img']))
        self.logger.info("Already Liked: {}".format(state['already_liked']))
        self.logger.info("Commented: {}".format(state['commented']))
        self.logger.info("Followed: {}".format(state['followed']))
        self.logger.info("Inappropriate: {}".format(state['inap_img']))
        self.logger.info("Not valid users: {}\n".format(state['not_valid_users']))

        self.liked_img += state['liked_img']
        self.already_liked += state['already_liked']
        self.commented += state['commented']
        self.followed += state['followed']
        self.inap_img += state['inap_img']
        self.not_valid_users += state['not_valid_users']

    return self
예제 #6
0
    def follow_by_list(self,
                       follow_list: List[str],
                       users_validated: bool = False):
        """
        Follows users in 'follow_list'

        :param follow_list: list of usernames to follow
        :param users_validated: if users are already considered valid to follow them
        """
        if self.aborting:
            return self

        interactions = Interactions()

        # for each username
        for index, username in enumerate(follow_list):
            # if aborting or quota was breached or its past time according to settings break the loop
            if self.aborting or self.quotient_breach or (
                    self.until_time and datetime.now() > self.until_time):
                break

            # if quotient was breached break the loop
            if self.jumps.check_follows():
                self.logger.warning(
                    "Follow quotient reached its peak, leaving Follow by List activity"
                )
                self.jumps.follows = 0
                self.quotient_breach = True
                break

            self.logger.info("Follow User [{}/{}] - started".format(
                index + 1, len(follow_list)))
            user_link = "https://www.instagram.com/{}".format(username)

            # skip to next in list if the user is follow restricted
            if is_follow_restricted(self, username):
                interactions.already_followed += 1
                self.logger.info("Account {} already followed {} times".format(
                    username, self.settings.follow_times))
                continue

            # validate user if not considered valid
            if not users_validated:
                validation, details = nf_validate_user_call(
                    self, username, self.quota_supervisor.FOLLOW)
                if not validation:
                    self.logger.info(
                        "--> Not a valid user: {}".format(details))
                    interactions.not_valid_users += 1
                    continue

            # follow user
            follow_state, msg = follow_user(self, "profile", username)
            if follow_state is True:
                interactions.followed += 1
                self.logger.debug("user followed")
            elif msg == "already followed":
                interactions.already_followed += 1
            elif msg == "jumped":
                # will break the loop after certain consecutive jumps
                self.jumps.follows += 1

            # interact with user
            if self.settings.do_like and random.randint(
                    0, 100) <= self.settings.user_interact_percentage:
                self.logger.info("Interacting with user '{}'".format(username))
                if not check_if_in_correct_page(self, user_link):
                    nf_go_from_post_to_profile(self, username)
                interactions += like_loop(
                    self, "Interact with user '{}'".format(username),
                    user_link, self.settings.user_interact_amount, True)

            self.logger.info("Follow User [{}/{}] - ended".format(
                index + 1, len(follow_list)))

        self.logger.info(str(interactions))
        self.interactions += interactions
        return self
예제 #7
0
    def follow_user_follow(self,
                           relation: str,
                           usernames: List[str],
                           amount: int = 10,
                           randomize: bool = False,
                           random_chance: int = 50):
        """
        Follows 'amount' users of 'relation' ("following" or "followers") list of each user in usernames

        :param relation: what list to use, "following" or "followers"
        :param usernames: list of usernames to follow relations of
        :param amount: amount of users to follow for each user in 'usernames'
        :param randomize: if the bot will include a random factor to choose who to follow or
        follow the first 'amount' of usernames on the list
        :param random_chance: chance a user will be followed if using 'randomize'
        """
        if self.aborting:
            return self

        valid = {"followers", "following"}
        if relation not in valid:
            self.logger.info(
                '{} is not a valid relation, using "followers"'.format(
                    relation))
            relation = "followers"

        self.logger.info("Starting to follow users {}".format(relation))

        # for each username
        for index, username in enumerate(usernames):
            # if aborting or quota was breached or its past time according to settings break the loop
            if self.aborting or self.quotient_breach or (
                    self.until_time and datetime.now() > self.until_time):
                break

            interactions = Interactions()

            self.logger.info("Follow User {} [{}/{}]: {} - started".format(
                relation, index + 1, len(usernames), username))

            user_link = "https://www.instagram.com/{}".format(username)
            follow_link = "https://www.instagram.com/{}/{}".format(
                username, relation)

            # navigate to user page
            if not check_if_in_correct_page(self, user_link):
                nf_go_to_user_page(self, username)
                sleep(1)

            # get followers & following counts and change amount if less than desired
            followers_count, following_count = get_relationship_counts(
                self, username)
            follow_count = following_count if relation == "following" else followers_count
            follow_count = follow_count if follow_count else 0
            actual_amount = amount
            if follow_count < amount:
                actual_amount = follow_count

            # go to relation page
            nf_go_to_follow_page(self, relation, username)
            sleep(2)

            # follow users
            sc_rolled = 0
            scroll_nap = 1.5
            already_interacted_links = []
            while interactions.followed in range(actual_amount):
                # if aborting or quota was breached or its past time according to settings break the loop
                if self.aborting or (self.until_time
                                     and datetime.now() > self.until_time):
                    break

                # if quotient was breached break the loop
                if self.jumps.check_follows():
                    self.logger.warning(
                        "Follow quotient reached its peak, leaving Follow User {} activity"
                        .format(relation))
                    # reset jump counter before breaking the loop
                    self.jumps.follows = 0
                    self.quotient_breach = True
                    break

                # if scrolled too much sleep for 5-10 minutes
                if sc_rolled > 100:
                    delay_random = random.randint(300, 600)
                    self.logger.info(
                        "Scrolled too much, sleeping {} minutes and {} seconds"
                        .format(int(delay_random / 60), delay_random % 60))
                    sleep(delay_random)
                    sc_rolled = 0

                # get loaded usernames
                users = nf_get_all_users_on_element(self)
                # if no users were grabbed try to go back and load the relation page again
                while len(users) == 0:
                    nf_find_and_press_back(self, user_link)
                    in_user_page = check_if_in_correct_page(self, user_link)
                    if not in_user_page:
                        nf_go_to_user_page(self, username)
                    nf_go_to_follow_page(self, relation, username)
                    # get loaded usernames
                    users = nf_get_all_users_on_element(self)
                    # If after rechecking we are in the correct page there still no are users
                    # the bot is most surely soft blocked from seeing relations, that block doesnt last long usually.
                    # sleep for 5-10 minutes
                    if len(users) == 0:
                        delay_random = random.randint(300, 600)
                        self.logger.info(
                            "Soft block on see followers, "
                            "sleeping {} minutes and {} seconds".format(
                                int(delay_random / 60), delay_random % 60))
                        sleep(delay_random)
                self.logger.debug("Grabbed {} usernames".format(len(users)))

                # first one in the list is un-clickable by bad design on browser instagram, its behind the top bar
                for user in users[1:]:
                    link = user.get_attribute("href")
                    # try to follow first not already interacted user
                    if link not in already_interacted_links:
                        msg = ""
                        try:
                            user_text = user.text
                            user_link2 = "https://www.instagram.com/{}".format(
                                user_text)
                            self.logger.info("Followed [{}/{}]".format(
                                interactions.followed, actual_amount))
                            # Go to user page
                            self.logger.info(
                                "Trying user {}".format(user_text))
                            nf_scroll_into_view(self, user)
                            sleep(1)
                            nf_click_center_of_element(self, user, user_link2)
                            sleep(2)

                            # validate user
                            valid = False
                            if (user_text not in self.settings.dont_include and
                                    not is_follow_restricted(self, user_text)
                                    and
                                    random.randint(0, 100) <= random_chance):
                                valid, details = nf_validate_user_call(
                                    self, user_text,
                                    self.quota_supervisor.FOLLOW)
                                self.logger.info(
                                    "Valid User: {}, details: {}".format(
                                        valid, details))
                            # follow user
                            if valid:
                                follow_state, msg = follow_user(
                                    self, "profile", user_text)
                                if follow_state is True:
                                    interactions.followed += 1
                                elif msg == "already followed":
                                    interactions.already_followed += 1
                                elif msg == "jumped":
                                    # will break the loop after certain consecutive jumps
                                    self.jumps.follows += 1
                                # interact with user
                                if (self.settings.do_like
                                        and random.randint(0, 100) <=
                                        self.settings.user_interact_percentage
                                    ):
                                    self.logger.info(
                                        "Interacting with user '{}'".format(
                                            user_text))
                                    if not check_if_in_correct_page(
                                            self, user_link2):
                                        nf_go_from_post_to_profile(
                                            self, user_text)
                                    interactions += like_loop(
                                        self, "Interact with user '{}'".format(
                                            user_text), user_link2,
                                        self.settings.user_interact_amount,
                                        True)
                            else:
                                interactions.not_valid_users += 1
                        except Exception as e:
                            self.logger.error(e)
                        finally:
                            # go back to relation page and start the loop again
                            sleep(1)
                            nf_find_and_press_back(self, follow_link)
                            in_follow_page = check_if_in_correct_page(
                                self, follow_link)
                            if not in_follow_page:
                                in_user_page = check_if_in_correct_page(
                                    self, user_link)
                                if not in_user_page:
                                    nf_go_to_user_page(self, username)
                                nf_go_to_follow_page(self, relation, username)

                            already_interacted_links.append(link)
                            if msg == "block on follow":
                                # raise SoftBlockedException(msg)
                                pass  # TODO: deal with block on follow
                            break
                else:
                    # For loop ended means all users in screen has been interacted with
                    scrolled_to_bottom = self.browser.execute_script(
                        JS.SCROLLED_TO_BOTTOM)
                    # even if we are at the bottom if we were using randomize some users were ignored
                    # so the bot can go back and look again with a higher random chance to foollow the users
                    if scrolled_to_bottom and randomize and random_chance < 100:
                        random_chance += 25
                        self.browser.execute_script(JS.SCROLL_TO_TOP)
                        self.quota_supervisor.add_server_call()
                        sc_rolled += 1
                        sleep(scroll_nap)
                    elif scrolled_to_bottom:
                        # already followed all possibles users
                        break
                    # if not at the bottom of the list
                    # will scroll the screen a bit and look again
                    for i in range(3):
                        self.browser.execute_script(JS.SCROLL_SCREEN)
                        self.quota_supervisor.add_server_call()
                        sc_rolled += 1
                        sleep(scroll_nap)

            sleep(3)
            self.logger.info("Follow User {} [{}/{}] - ended".format(
                relation, index + 1, len(usernames)))
            self.logger.info(str(interactions))
            self.interactions += interactions

        return self
예제 #8
0
    def like_by_users(self,
                      usernames: List[str],
                      amount: int = None,
                      users_validated: bool = False):
        """
        Likes 'amount' (default bot settings 'user_interact_amount') images per given user,
        before it starts liking it may follow the user and after each like it may comment the post,
        according to bot settings

        :param usernames: list of usernames to like posts of
        :param amount: amount of post to like in each user feed
        :param users_validated: if users are already considered valid to like them
        """
        if self.aborting:
            return self

        amount = amount or self.settings.user_interact_amount
        usernames = usernames or []
        self.quotient_breach = False

        # for each username
        for index, username in enumerate(usernames):
            # if aborting or quota was breached or its past time according to settings break the loop
            if self.aborting or self.quotient_breach or (
                    self.until_time and datetime.now() > self.until_time):
                break

            # clean username
            username = username.strip()
            user_link = "https://www.instagram.com/{}/".format(username)
            interactions = Interactions()

            self.logger.info("Like by User [{}/{}]: {} - started".format(
                index + 1, len(usernames), username))

            # navigate to user feed
            if not check_if_in_correct_page(self, user_link):
                nf_go_to_user_page(self, username)
                sleep(1)

            # validate user according to settings
            if not users_validated:
                valid, details = nf_validate_user_call(
                    self, username, self.quota_supervisor.LIKE)
                self.logger.info("'{}' is{} a valid user{}".format(
                    username, "" if valid else " not",
                    "" if valid else ": {}".format(details)))
                if not valid:
                    interactions.not_valid_users += 1
                    continue

            # follow user according to settings
            if (self.settings.do_follow
                    and username not in self.settings.dont_include and
                    random.randint(0, 100) <= self.settings.follow_percentage
                    and not is_follow_restricted(self, username)):
                self.logger.debug("Following user")
                follow_state, msg = follow_user(self, "profile", username,
                                                None)
                if follow_state is True:
                    interactions.followed += 1
                elif msg == "already followed":
                    interactions.already_followed += 1
                sleep(1)

            # like images
            interactions += like_loop(
                self, "User [{}/{}]: {}".format(index + 1, len(usernames),
                                                username), user_link, amount,
                True)

            self.logger.info("Like by User [{}/{}]: {} - ended".format(
                index + 1, len(usernames), username))
            self.logger.info(str(interactions))
            self.interactions += interactions

        return self
예제 #9
0
def get_follow(
    self, username: str, follow: str
) -> Set[str]:  # set of followers or following of given username

    valid = {"followers", "following"}
    if follow not in valid:
        raise ValueError("get_follow: follow must be one of %r." % valid)

    user_link = "https://www.instagram.com/{}/".format(username)
    if not check_if_in_correct_page(self, user_link):
        if self.username == username:
            go_to_bot_user_page(self)
        else:
            nf_go_to_user_page(self, username)

    if follow == 'followers':
        query = self.instauser.followers.all()
    else:
        query = self.instauser.following.all()

    usernames = set([instauser.username for instauser in query])
    followers_count, following_count = get_relationship_counts(self, username)
    count = followers_count if follow == 'followers' else following_count
    if count == len(usernames):
        return usernames

    sleep(2)
    nf_go_to_follow_page(self, follow, username)
    sleep(2)

    sc_rolled = 0
    scroll_nap = 1.5
    seen_usernames = []
    try:
        while True:
            if self.aborting or (self.until_time
                                 and datetime.now() > self.until_time):
                break

            if sc_rolled > 100:
                delay_random = random.randint(400, 600)
                self.logger.info(
                    "Scrolled too much, sleeping {} minutes and {} seconds".
                    format(int(delay_random / 60), delay_random % 60))
                sleep(delay_random)
                sc_rolled = 0

            users = nf_get_all_users_on_element(self)
            while len(users) == 0:
                nf_find_and_press_back(self, user_link)
                in_user_page = check_if_in_correct_page(self, user_link)
                if not in_user_page:
                    nf_go_to_user_page(self, username)
                nf_go_to_follow_page(self, follow, username)
                users = nf_get_all_users_on_element(self)
                if len(users) == 0:
                    delay_random = random.randint(200, 300)
                    self.logger.info(
                        "Soft block on see {}, "
                        "sleeping {} minutes and {} seconds".format(
                            follow, int(delay_random / 60), delay_random % 60))
                    sleep(300)
            for user in users[1:]:
                link = user.get_attribute("href")
                user_text = user.text
                if user_text not in seen_usernames:
                    seen_usernames.append(user_text)
                    if user_text not in usernames:
                        add_follow_times(self, user_text)
            else:
                # For loop ended means all users in screen have been saved
                scrolled_to_bottom = self.browser.execute_script(
                    JS.SCROLLED_TO_BOTTOM)
                if scrolled_to_bottom:
                    # already saved all possibles users
                    break
                # will scroll the screen a bit and grab usernames again
                for i in range(3):
                    self.browser.execute_script(JS.SCROLL_SCREEN)
                    self.quota_supervisor.add_server_call()
                    sc_rolled += 1
                    sleep(scroll_nap)
            if scrolled_to_bottom:
                # already saved all possibles users
                break
    except Exception:
        raise

    usernames = usernames.union(set(seen_usernames))
    self.logger.info("Grabbed {} {} names".format(len(usernames), follow))
    return usernames
예제 #10
0
def follow_user(
    self,
    track: str,
    user_name: str,
    button: Union[WebElement, None] = None
) -> Tuple[bool, str]:  # follow_state, msg
    """ 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 self.quota_supervisor.jump_follow():
        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.instagram.com/{}/".format(user_name)
            if not check_if_in_correct_page(self, user_link):
                nf_go_to_user_page(self, user_name)

        # find out CURRENT following status
        for _ in range(3):
            following_status, follow_button = get_following_status(
                self, track, user_name)
            if following_status in ["Follow", "Follow Back"]:
                nf_scroll_into_view(self, follow_button)
                nf_click_center_of_element(self,
                                           follow_button,
                                           skip_action_chain=True)
                sleep(3)
                following_status, follow_button = get_following_status(
                    self, track, user_name)
                if following_status in ["Following", "Requested"]:
                    break
            elif following_status == "Following":
                self.logger.info("Already following '{}'".format(user_name))
                return False, "already followed"
            elif following_status == "Requested":
                self.logger.info(
                    "Already requested '{}' to follow".format(user_name))
                return False, "already requested"
            elif following_status == "Unblock":
                self.logger.info("User '{}' is blocked".format(user_name))
                return False, "user is blocked"
            elif following_status == "UNAVAILABLE":
                self.logger.info("User '{}' is inaccessible".format(user_name))
                return False, "user is inaccessible"
            elif following_status is None:
                sirens_wailing, emergency_state = emergency_exit(self)
                if sirens_wailing is True:
                    return False, emergency_state
            else:
                self.logger.warning(
                    "Couldn't follow '{}', unexpected failure".format(
                        user_name))
                return False, "unexpected failure"
    elif track == "dialog":
        nf_click_center_of_element(self, button)

    # general tasks after a successful follow
    self.logger.info("Followed {}".format(user_name))
    add_follow_times(self, user_name)
    add_user_to_blacklist(self, user_name, self.quota_supervisor.FOLLOW)
    self.quota_supervisor.add_follow()
    return True, "success"