Beispiel #1
0
 def wrapper(*args, **kwargs):
     session_state = sessions[-1]
     try:
         func(*args, **kwargs)
     except KeyboardInterrupt:
         close_instagram(device_id)
         logger.info(
             f"-------- FINISH: {datetime.now().time()} --------",
             extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
         )
         print_full_report(sessions)
         sessions.persist(directory=session_state.my_username)
         sys.exit(0)
     except (DeviceFacade.JsonRpcError, IndexError, HTTPException,
             timeout):
         logger.error(traceback.format_exc())
         save_crash(device)
         logger.info("No idea what it was. Let's try again.")
         # Hack for the case when IGTV was accidentally opened
         close_instagram(device_id)
         random_sleep()
         open_instagram(device_id)
         TabBarView(device).navigateToProfile()
     except LanguageNotEnglishException:
         logger.info(
             "Language was changed. We'll have to start from the beginning."
         )
         TabBarView(device).navigateToProfile()
     except Exception as e:
         save_crash(device)
         close_instagram(device_id)
         print_full_report(sessions)
         sessions.persist(directory=session_state.my_username)
         raise e
    def open_user_followers(self, device, username):
        if username is None:
            logger.info("Open your followers")
            profile_view = TabBarView(device).navigateToProfile()
            profile_view.navigateToFollowers()
        else:
            search_view = TabBarView(device).navigateToSearch()
            profile_view = search_view.navigateToUsername(username)
            random_sleep()
            if not profile_view:
                return False

            logger.info(f"Open @{username} followers")
            profile_view.navigateToFollowers()

        return True
    def handle_hashtag(
        self,
        device,
        hashtag,
        likes_count,
        follow_percentage,
        follow_limit,
        storage,
        profile_filter,
        on_like,
        on_interaction,
    ):
        interaction = partial(
            interact_with_user,
            my_username=self.session_state.my_username,
            likes_count=likes_count,
            follow_percentage=follow_percentage,
            on_like=on_like,
            profile_filter=profile_filter,
        )

        is_follow_limit_reached = partial(
            is_follow_limit_reached_for_source,
            follow_limit=follow_limit,
            source=hashtag,
            session_state=self.session_state,
        )
        search_view = TabBarView(device).navigateToSearch()
        random_sleep()
        if not search_view.navigateToHashtag(hashtag):
            return

        logger.info("Opening the first result")

        first_result_view = device.find(
            resourceId="com.instagram.android:id/recycler_view",
            className="androidx.recyclerview.widget.RecyclerView",
        )

        first_result_view.child(index=3).click()
        random_sleep()

        posts_list_view = device.find(
            resourceId="android:id/list",
            className="androidx.recyclerview.widget.RecyclerView",
        )
        posts_end_detector = ScrollEndDetector(repeats_to_end=2)

        while True:
            if not self.open_likers(device):
                logger.info(
                    "No likes, let's scroll down.", extra={"color": f"{Fore.GREEN}"}
                )
                posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
                continue

            logger.info("List of likers is opened.")
            posts_end_detector.notify_new_page()
            random_sleep()
            likes_list_view = device.find(
                resourceId="android:id/list", className="android.widget.ListView"
            )
            prev_screen_iterated_likers = []
            while True:
                logger.info("Iterate over visible likers.")
                screen_iterated_likers = []

                try:
                    for item in device.find(
                        resourceId="com.instagram.android:id/row_user_container_base",
                        className="android.widget.LinearLayout",
                    ):
                        username_view = item.child(
                            resourceId="com.instagram.android:id/row_user_primary_name",
                            className="android.widget.TextView",
                        )
                        if not username_view.exists(quick=True):
                            logger.info(
                                "Next item not found: probably reached end of the screen.",
                                extra={"color": f"{Fore.GREEN}"},
                            )
                            break

                        username = username_view.get_text()
                        screen_iterated_likers.append(username)
                        posts_end_detector.notify_username_iterated(username)

                        if storage.is_user_in_blacklist(username):
                            logger.info(f"@{username} is in blacklist. Skip.")
                            continue
                        elif storage.check_user_was_interacted(username):
                            logger.info(f"@{username}: already interacted. Skip.")
                            continue
                        else:
                            logger.info(f"@{username}: interact")
                            username_view.click()

                        can_follow = (
                            not is_follow_limit_reached()
                            and storage.get_following_status(username)
                            == FollowingStatus.NONE
                        )

                        interaction_succeed, followed = interaction(
                            device, username=username, can_follow=can_follow
                        )
                        storage.add_interacted_user(username, followed=followed)
                        can_continue = on_interaction(
                            succeed=interaction_succeed, followed=followed
                        )
                        if not can_continue:
                            return

                        logger.info("Back to likers list")
                        device.back()
                        random_sleep()
                except IndexError:
                    logger.info(
                        "Cannot get next item: probably reached end of the screen.",
                        extra={"color": f"{Fore.GREEN}"},
                    )

                if screen_iterated_likers == prev_screen_iterated_likers:
                    logger.info(
                        "Iterated exactly the same likers twice, finish.",
                        extra={"color": f"{Fore.GREEN}"},
                    )
                    logger.info(f"Back to #{hashtag}")
                    device.back()
                    break

                prev_screen_iterated_likers.clear()
                prev_screen_iterated_likers += screen_iterated_likers

                logger.info("Need to scroll now", extra={"color": f"{Fore.GREEN}"})
                likes_list_view.scroll(DeviceFacade.Direction.BOTTOM)

            if posts_end_detector.is_the_end():
                break
            else:
                posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
Beispiel #4
0
    def handle_hashtag(
        self,
        device,
        hashtag,
        likes_count,
        stories_count,
        stories_percentage,
        follow_percentage,
        follow_limit,
        current_job,
        storage,
        profile_filter,
        on_like,
        on_watch,
        on_interaction,
    ):
        interaction = partial(
            interact_with_user,
            my_username=self.session_state.my_username,
            likes_count=likes_count,
            stories_count=stories_count,
            stories_percentage=stories_percentage,
            follow_percentage=follow_percentage,
            on_like=on_like,
            on_watch=on_watch,
            profile_filter=profile_filter,
            args=self.args,
            session_state=self.session_state,
            current_mode=self.current_mode,
        )

        is_follow_limit_reached = partial(
            is_follow_limit_reached_for_source,
            follow_limit=follow_limit,
            source=hashtag,
            session_state=self.session_state,
        )
        search_view = TabBarView(device).navigateToSearch()
        if not search_view.navigateToHashtag(hashtag):
            return

        if current_job == "hashtag-likers-recent":
            logger.info("Switching to Recent tab")
            HashTagView(device)._getRecentTab().click()
            random_sleep(5, 10)
            if HashTagView(device)._check_if_no_posts():
                HashTagView(device)._reload_page()
                random_sleep(4, 8)

        logger.info("Opening the first result")

        result_view = HashTagView(device)._getRecyclerView()
        HashTagView(device)._getFistImageView(result_view).click()
        random_sleep()

        skipped_list_limit = get_value(self.args.skipped_list_limit, None, 15)
        skipped_fling_limit = get_value(self.args.fling_when_skipped, None, 0)

        posts_end_detector = ScrollEndDetector(
            repeats_to_end=2,
            skipped_list_limit=skipped_list_limit,
            skipped_fling_limit=skipped_fling_limit,
        )

        post_description = ""
        nr_same_post = 0
        nr_same_posts_max = 3
        while True:
            likers_container_exists = PostsViewList(device)._find_likers_container()
            has_one_liker_or_none = PostsViewList(
                device
            )._check_if_only_one_liker_or_none()

            flag, post_description = PostsViewList(device)._check_if_last_post(
                post_description
            )
            if flag:
                nr_same_post += 1
                logger.info(
                    f"Warning: {nr_same_post}/{nr_same_posts_max} repeated posts."
                )
                if nr_same_post == nr_same_posts_max:
                    logger.info(
                        f"Scrolled through {nr_same_posts_max} posts with same description and author. Finish."
                    )
                    break
            else:
                nr_same_post = 0

            if likers_container_exists and not has_one_liker_or_none:
                PostsViewList(device).open_likers_container()
            else:
                PostsViewList(device).swipe_to_fit_posts(SwipeTo.NEXT_POST)
                continue

            posts_end_detector.notify_new_page()
            random_sleep()

            likes_list_view = OpenedPostView(device)._getListViewLikers()
            prev_screen_iterated_likers = []
            while True:
                logger.info("Iterate over visible likers.")
                screen_iterated_likers = []
                opened = False

                try:
                    for item in OpenedPostView(device)._getUserCountainer():
                        username_view = OpenedPostView(device)._getUserName(item)
                        if not username_view.exists(quick=True):
                            logger.info(
                                "Next item not found: probably reached end of the screen.",
                                extra={"color": f"{Fore.GREEN}"},
                            )
                            break

                        username = username_view.get_text()
                        profile_interact = profile_filter.check_profile_from_list(
                            device, item, username
                        )
                        screen_iterated_likers.append(username)
                        posts_end_detector.notify_username_iterated(username)
                        if not profile_interact:
                            continue
                        elif storage.is_user_in_blacklist(username):
                            logger.info(f"@{username} is in blacklist. Skip.")
                            continue
                        elif storage.check_user_was_interacted(username):
                            logger.info(f"@{username}: already interacted. Skip.")
                            continue
                        else:
                            logger.info(f"@{username}: interact")
                            username_view.click()

                        can_follow = not is_follow_limit_reached() and (
                            storage.get_following_status(username)
                            == FollowingStatus.NONE
                            or storage.get_following_status(username)
                            == FollowingStatus.NOT_IN_LIST
                        )

                        interaction_succeed, followed = interaction(
                            device, username=username, can_follow=can_follow
                        )
                        storage.add_interacted_user(username, followed=followed)
                        opened = True
                        can_continue = on_interaction(
                            succeed=interaction_succeed, followed=followed
                        )
                        if not can_continue:
                            return

                        logger.info("Back to likers list.")
                        device.back()
                        random_sleep()
                except IndexError:
                    logger.info(
                        "Cannot get next item: probably reached end of the screen.",
                        extra={"color": f"{Fore.GREEN}"},
                    )
                    break

                go_back = False
                if not opened:
                    logger.info(
                        "All likers skipped.",
                        extra={"color": f"{Fore.GREEN}"},
                    )
                    posts_end_detector.notify_skipped_all()
                    if posts_end_detector.is_skipped_limit_reached():
                        posts_end_detector.reset_skipped_all()
                        device.back()
                        PostsViewList(device).swipe_to_fit_posts(False)
                        break
                if screen_iterated_likers == prev_screen_iterated_likers:
                    logger.info(
                        "Iterated exactly the same likers twice.",
                        extra={"color": f"{Fore.GREEN}"},
                    )
                    go_back = True
                if go_back:
                    prev_screen_iterated_likers.clear()
                    prev_screen_iterated_likers += screen_iterated_likers
                    logger.info(
                        f"Back to {hashtag}'s posts list.",
                        extra={"color": f"{Fore.GREEN}"},
                    )
                    device.back()
                    logger.info("Going to the next post.")
                    PostsViewList(device).swipe_to_fit_posts(SwipeTo.NEXT_POST)
                    break
                if posts_end_detector.is_fling_limit_reached():
                    prev_screen_iterated_likers.clear()
                    prev_screen_iterated_likers += screen_iterated_likers
                    logger.info(
                        "Reached fling limit. Fling to see other likers",
                        extra={"color": f"{Fore.GREEN}"},
                    )
                    likes_list_view.fling(DeviceFacade.Direction.BOTTOM)
                else:
                    prev_screen_iterated_likers.clear()
                    prev_screen_iterated_likers += screen_iterated_likers
                    logger.info(
                        "Scroll to see other likers",
                        extra={"color": f"{Fore.GREEN}"},
                    )
                    likes_list_view.scroll(DeviceFacade.Direction.BOTTOM)

                if posts_end_detector.is_the_end():
                    break
Beispiel #5
0
        def wrapper(*args, **kwargs):
            session_state = sessions[-1]
            try:
                func(*args, **kwargs)
            except KeyboardInterrupt:
                try:
                    # Catch Ctrl-C and ask if user wants to pause execution
                    logger.info(
                        "CTRL-C detected . . .",
                        extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
                    )
                    logger.info(
                        f"-------- PAUSED: {datetime.now().time()} --------",
                        extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
                    )
                    logger.info(
                        "NOTE: This is a rudimentary pause. It will restart the action, while retaining session data.",
                        extra={"color": Style.BRIGHT},
                    )
                    logger.info(
                        "Press RETURN to resume or CTRL-C again to Quit: ",
                        extra={"color": Style.BRIGHT},
                    )

                    input("")

                    logger.info(
                        f"-------- RESUMING: {datetime.now().time()} --------",
                        extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
                    )
                    TabBarView(device).navigateToProfile()
                except KeyboardInterrupt:
                    close_instagram(device, screen_record)
                    logger.info(
                        f"-------- FINISH: {datetime.now().time()} --------",
                        extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
                    )
                    print_full_report(sessions)
                    sessions.persist(directory=session_state.my_username)
                    sys.exit(0)

            except (
                    DeviceFacade.JsonRpcError,
                    IndexError,
                    HTTPException,
                    timeout,
                    UiObjectNotFoundErrorv2,
            ):
                logger.error(traceback.format_exc())
                save_crash(device)
                logger.info("No idea what it was. Let's try again.")
                # Hack for the case when IGTV was accidentally opened
                close_instagram(device, screen_record)
                random_sleep()
                open_instagram(device, screen_record)
                TabBarView(device).navigateToProfile()
            except LanguageNotEnglishException:
                logger.info(
                    "Language was changed. We'll have to start from the beginning."
                )
                TabBarView(device).navigateToProfile()
            except Exception as e:
                logger.error(traceback.format_exc())
                save_crash(device)
                close_instagram(device, screen_record)
                print_full_report(sessions)
                sessions.persist(directory=session_state.my_username)
                raise e
Beispiel #6
0
def run():
    global device_id
    global first_run
    loaded = load_plugins()
    args = get_args()
    enabled = []
    if not args:
        return
    dargs = vars(args)

    for k in loaded:
        if dargs[k.replace("-", "_")[2:]] != None:
            if k == "--interact":
                logger.warn(
                    'Using legacy argument "--interact". Please switch to new arguments as this will be deprecated in the near future.'
                )
                if "#" in args.interact[0]:
                    enabled.append("--hashtag-likers")
                    args.hashtag_likers = args.interact
                else:
                    enabled.append("--blogger-followers")
                    args.blogger_followers = args.interact
            else:
                enabled.append(k)
    enabled = list(dict.fromkeys(enabled))

    if len(enabled) < 1:
        logger.error("You have to specify one of the actions: " + ", ".join(loaded))
        return
    if len(enabled) > 1:
        logger.error(
            "Running GramAddict with two or more actions is not supported yet."
        )
        return

    device_id = args.device
    if not check_adb_connection(is_device_id_provided=(device_id is not None)):
        return
    logger.info("Instagram version: " + get_instagram_version(device_id))
    device = create_device(device_id)

    if device is None:
        return

    while True:
        session_state = SessionState()
        session_state.args = args.__dict__
        sessions.append(session_state)

        logger.info(
            "-------- START: " + str(session_state.startTime) + " --------",
            extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
        )

        if args.screen_sleep:
            screen_sleep(device_id, "on")  # Turn on the device screen

        open_instagram(device_id)

        try:
            profileView = TabBarView(device).navigateToProfile()
            (
                session_state.my_username,
                session_state.my_followers_count,
                session_state.my_following_count,
            ) = profileView.getProfileInfo()
        except Exception as e:
            logger.error(f"Exception: {e}")
            save_crash(device)
            switch_to_english(device)
            # Try again on the correct language
            profileView = TabBarView(device).navigateToProfile()
            (
                session_state.my_username,
                session_state.my_followers_count,
                session_state.my_following_count,
            ) = profileView.getProfileInfo()

        if (
            session_state.my_username == None
            or session_state.my_followers_count == None
            or session_state.my_following_count == None
        ):
            logger.critical(
                "Could not get one of the following from your profile: username, # of followers, # of followings. This is typically due to a soft ban. Review the crash screenshot to see if this is the case."
            )
            logger.critical(
                f"Username: {session_state.my_username}, Followers: {session_state.my_followers_count}, Following: {session_state.my_following_count}"
            )
            save_crash(device)
            exit(1)
        if first_run:
            try:
                update_log_file_name(session_state.my_username)
            except Exception as e:
                logger.error(
                    f"Failed to update log file name. Will continue anyway. {e}"
                )
                save_crash(device)

        report_string = f"Hello, @{session_state.my_username}! You have {session_state.my_followers_count} followers and {session_state.my_following_count} followings so far."

        logger.info(report_string, extra={"color": f"{Style.BRIGHT}"})

        storage = Storage(session_state.my_username)

        loaded[enabled[0]].run(device, device_id, args, enabled, storage, sessions)

        close_instagram(device_id)
        session_state.finishTime = datetime.now()

        if args.screen_sleep:
            screen_sleep(device_id, "off")  # Turn off the device screen

        logger.info(
            "-------- FINISH: " + str(session_state.finishTime) + " --------",
            extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
        )

        if args.repeat:
            print_full_report(sessions)
            repeat = get_value(args.repeat, "Sleep for {} minutes", 180)
            try:
                sleep(60 * repeat)
            except KeyboardInterrupt:
                print_full_report(sessions)
                sessions.persist(directory=session_state.my_username)
                sys.exit(0)
        else:
            break

        first_run = False

    print_full_report(sessions)
    sessions.persist(directory=session_state.my_username)
Beispiel #7
0
def run():
    # Some plugins need config values without being passed
    # through. Because we do a weird config/argparse hybrid,
    # we need to load the configs in a weird way
    load_filter(configs)
    load_interaction(configs)
    load_utils(configs)
    load_views(configs)

    if not configs.args or not check_adb_connection():
        return

    if len(configs.enabled) < 1:
        logger.error("You have to specify one of the actions: " +
                     ", ".join(configs.actions))
        return

    logger.info("Instagram version: " + get_instagram_version())
    device = create_device(configs.device_id, configs.args.uia_version)

    if device is None:
        return

    while True:
        session_state = SessionState(configs)
        sessions.append(session_state)

        device.wake_up()

        logger.info(
            "-------- START: " + str(session_state.startTime) + " --------",
            extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
        )

        if not device.get_info()["screenOn"]:
            device.press_power()
        if device.is_screen_locked():
            device.unlock()
            if device.is_screen_locked():
                logger.error(
                    "Can't unlock your screen. There may be a passcode on it. If you would like your screen to be turned on and unlocked automatically, please remove the passcode."
                )
                exit(0)

        logger.info("Device screen on and unlocked.")

        open_instagram(device, configs.args.screen_record)

        try:
            profileView = TabBarView(device).navigateToProfile()
            random_sleep()
            if configs.args.username is not None:
                success = AccountView(device).changeToUsername(
                    configs.args.username)
                if not success:
                    logger.error(
                        f"Not able to change to {configs.args.username}, abort!"
                    )
                    device.back()
                    break

            (
                session_state.my_username,
                session_state.my_followers_count,
                session_state.my_following_count,
            ) = profileView.getProfileInfo()
        except Exception as e:
            logger.error(f"Exception: {e}")
            save_crash(device)
            switch_to_english(device)
            # Try again on the correct language
            profileView = TabBarView(device).navigateToProfile()
            random_sleep()
            (
                session_state.my_username,
                session_state.my_followers_count,
                session_state.my_following_count,
            ) = profileView.getProfileInfo()

        if (session_state.my_username is None
                or session_state.my_followers_count is None
                or session_state.my_following_count is None):
            logger.critical(
                "Could not get one of the following from your profile: username, # of followers, # of followings. This is typically due to a soft ban. Review the crash screenshot to see if this is the case."
            )
            logger.critical(
                f"Username: {session_state.my_username}, Followers: {session_state.my_followers_count}, Following: {session_state.my_following_count}"
            )
            save_crash(device)
            exit(1)

        if not is_log_file_updated():
            try:
                update_log_file_name(session_state.my_username)
            except Exception as e:
                logger.error(
                    f"Failed to update log file name. Will continue anyway. {e}"
                )
                save_crash(device)

        report_string = f"Hello, @{session_state.my_username}! You have {session_state.my_followers_count} followers and {session_state.my_following_count} followings so far."

        logger.info(report_string, extra={"color": f"{Style.BRIGHT}"})

        storage = Storage(session_state.my_username)
        for plugin in configs.enabled:
            if not session_state.check_limit(
                    configs.args, limit_type=session_state.Limit.ALL,
                    output=False):
                logger.info(f"Current job: {plugin}",
                            extra={"color": f"{Fore.BLUE}"})
                if ProfileView(
                        device).getUsername() != session_state.my_username:
                    logger.debug("Not in your main profile.")
                    TabBarView(device).navigateToProfile()
                configs.actions[plugin].run(device, configs, storage, sessions,
                                            plugin)

            else:
                logger.info(
                    "Successful or Total Interactions limit reached. Ending session."
                )
                break

        close_instagram(device, configs.args.screen_record)
        session_state.finishTime = datetime.now()

        if configs.args.screen_sleep:
            device.screen_off()
            logger.info("Screen turned off for sleeping time")

        logger.info(
            "-------- FINISH: " + str(session_state.finishTime) + " --------",
            extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
        )

        if configs.args.repeat:
            print_full_report(sessions)
            repeat = get_value(configs.args.repeat, "Sleep for {} minutes",
                               180)
            try:
                sleep(60 * repeat)
            except KeyboardInterrupt:
                print_full_report(sessions)
                sessions.persist(directory=session_state.my_username)
                exit(0)
        else:
            break

    print_full_report(sessions)
    sessions.persist(directory=session_state.my_username)
Beispiel #8
0
    def handle_hashtag(
        self,
        device,
        hashtag,
        likes_count,
        stories_count,
        stories_percentage,
        follow_percentage,
        follow_limit,
        interact_percentage,
        current_job,
        storage,
        profile_filter,
        on_like,
        on_watch,
        on_interaction,
    ):
        interaction = partial(
            interact_with_user,
            my_username=self.session_state.my_username,
            likes_count=likes_count,
            stories_count=stories_count,
            stories_percentage=stories_percentage,
            follow_percentage=follow_percentage,
            on_like=on_like,
            on_watch=on_watch,
            profile_filter=profile_filter,
            args=self.args,
            session_state=self.session_state,
            current_mode=self.current_mode,
        )

        is_follow_limit_reached = partial(
            is_follow_limit_reached_for_source,
            follow_limit=follow_limit,
            source=hashtag,
            session_state=self.session_state,
        )
        search_view = TabBarView(device).navigateToSearch()
        if not search_view.navigateToHashtag(hashtag):
            return
        if current_job == "hashtag-posts-recent":
            logger.info("Switching to Recent tab")
            HashTagView(device)._getRecentTab().click()
            random_sleep(5, 10)
        if HashTagView(device)._check_if_no_posts():
            UniversalActions(device)._reload_page()
            random_sleep(4, 8)

        logger.info("Opening the first result")

        result_view = HashTagView(device)._getRecyclerView()
        HashTagView(device)._getFistImageView(result_view).click()
        random_sleep()

        def interact():
            can_follow = not is_follow_limit_reached() and (
                storage.get_following_status(username) == FollowingStatus.NONE
                or storage.get_following_status(username) == FollowingStatus.NOT_IN_LIST
            )

            interaction_succeed, followed = interaction(
                device, username=username, can_follow=can_follow
            )
            storage.add_interacted_user(username, followed=followed)
            can_continue = on_interaction(
                succeed=interaction_succeed, followed=followed
            )
            if not can_continue:
                return False
            else:
                return True

        def random_choice():
            from random import randint

            random_number = randint(1, 100)
            if interact_percentage > random_number:
                return True
            else:
                return False

        post_description = ""
        nr_same_post = 0
        nr_same_posts_max = 3
        while True:
            flag, post_description = PostsViewList(device)._check_if_last_post(
                post_description
            )
            if flag:
                nr_same_post += 1
                logger.info(
                    f"Warning: {nr_same_post}/{nr_same_posts_max} repeated posts."
                )
                if nr_same_post == nr_same_posts_max:
                    logger.info(
                        f"Scrolled through {nr_same_posts_max} posts with same description and author. Finish."
                    )
                    break
            else:
                nr_same_post = 0
            if random_choice():
                username = PostsViewList(device)._post_owner(Owner.GET_NAME)[:-3]
                if storage.is_user_in_blacklist(username):
                    logger.info(f"@{username} is in blacklist. Skip.")
                elif storage.check_user_was_interacted(username):
                    logger.info(f"@{username}: already interacted. Skip.")
                else:
                    logger.info(f"@{username}: interact")
                    PostsViewList(device)._like_in_post_view(LikeMode.DOUBLE_CLICK)
                    detect_block(device)
                    if not PostsViewList(device)._check_if_liked():
                        PostsViewList(device)._like_in_post_view(LikeMode.SINGLE_CLICK)
                        detect_block(device)
                    random_sleep(1, 2)
                    if PostsViewList(device)._post_owner(Owner.OPEN):
                        if not interact():
                            break
                        device.back()

            PostsViewList(device).swipe_to_fit_posts(SwipeTo.HALF_PHOTO)
            random_sleep(0, 1)
            PostsViewList(device).swipe_to_fit_posts(SwipeTo.NEXT_POST)
            random_sleep()
            continue
Beispiel #9
0
def run():
    global device_id
    loaded = load_plugins()
    args = get_args()
    enabled = []
    if not args:
        return
    dargs = vars(args)

    for item in sys.argv[1:]:
        if item in loaded:
            if item != "--interact" and item != "--hashtag-likers":
                enabled.append(item)

    for k in loaded:
        if dargs[k.replace("-", "_")[2:]] != None:
            if k == "--interact":
                logger.warn(
                    'Using legacy argument "--interact". Please switch to new arguments as this will be deprecated in the near future.'
                )
                for source in args.interact:
                    if "@" in source:
                        enabled.append("--blogger-followers")
                        if type(args.blogger_followers) != list:
                            args.blogger_followers = [source]
                        else:
                            args.blogger_followers.append(source)
                    else:
                        enabled.append("--hashtag-likers-top")
                        if type(args.hashtag_likers_top) != list:
                            args.hashtag_likers_top = [source]
                        else:
                            args.hashtag_likers_top.append(source)
            elif k == "--hashtag-likers":
                logger.warn(
                    'Using legacy argument "--hashtag-likers". Please switch to new arguments as this will be deprecated in the near future.'
                )
                for source in args.hashtag_likers:
                    enabled.append("--hashtag-likers-top")
                    if type(args.hashtag_likers_top) != list:
                        args.hashtag_likers_top = [source]
                    else:
                        args.hashtag_likers_top.append(source)

    enabled = list(dict.fromkeys(enabled))

    if len(enabled) < 1:
        logger.error("You have to specify one of the actions: " +
                     ", ".join(loaded))
        return

    device_id = args.device
    if not check_adb_connection(is_device_id_provided=(device_id is not None)):
        return
    logger.info("Instagram version: " + get_instagram_version(device_id))
    device = create_device(device_id)

    if device is None:
        return

    while True:
        session_state = SessionState()
        session_state.args = args.__dict__
        sessions.append(session_state)

        device.wake_up()

        logger.info(
            "-------- START: " + str(session_state.startTime) + " --------",
            extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
        )

        if not DeviceFacade(device_id).get_info()["screenOn"]:
            DeviceFacade(device_id).press_power()
        if DeviceFacade(device_id).is_screen_locked():
            DeviceFacade(device_id).unlock()
            if DeviceFacade(device_id).is_screen_locked():
                logger.error(
                    "Can't unlock your screen. There may be a passcode on it. If you would like your screen to be turned on and unlocked automatically, please remove the passcode."
                )
                sys.exit()

        logger.info("Device screen on and unlocked.")

        open_instagram(device_id)

        try:
            profileView = TabBarView(device).navigateToProfile()
            random_sleep()
            (
                session_state.my_username,
                session_state.my_followers_count,
                session_state.my_following_count,
            ) = profileView.getProfileInfo()
        except Exception as e:
            logger.error(f"Exception: {e}")
            save_crash(device)
            switch_to_english(device)
            # Try again on the correct language
            profileView = TabBarView(device).navigateToProfile()
            random_sleep()
            (
                session_state.my_username,
                session_state.my_followers_count,
                session_state.my_following_count,
            ) = profileView.getProfileInfo()

        if (session_state.my_username == None
                or session_state.my_followers_count == None
                or session_state.my_following_count == None):
            logger.critical(
                "Could not get one of the following from your profile: username, # of followers, # of followings. This is typically due to a soft ban. Review the crash screenshot to see if this is the case."
            )
            logger.critical(
                f"Username: {session_state.my_username}, Followers: {session_state.my_followers_count}, Following: {session_state.my_following_count}"
            )
            save_crash(device)
            exit(1)

        if not is_log_file_updated():
            try:
                update_log_file_name(session_state.my_username)
            except Exception as e:
                logger.error(
                    f"Failed to update log file name. Will continue anyway. {e}"
                )
                save_crash(device)

        report_string = f"Hello, @{session_state.my_username}! You have {session_state.my_followers_count} followers and {session_state.my_following_count} followings so far."

        logger.info(report_string, extra={"color": f"{Style.BRIGHT}"})

        storage = Storage(session_state.my_username)
        for plugin in enabled:
            if not session_state.check_limit(
                    args, limit_type=session_state.Limit.ALL, output=False):
                loaded[plugin].run(device, device_id, args, enabled, storage,
                                   sessions, plugin)
            else:
                logger.info(
                    "Successful or Total Interactions limit reached. Ending session."
                )
                break

        close_instagram(device_id)
        session_state.finishTime = datetime.now()

        if args.screen_sleep:
            DeviceFacade(device_id).screen_off()
            logger.info("Screen turned off for sleeping time")

        logger.info(
            "-------- FINISH: " + str(session_state.finishTime) + " --------",
            extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
        )

        if args.repeat:
            print_full_report(sessions)
            repeat = get_value(args.repeat, "Sleep for {} minutes", 180)
            try:
                sleep(60 * repeat)
            except KeyboardInterrupt:
                print_full_report(sessions)
                sessions.persist(directory=session_state.my_username)
                sys.exit(0)
        else:
            break

    print_full_report(sessions)
    sessions.persist(directory=session_state.my_username)
    def handle_hashtag(
        self,
        device,
        hashtag,
        likes_count,
        stories_count,
        stories_percentage,
        follow_percentage,
        follow_limit,
        hashtag_likers_recent,
        # recent_tab,
        storage,
        profile_filter,
        on_like,
        on_watch,
        on_interaction,
    ):
        interaction = partial(
            interact_with_user,
            my_username=self.session_state.my_username,
            likes_count=likes_count,
            stories_count=stories_count,
            stories_percentage=stories_percentage,
            follow_percentage=follow_percentage,
            on_like=on_like,
            on_watch=on_watch,
            profile_filter=profile_filter,
            args=self.args,
            session_state=self.session_state,
        )

        is_follow_limit_reached = partial(
            is_follow_limit_reached_for_source,
            follow_limit=follow_limit,
            source=hashtag,
            session_state=self.session_state,
        )
        search_view = TabBarView(device).navigateToSearch()
        random_sleep()
        if not search_view.navigateToHashtag(hashtag):
            return

        if hashtag_likers_recent != None:
            logger.info("Switching to Recent tab")
            HashTagView(device)._getRecentTab().click()
            random_sleep()
            random_sleep(
            )  # wonder if it possible to check if everything is loaded instead of doing multiple random_sleep..

        logger.info("Opening the first result")

        result_view = HashTagView(device)._getRecyclerView()
        HashTagView(device)._getFistImageView(result_view).click()
        random_sleep()

        posts_list_view = ProfileView(device)._getRecyclerView()
        posts_end_detector = ScrollEndDetector(repeats_to_end=2)
        first_post = True
        post_description = ""
        while True:
            if first_post:
                PostsViewList(device).swipe_to_fit_posts(True)
                first_post = False
            if not OpenedPostView(device).open_likers():
                logger.info("No likes, let's scroll down.",
                            extra={"color": f"{Fore.GREEN}"})
                PostsViewList(device).swipe_to_fit_posts(False)

                flag, post_description = PostsViewList(
                    device).check_if_last_post(post_description)
                if not flag:
                    continue
                else:
                    break

            logger.info("List of likers is opened.")
            posts_end_detector.notify_new_page()
            random_sleep()

            likes_list_view = OpenedPostView(device)._getListViewLikers()
            prev_screen_iterated_likers = []

            while True:
                logger.info("Iterate over visible likers.")
                screen_iterated_likers = []

                try:
                    for item in OpenedPostView(device)._getUserCountainer():
                        username_view = OpenedPostView(device)._getUserName(
                            item)

                        if not username_view.exists(quick=True):
                            logger.info(
                                "Next item not found: probably reached end of the screen.",
                                extra={"color": f"{Fore.GREEN}"},
                            )
                            break

                        username = username_view.get_text()
                        screen_iterated_likers.append(username)
                        posts_end_detector.notify_username_iterated(username)

                        if storage.is_user_in_blacklist(username):
                            logger.info(f"@{username} is in blacklist. Skip.")
                            continue
                        elif storage.check_user_was_interacted(username):
                            logger.info(
                                f"@{username}: already interacted. Skip.")
                            continue
                        else:
                            logger.info(f"@{username}: interact")
                            username_view.click()

                        can_follow = not is_follow_limit_reached() and (
                            storage.get_following_status(username)
                            == FollowingStatus.NONE
                            or storage.get_following_status(username)
                            == FollowingStatus.NOT_IN_LIST)

                        interaction_succeed, followed = interaction(
                            device, username=username, can_follow=can_follow)
                        storage.add_interacted_user(username,
                                                    followed=followed)
                        can_continue = on_interaction(
                            succeed=interaction_succeed, followed=followed)
                        if not can_continue:
                            return

                        logger.info("Back to likers list")
                        device.back()
                        random_sleep()
                except IndexError:
                    logger.info(
                        "Cannot get next item: probably reached end of the screen.",
                        extra={"color": f"{Fore.GREEN}"},
                    )

                if screen_iterated_likers == prev_screen_iterated_likers:
                    logger.info(
                        "Iterated exactly the same likers twice, finish.",
                        extra={"color": f"{Fore.GREEN}"},
                    )
                    logger.info(f"Back to {hashtag}")
                    device.back()
                    break

                prev_screen_iterated_likers.clear()
                prev_screen_iterated_likers += screen_iterated_likers

                logger.info("Need to scroll now",
                            extra={"color": f"{Fore.GREEN}"})
                likes_list_view.scroll(DeviceFacade.Direction.BOTTOM)

            if posts_end_detector.is_the_end():
                break
            else:
                posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
Beispiel #11
0
    def handle_username_file(
        self,
        device,
        current_file,
        likes_count,
        stories_count,
        stories_percentage,
        follow_percentage,
        follow_limit,
        current_job,
        storage,
        profile_filter,
        on_like,
        on_watch,
        on_interaction,
    ):
        interaction = partial(
            interact_with_user,
            my_username=self.session_state.my_username,
            likes_count=likes_count,
            stories_count=stories_count,
            stories_percentage=stories_percentage,
            follow_percentage=follow_percentage,
            on_like=on_like,
            on_watch=on_watch,
            profile_filter=profile_filter,
            args=self.args,
            session_state=self.session_state,
            current_mode=self.current_mode,
        )
        is_follow_limit_reached = partial(
            is_follow_limit_reached_for_source,
            follow_limit=follow_limit,
            source=current_file,
            session_state=self.session_state,
        )
        need_to_refresh = True
        if path.isfile(current_file):
            with open(current_file, "r") as f:
                for line in f:
                    username = line.strip()
                    if username != "":
                        if storage.is_user_in_blacklist(username):
                            logger.info(f"@{username} is in blacklist. Skip.")
                            continue
                        elif storage.check_user_was_interacted(username):
                            logger.info(
                                f"@{username}: already interacted. Skip.")
                            continue
                        if need_to_refresh:
                            search_view = TabBarView(device).navigateToSearch()
                            random_sleep()
                        profile_view = search_view.navigateToUsername(
                            username, True, need_to_refresh)
                        need_to_refresh = False
                        if not profile_view:
                            continue
                        random_sleep()

                        def interact():
                            can_follow = not is_follow_limit_reached() and (
                                storage.get_following_status(username)
                                == FollowingStatus.NONE
                                or storage.get_following_status(username)
                                == FollowingStatus.NOT_IN_LIST)

                            interaction_succeed, followed = interaction(
                                device,
                                username=username,
                                can_follow=can_follow)
                            storage.add_interacted_user(username,
                                                        followed=followed)
                            can_continue = on_interaction(
                                succeed=interaction_succeed, followed=followed)
                            if not can_continue:
                                return False
                            else:
                                return True

                        logger.info(f"@{username}: interact")
                        if not interact():
                            break
                        device.back()
                    else:
                        logger.info("Line in file is blank, skip.")
                remaining = f.readlines()
            if self.args.delete_interacted_users:
                with open(current_file, "w") as f:
                    f.writelines(remaining)
        else:
            logger.warning(f"File {current_file} not found.")
            return

        logger.info(f"Interact with users in {current_file} complete.")
        device.back()