Beispiel #1
0
    def shuffle_actions(self, actions):
        if len(actions) <= 1:
            sleep(7 * 60)
            return actions

        old_order = actions[:]
        random.shuffle(actions)

        if actions[0] == old_order[-1]:
            actions = actions[1:] + actions[0:1]
        return actions
Beispiel #2
0
def like_comment(browser, original_comment_text, logger):
    """ Like the given comment """
    comments_block_XPath = read_xpath(
        like_comment.__name__, "comments_block"
    )  # quite an efficient
    # location path

    try:
        comments_block = browser.find_elements_by_xpath(comments_block_XPath)
        for comment_line in comments_block:
            comment_elem = comment_line.find_elements_by_tag_name("span")[0]
            comment = extract_text_from_element(comment_elem)

            if comment and (comment == original_comment_text):
                # find "Like" span (a direct child of Like button)
                span_like_elements = comment_line.find_elements_by_xpath(
                    read_xpath(like_comment.__name__, "span_like_elements")
                )
                if not span_like_elements:
                    # this is most likely a liked comment
                    return True, "success"

                # like the given comment
                span_like = span_like_elements[0]
                comment_like_button = span_like.find_element_by_xpath(
                    read_xpath(like_comment.__name__, "comment_like_button")
                )
                click_element(browser, comment_like_button)

                # verify if like succeeded by waiting until the like button
                # element goes stale..
                button_change = explicit_wait(
                    browser, "SO", [comment_like_button], logger, 7, False
                )

                if button_change:
                    logger.info("--> Liked the comment!")
                    sleep(random.uniform(1, 2))
                    return True, "success"

                else:
                    logger.info("--> Unfortunately, comment was not liked.")
                    sleep(random.uniform(0, 1))
                    return False, "failure"

    except (NoSuchElementException, StaleElementReferenceException) as exc:
        logger.error(
            "Error occured while liking a comment.\n\t{}\n\n".format(
                str(exc).encode("utf-8")
            )
        )
        return False, "error"

    return None, "unknown"
Beispiel #3
0
    def act(self, count=0):
        if self.aborting:
            return

        actions = self.get_actions(self.settings or {})

        while datetime.datetime.now() < self.end_time:
            try:
                self.shuffle_actions(actions)
                self.logger.warning("shuffled actions: %s" %
                                    list(map(lambda a: a["name"], actions)))
                for f in actions:
                    if self.aborting:
                        self.logger.warning("ABORTING")
                        return

                    self.logger.warning("RUN: %s" % f["name"])
                    f["fun"]()
                    count = 0
                    sleep(1 * 60)

                sleep(2 * 60)

            except NoSuchElementException as exc:
                # if changes to IG layout, upload the file to help us locate the change
                file_path = os.path.join(
                    gettempdir(),
                    '{}.html'.format(time.strftime('%Y%m%d-%H%M%S')))
                with open(file_path, 'wb') as fp:
                    fp.write(self.browser.page_source.encode('utf8'))
                print(
                    '{0}\nIf raising an issue, please also upload the file located at:\n{1}\n{0}'
                    .format('*' * 70, file_path))
                # full stacktrace when raising Github issue
                self.logger.exception(exc)
            except (ConnectionRefusedError, RemoteDisconnected, ProtocolError,
                    MaxRetryError, AttributeError) as exc:
                return self.try_again(count, exc)
            except Exception as exc:
                if 'RemoteDisconnected' in str(exc):
                    return self.try_again(count, exc)

                self.logger.error("Excepiton in act(): %s \n %s" %
                                  (exc, traceback.format_exc()))
                raise
Beispiel #4
0
def get_links(browser, page, logger, media, element):
    links = []
    try:
        # Get image links in scope from hashtag, location and other pages
        link_elems = element.find_elements_by_xpath('//a[starts-with(@href, "/p/")]')
        sleep(2)
        if link_elems:
            for link_elem in link_elems:
                try:
                    post_href = link_elem.get_attribute("href")
                    post_elem = element.find_elements_by_xpath(
                        "//a[@href='/p/" + post_href.split("/")[-2] + "/']/child::div"
                    )

                    if len(post_elem) == 1 and MEDIA_PHOTO in media:
                        # Single photo
                        links.append(post_href)

                    if len(post_elem) == 2:
                        # Carousel or Video
                        post_category = element.find_element_by_xpath(
                            "//a[@href='/p/"
                            + post_href.split("/")[-2]
                            + "/']/child::div[@class='u7YqG']/child::div"
                        ).get_attribute("aria-label")

                        if post_category in media:
                            links.append(post_href)
                except WebDriverException:
                    logger.info(
                        "Cannot detect post media type. Skip {}".format(post_href)
                    )
        else:
            logger.info("'{}' page does not contain a picture".format(page))
    except BaseException as e:
        logger.error("link_elems error {}".format(str(e)))
    return links
Beispiel #5
0
def like_image(browser, username, blacklist, logger, logfolder, total_liked_img):
    """Likes the browser opened image"""
    # check action availability
    if quota_supervisor("likes") == "jump":
        return False, "jumped"

    like_xpath = read_xpath(like_image.__name__, "like")
    unlike_xpath = read_xpath(like_image.__name__, "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)
        like_elem = browser.find_elements_by_xpath(like_xpath)
        click_element(browser, 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!")
            Event().liked(username)
            update_activity(
                browser, action="likes", state=None, logfolder=logfolder, logger=logger
            )

            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")
            sleep(naply)

            # after every 10 liked image do checking on the block
            if total_liked_img % 10 == 0 and not verify_liked_image(browser, logger):
                return False, "block on likes"

            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"
Beispiel #6
0
    def act(self):
        env = self.settings or {}
        actions = [
            lambda: self.like_by_tags(
                tags=shuffle(env.get("like_by_tags", []))
                if env.get("enable_like_by_tags", True) else [],
                amount=env.get("like_by_tags_amount", 1),
                skip_top_posts=env.get("like_by_tags_skip_top_posts", True),
                use_smart_hashtags=env.get("like_by_tags_use_smart_hashtags",
                                           False),
                interact=env.get("like_by_tags_interact", False)),
            lambda: self.like_by_locations(
                locations=shuffle(env.get("like_by_locations", []))
                if env.get("enable_like_by_locations", True) else [],
                amount=env.get("like_by_locations_amount", 1),
                skip_top_posts=env.get("like_by_locations_skip_top_posts", True
                                       )),
            lambda: self.follow_user_followers(
                usernames=shuffle(env.get("follow_user_followers", []))
                if env.get("enable_follow_user_followers", True) else [],
                amount=env.get("follow_user_followers_amount", 9),
                randomize=env.get("follow_user_followers_randomize", False),
                interact=env.get("follow_user_followers_interact", True),
                sleep_delay=env.get("follow_user_followers_sleep_delay", 600)),
            lambda: self.like_by_feed(
                amount=env.get("like_by_feed_amount", 10)
                if env.get("enable_like_by_feed", True) else 0,
                randomize=env.get("like_by_feed_randomize", True),
                unfollow=env.get("like_by_feed_unfollow", False),
                interact=env.get("like_by_feed_interact", False)),
            lambda: self.unfollow_users(
                amount=env.get("unfollow_users_amount", 50)
                if env.get("enable_unfollow", True) else 0,
                # customList=(False, [], "all"),
                InstapyFollowed=(env.get("unfollow_users_InstapyFollowed", True
                                         ), "nonfollowers"
                                 if env.get("unfollow_users_nonfollowers",
                                            False) else "all"),
                # 'all' or 'nonfollowers'
                # nonFollowers=False,
                # allFollowing=False,
                style=env.get("unfollow_users_style", 'FIFO'
                              ),  # or 'LIFO', 'RANDOM'
                unfollow_after=env.get("unfollow_users_unfollow_after", 2) * 24
                * 60 * 60,
                sleep_delay=env.get("unfollow_users_sleep_delay", 600))
        ]

        while datetime.datetime.now() < self.end_time:
            try:
                sleep(10)
                random.shuffle(actions)
                for f in actions:
                    f()

            except Exception as exc:
                # if changes to IG layout, upload the file to help us locate the change
                if isinstance(exc, NoSuchElementException):
                    file_path = os.path.join(
                        gettempdir(),
                        '{}.html'.format(time.strftime('%Y%m%d-%H%M%S')))
                    with open(file_path, 'wb') as fp:
                        fp.write(self.browser.page_source.encode('utf8'))
                    print(
                        '{0}\nIf raising an issue, please also upload the file located at:\n{1}\n{0}'
                        .format('*' * 70, file_path))
                # full stacktrace when raising Github issue
                self.logger.exception(exc)
Beispiel #7
0
def get_links_for_username(
    browser,
    username,
    person,
    amount,
    logger,
    logfolder,
    randomize=False,
    media=None,
    taggedImages=False,
    imageToFind=None
):
    """
    Fetches the number of links specified by amount and returns a list of links
    """

    if media is None:
        # All known media types
        media = MEDIA_ALL_TYPES
    elif media == MEDIA_PHOTO:
        # Include posts with multiple images in it
        media = [MEDIA_PHOTO, MEDIA_CAROUSEL]
    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.instagram.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)

    if not is_page_available(browser, logger):
        logger.error(
            "Instagram 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_status, _ = get_following_status(
        browser, "profile", username, person, None, logger, logfolder
    )

    # if following_status is None:
    #    browser.wait_for_valid_connection(browser, username, logger)

    # if following_status == 'Follow':
    #    browser.wait_for_valid_authorization(browser, username, logger)

    is_private = is_private_profile(browser, logger, following_status == "Following")
    if (
        is_private is None
        or (is_private is True and following_status not in ["Following", True])
        or (following_status == "Blocked")
    ):
        logger.info("This user is private and we are not following")
        return False

    web_address_navigator(browser, user_link)


    # 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
        sleep(1.25)
        browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        # update server calls after a scroll request
        update_activity(browser, state=None)

        # using `extend`  or `+=` results reference stay alive which affects
        # previous assignment (can use `copy()` for it)
        main_elem = browser.find_element_by_tag_name("article")

        tempLinks = get_links(browser, person, logger, media, main_elem)
        links = links + tempLinks
        links = sorted(set(links), key=links.index)

        if len(tempLinks)>0 and (imageToFind is not None) and (imageToFind in tempLinks):
            break

        if len(links) == len(initial_links):
            logger.info("Pausing 45s during scroll for new links.  Currently at: {} of {} (attempt:{})".format(len(links),amount,attempt))
            sleep(45.0)
            if attempt >= 60:
                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]
Beispiel #8
0
def OnePass(username, password, username1, amountToQuickscan, amountToLookup,
            iCnt, iMax):

    # start the scan

    session = InstaPy(username=username, password=password)
    session.login()
    prepare_my_database(session.logger)

    randomize = False
    media = MEDIA_PHOTO
    taggedImages = True

    links = []
    try:

        #   build list of links to ignore from the data base:  those recently queried (less than 20 hours old) and those posted more than 72 hours ago.
        ignore_links = getFreshTaggedLinks(username1)
        ignore_links = list(dict.fromkeys(ignore_links))

        fresh_links = get_links_for_username(session.browser, session.username,
                                             username1, amountToQuickscan,
                                             session.logger, session.logfolder,
                                             randomize, media, taggedImages)
        links = list(set(fresh_links) - set(ignore_links))
        session.logger.info("Links quickscanned: {}".format(len(fresh_links)))
        session.logger.info("Links to ignore: {}".format(len(ignore_links)))

        links = links[:amountToLookup] if len(
            links) > amountToLookup else links
        session.logger.info("Links to lookup: {}".format(len(links)))

    except NoSuchElementException:
        session.logger.error("Element not found, skipping this username")

    i = 0
    # for each link in the list, follow it and grab lots of statistics.  This consumes instagram resources.
    # then follow the posting username and get their statistics.  This consumes instragram resources.

    sleep(1.2)

    for i, posted_link in enumerate(links):

        sleep(3.0)
        #        session.logger.info("Processing link {}:{}".format(i+1,len(links)))
        session.logger.info(
            "Processing link:{}   {}/{}:{}/{}  totalLinks: {}/{}".format(
                posted_link, iCnt, iMax, username, username1, i + 1,
                len(links)))

        try:
            try:
                inappropriate, posted_by_username, posted_link_likes_count, posted_link_comments_count, posted_link_datetime_str, posted_link_location_name, posted_link_image_text, is_video, reason, scope = check_link2(
                    session.browser,
                    posted_link,
                    session.dont_like,
                    session.mandatory_words,
                    session.mandatory_language,
                    session.is_mandatory_character,
                    session.mandatory_character,
                    session.check_character_set,
                    session.ignore_if_contains,
                    session.logger,
                )
            except:
                inappropriate = True

            if not inappropriate:

                sleep(1.5)
                try:
                    posted_by_followers_count, posted_by_following_count = get_relationship_counts(
                        session.browser, posted_by_username, session.logger)
                    #                    posted_by_posts_count = get_number_of_posts(session.browser)
                    posted_by_posts_count = None

                except:
                    # if you can't get follower count, then you're probably out of daily page pulls
                    # Might as well quit!
                    session.logger.warning(
                        "Might be out of daily page pulls.  Closing session.")
                    posted_by_posts_count = None
                    posted_by_followers_count = None
                    posted_by_following_count = None
                    session.end()
                    return False

                session.logger.info(
                    "-Posted on: {}  by: {}  posts: {}  followers: {}  following: {}"
                    .format(posted_link_datetime_str, posted_by_username,
                            posted_by_posts_count, posted_by_followers_count,
                            posted_by_following_count))

                now = datetime.now(timezone.utc)
                last_checked_datetime_str = now.strftime(
                    "%Y-%m-%dT%H:%M:%S.%fZ")

                posted_link_datetime = datetime.strptime(
                    posted_link_datetime_str, "%Y-%m-%dT%H:%M:%S.%fZ")
                last_checked_datetime = datetime.strptime(
                    last_checked_datetime_str, "%Y-%m-%dT%H:%M:%S.%fZ")

                deltatime = (last_checked_datetime - posted_link_datetime)
                last_checked_age_in_hrs = deltatime.seconds / 3600.00

                storeRecord(username1, last_checked_datetime, posted_link,
                            posted_link_datetime, posted_link_location_name,
                            posted_link_likes_count,
                            posted_link_comments_count, posted_by_username,
                            posted_by_posts_count, posted_by_followers_count,
                            posted_by_following_count)

                storeTaggedActivitytoDB(
                    session.logger, username1, last_checked_datetime,
                    posted_link, posted_link_datetime,
                    posted_link_location_name, posted_link_likes_count,
                    posted_link_comments_count, posted_by_username,
                    posted_by_posts_count, posted_by_followers_count,
                    posted_by_following_count)

                sleep(1.0)
        except NoSuchElementException as err:
            session.logger.error("Invalid Page: {}".format(err))

    session.end()
    return True
Beispiel #9
0
def gatherAndStoreLinkData(session, username1, posted_link):
    "Given a posted_link, gather it's info and update the database"
    #    session.logger.info("Processing link: {}".format(posted_link))
    try:
        inappropriate = True
        sleep(1.0)
        try:
            inappropriate, posted_by_username, posted_link_likes_count, posted_link_comments_count, posted_link_datetime_str, posted_link_location_name, posted_link_image_text, is_video, reason, scope = check_link2(
                session.browser,
                posted_link,
                session.dont_like,
                session.mandatory_words,
                session.mandatory_language,
                session.is_mandatory_character,
                session.mandatory_character,
                session.check_character_set,
                session.ignore_if_contains,
                session.logger,
            )
            session.logger.info("-Posted on: {}  by: {} ".format(
                posted_link_datetime_str, posted_by_username))

        except:
            inappropriate = True

        updateSessionActivityToDB(session)

        if not inappropriate:

            sleep(1.0)
            try:
                posted_by_followers_count, posted_by_following_count = get_relationship_counts(
                    session.browser, posted_by_username, session.logger)
                #                    posted_by_posts_count = get_number_of_posts(session.browser)
                posted_by_posts_count = None

            except:
                session.logger.warning(
                    "Might be out of daily page pulls.  Closing session.")
                posted_by_posts_count = None
                posted_by_followers_count = None
                posted_by_following_count = None
                return False

            session.logger.info(
                "-Posts: {}  followers: {}  following: {}".format(
                    posted_by_posts_count, posted_by_followers_count,
                    posted_by_following_count))

            now = datetime.now(timezone.utc)
            last_checked_datetime_str = now.strftime("%Y-%m-%dT%H:%M:%S.%fZ")

            posted_link_datetime = datetime.strptime(posted_link_datetime_str,
                                                     "%Y-%m-%dT%H:%M:%S.%fZ")
            last_checked_datetime = datetime.strptime(
                last_checked_datetime_str, "%Y-%m-%dT%H:%M:%S.%fZ")

            deltatime = (last_checked_datetime - posted_link_datetime)
            #            last_checked_age_in_hrs = deltatime.seconds / 3600.00

            storeRecord(username1, last_checked_datetime, posted_link,
                        posted_link_datetime, posted_link_location_name,
                        posted_link_likes_count, posted_link_comments_count,
                        posted_by_username, posted_by_posts_count,
                        posted_by_followers_count, posted_by_following_count)

            storeTaggedActivitytoDB(
                session.logger, username1, last_checked_datetime, posted_link,
                posted_link_datetime, posted_link_location_name,
                posted_link_likes_count, posted_link_comments_count,
                posted_by_username, posted_by_posts_count,
                posted_by_followers_count, posted_by_following_count)

        if reason == "Unavailable Page":
            # delete link from data base
            deleteLinkFromDB(session, username1, posted_link)

        sleep(1.0)

    except NoSuchElementException as err:
        session.logger.error("Invalid Page: {}".format(err))

    return True
Beispiel #10
0
def nf_interact_with_post(
        self,
        link: str,
        amount: int,
        state: dict,
        user_validated: bool = False,
):
    try:
        self.logger.info("about to check post")
        sleep(1)
        inappropriate, user_name, is_video, image_links, reason, scope = nf_check_post(self, link)
        self.logger.info("about to verify post")
        sleep(1)
        if not inappropriate and self.delimit_liking:
            self.liking_approved = verify_liking(
                self.browser, self.max_likes, self.min_likes, self.logger
            )

        if not inappropriate and self.liking_approved:
            # validate user
            self.logger.info("about to validate user")
            sleep(1)
            if user_validated:
                valid = True
                details = "User already validated"
            else:
                valid, details = nf_validate_user_call(self, user_name, link)

            self.logger.info("Valid User: {}, details: {}".format(valid, details))

            if not valid:
                state["not_valid_users"] += 1
                return True, "not_valid_users", state

            # try to like
            self.logger.info("about to like post")
            sleep(1)
            like_state, msg = like_image(
                self.browser,
                "user_name",
                self.blacklist,
                self.logger,
                self.logfolder,
                state['liked_img'],
            )

            if like_state is True:
                state['liked_img'] += 1
                self.logger.info("Like# [{}/{}]".format(state['liked_img'], amount))
                self.logger.info(link)
                # reset jump counter after a successful like
                self.jumps["consequent"]["likes"] = 0

                checked_img = True
                temp_comments = []

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

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

                # comments
                if (
                        self.do_comment
                        and user_name not in self.dont_include
                        and checked_img
                        and commenting
                ):
                    comments = (self.comments +
                                (self.video_comments if is_video else self.photo_comments))

                    success = process_comments(self, user_name, comments, temp_comments)

                    if success:
                        state['commented'] += 1
                else:
                    self.logger.info("--> Not commented")
                    sleep(1)

                # following
                if (
                        self.do_follow
                        and user_name not in self.dont_include
                        and checked_img
                        and following
                        and not follow_restriction(
                            "read", user_name, self.follow_times, self.logger
                        )
                ):

                    self.logger.info("about to follow user")
                    sleep(1)
                    follow_state, msg = follow_user(
                        self.browser,
                        "post",
                        self.username,
                        user_name,
                        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)

                # interactions (only of user not previously validated to impede recursion)
                if interact and not user_validated:
                    self.logger.info(
                        "--> User gonna be interacted: '{}'".format(
                            user_name
                        )
                    )

                    # disable re-validating user in like_by_users
                    like_by_users(
                        self,
                        [user_name],
                        None,
                        True,
                    )

            elif msg == "already liked":
                state['already_liked'] += 1
                return True, msg, state

            elif msg == "block on likes":
                return False, msg, state

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

            return True, "success", state

        else:
            self.logger.info(
                "--> Image not liked: {}".format(reason.encode("utf-8"))
            )
            state["inap_img"] += 1
            return True, "inap_img", state

    except NoSuchElementException as err:
        self.logger.error("Invalid Page: {}".format(err))
        return False, "Invalid Page", state
Beispiel #11
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
Beispiel #12
0
def like_by_users(
        self,
        usernames: List[str],
        amount: int = None,
        users_validated: bool = False
):
    """Likes some amounts of images for each usernames"""
    if self.aborting:
        return self

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

    for index, username in enumerate(usernames):
        if self.quotient_breach:
            break

        state = {
            'liked_img': 0,
            'already_liked': 0,
            'inap_img': 0,
            'commented': 0,
            'followed': 0,
            'not_valid_users': 0,
        }

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

        if len(usernames) == 1 and users_validated:
            nf_go_from_post_to_profile(self, username)
        else:
            nf_go_to_user_page(self, username)

        if not users_validated:
            validation, details = nf_validate_user_call(self, username)
            if not validation:
                self.logger.info(
                    "--> Not a valid user: {}".format(details)
                )
                state["not_valid_users"] += 1
                continue

        try_again = 0
        sc_rolled = 0
        scroll_nap = 1.5
        already_interacted_links = []
        try:
            while state['liked_img'] in range(0, amount):

                if self.jumps["consequent"]["likes"] >= self.jumps["limit"]["likes"]:
                    self.logger.warning(
                        "--> Like quotient reached its peak!\t~leaving "
                        "Like-By-Users activity\n"
                    )
                    self.quotient_breach = True
                    # reset jump counter after a breach report
                    self.jumps["consequent"]["likes"] = 0
                    break

                if sc_rolled > 100:
                    try_again += 1
                    if try_again > 2:  # you can try again as much as you want by changing this number
                        self.logger.info(
                            "'{}' user POSSIBLY has less valid images than "
                            "desired:{} found:{}...".format(
                                username, amount, len(already_interacted_links))
                        )
                        break
                    self.logger.info(
                        "Scrolled too much! ~ sleeping 10 minutes")
                    sleep(600)
                    sc_rolled = 0

                main_elem = self.browser.find_element_by_tag_name("main")
                # feed = main_elem.find_elements_by_xpath('//div[@class=" _2z6nI"]')
                posts = nf_get_all_posts_on_element(main_elem)

                # Interact with links instead of just storing them
                for post in posts:
                    link = post.get_attribute("href")
                    if link not in already_interacted_links:
                        self.logger.info("about to scroll to post")
                        sleep(1)
                        nf_scroll_into_view(self, post)
                        self.logger.info("about to click to post")
                        sleep(1)
                        nf_click_center_of_element(self, post)

                        success, msg, state = nf_interact_with_post(
                            self,
                            link,
                            amount,
                            state,
                            users_validated,
                        )

                        self.logger.info(
                            "Returned from liking, should still be in post page")
                        sleep(5)
                        nf_find_and_press_back(
                            self,
                            "https://www.instagram.com/{}/".format(username)
                        )

                        already_interacted_links.append(link)

                        if success:
                            break
                        if msg == "block on likes":
                            # TODO deal with block on likes
                            break
                else:
                    # For loop ended means all posts in screen has been interacted with
                    # 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("Username [{}/{}]".format(index + 1, len(usernames)))
        self.logger.info("--> {} ended".format(username.encode("utf-8")))
        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
Beispiel #13
0
def like_by_tags(
        self,
        tags: List[str] = None,
        amount: int = 50,
        skip_top_posts: bool = True,
        use_smart_hashtags: bool = False,
        use_smart_location_hashtags: bool = False,
):
    """Likes (default) 50 images per given tag"""
    if self.aborting:
        return self

    # if smart hashtag is enabled
    if use_smart_hashtags is True and self.smart_hashtags != []:
        self.logger.info("Using smart hashtags")
        tags = self.smart_hashtags
    elif use_smart_location_hashtags is True and self.smart_location_hashtags != []:
        self.logger.info("Using smart location hashtags")
        tags = self.smart_location_hashtags

    # deletes white spaces in tags
    tags = [tag.strip() for tag in tags]
    tags = tags or []
    self.quotient_breach = False

    for index, tag in enumerate(tags):
        if self.quotient_breach:
            break

        state = {
            'liked_img': 0,
            'already_liked': 0,
            'inap_img': 0,
            'commented': 0,
            'followed': 0,
            'not_valid_users': 0,
        }

        self.logger.info("Tag [{}/{}]".format(index + 1, len(tags)))
        self.logger.info("--> {}".format(tag.encode("utf-8")))

        tag = tag[1:] if tag[:1] == "#" else tag

        nf_go_to_tag_page(self, tag)

        # get amount of post with this hashtag
        try:
            possible_posts = self.browser.execute_script(
                "return window._sharedData.entry_data."
                "TagPage[0].graphql.hashtag.edge_hashtag_to_media.count"
            )
        except WebDriverException:
            try:
                possible_posts = self.browser.find_element_by_xpath(
                    read_xpath("get_links_for_tag", "possible_post")
                ).text
                if possible_posts:
                    possible_posts = format_number(possible_posts)
                else:
                    self.logger.info(
                        "Failed to get the amount of possible posts in '{}' tag  "
                        "~empty string".format(tag)
                    )
                    possible_posts = None

            except NoSuchElementException:
                self.logger.info(
                    "Failed to get the amount of possible posts in {} tag".format(tag)
                )
                possible_posts = None

        self.logger.info(
            "desired amount: {}  |  top posts [{}] |  possible posts: "
            "{}".format(
                amount,
                "enabled" if not skip_top_posts else "disabled",
                possible_posts,
            )
        )

        if possible_posts is not None:
            amount = possible_posts if amount > possible_posts else amount
        # sometimes pages do not have the correct amount of posts as it is
        # written there, it may be cos of some posts is deleted but still keeps
        # counted for the tag

        sleep(1)

        try_again = 0
        sc_rolled = 0
        scroll_nap = 1.5
        already_interacted_links = []
        try:
            while state['liked_img'] in range(0, amount):
                if sc_rolled > 100:
                    try_again += 1
                    if try_again > 2:
                        self.logger.info(
                            "'{}' tag POSSIBLY has less images than "
                            "desired:{} found:{}...".format(
                                tag,
                                amount,
                                len(already_interacted_links)
                            )
                        )
                        break
                    self.logger.info("Scrolled too much! ~ sleeping 10 minutes")
                    sleep(600)
                    sc_rolled = 0

                main_elem = self.browser.find_element_by_tag_name("main")
                posts = nf_get_all_posts_on_element(main_elem)

                # Interact with links instead of just storing them
                for post in posts:
                    link = post.get_attribute("href")
                    if link not in already_interacted_links:

                        self.logger.info("about to scroll to post")
                        sleep(1)
                        nf_scroll_into_view(self, post)
                        self.logger.info("about to click to post")
                        sleep(1)
                        nf_click_center_of_element(self, post)

                        success, msg, state = nf_interact_with_post(
                            self,
                            link,
                            amount,
                            state,
                        )

                        self.logger.info("Returned from liking, should still be in post page")
                        sleep(2)
                        nf_find_and_press_back(self, "https://www.instagram.com/explore/tags/{}/".format(tag))

                        already_interacted_links.append(link)

                        if success:
                            break
                        if msg == "block on likes":
                            # TODO deal with block on likes
                            break
                else:
                    # For loop ended means all posts in screen has been interacted with
                    # 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(2)

        self.logger.info("Tag [{}/{}]".format(index + 1, len(tags)))
        self.logger.info("--> {} ended".format(tag.encode("utf-8")))
        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
def check_browser(browser, logfolder, logger, proxy_address):
    # set initial state to offline
    update_activity(
        browser,
        action=None,
        state="trying to connect",
        logfolder=logfolder,
        logger=logger,
    )

    # check connection status
    try:
        logger.info("-- Connection Checklist [1/3] (Internet Connection Status)")
        browser.get("view-source:https://api.myip.com/")
        pre = browser.find_element_by_tag_name("pre").text
        current_ip_info = json.loads(pre)
        if (
            proxy_address is not None
            and socket.gethostbyname(proxy_address) != current_ip_info["ip"]
        ):
            logger.warn("- Proxy is set, but it's not working properly")
            logger.warn(
                '- Expected Proxy IP is "{}", and the current IP is "{}"'.format(
                    proxy_address, current_ip_info["ip"]
                )
            )
            # logger.warn("- Try again or disable the Proxy Address on your setup")
            # logger.warn("- Aborting connection...")
            # return False
        else:
            logger.info("- Internet Connection Status: ok")
            logger.info(
                '- Current IP is "{}" and it\'s from "{}/{}"'.format(
                    current_ip_info["ip"],
                    current_ip_info["country"],
                    current_ip_info["cc"],
                )
            )
            update_activity(
                browser,
                action=None,
                state="Internet connection is ok",
                logfolder=logfolder,
                logger=logger,
            )
    except Exception:
        logger.warn("- Internet Connection Status: error")
        update_activity(
            browser,
            action=None,
            state="There is an issue with the internet connection",
            logfolder=logfolder,
            logger=logger,
        )
        return False

    # check Instagram.com status
    try:
        logger.info("-- Connection Checklist [2/3] (Instagram Server Status)")
        browser.get("https://isitdownorjust.me/instagram-com/")
        sleep(2)
        # collect isitdownorjust.me website information
        website_status = browser.find_element_by_xpath(
            read_xpath(login_user.__name__, "website_status")
        )
        response_time = browser.find_element_by_xpath(
            read_xpath(login_user.__name__, "response_time")
        )
        response_code = browser.find_element_by_xpath(
            read_xpath(login_user.__name__, "response_code")
        )

        logger.info("- Instagram WebSite Status: {} ".format(website_status.text))
        logger.info("- Instagram Response Time: {} ".format(response_time.text))
        logger.info("- Instagram Reponse Code: {}".format(response_code.text))
        logger.info("- Instagram Server Status: ok")
        update_activity(
            browser,
            action=None,
            state="Instagram servers are running correctly",
            logfolder=logfolder,
            logger=logger,
        )
    except Exception:
        logger.warn("- Instagram Server Status: error")
        update_activity(
            browser,
            action=None,
            state="Instagram server is down",
            logfolder=logfolder,
            logger=logger,
        )
        return False

    # check if hide-selenium extension is running
    logger.info("-- Connection Checklist [3/3] (Hide Selenium Extension)")
    webdriver = browser.execute_script("return window.navigator.webdriver")
    logger.info("- window.navigator.webdriver response: {}".format(webdriver))
    if webdriver:
        logger.warn("- Hide Selenium Extension: error")
    else:
        logger.info("- Hide Selenium Extension: ok")

    # everything is ok, then continue(True)
    return True