예제 #1
0
def _open_user(device, username, open_followers=False, open_followings=False, refresh=False, on_action=None):
    if refresh:
        print("Refreshing profile status...")
        coordinator_layout = device.find(resourceId='com.instagram.android:id/coordinator_root_layout')
        if coordinator_layout.exists():
            coordinator_layout.scroll(DeviceFacade.Direction.TOP)

    if username is None:
        if open_followers:
            print("Open your followers")
            followers_button = device.find(resourceIdMatches=FOLLOWERS_BUTTON_ID_REGEX)
            followers_button.click()

        if open_followings:
            print("Open your followings")
            followings_button = device.find(resourceIdMatches=FOLLOWING_BUTTON_ID_REGEX)
            followings_button.click()
    else:
        if not search_for(device, username=username, on_action=on_action):
            return False

        if open_followers:
            print("Open @" + username + " followers")
            followers_button = device.find(resourceIdMatches=FOLLOWERS_BUTTON_ID_REGEX)
            followers_button.click()

        if open_followings:
            print("Open @" + username + " followings")
            followings_button = device.find(resourceIdMatches=FOLLOWING_BUTTON_ID_REGEX)
            followings_button.click()

    return True
def extract_hashtag_profiles_and_interact(device, hashtag, instructions,
                                          iteration_callback,
                                          iteration_callback_pre_conditions,
                                          on_action):
    print("Interacting with #{0}-{1}".format(hashtag, instructions.value))

    if not search_for(device, hashtag=hashtag, on_action=on_action):
        return

    # Switch to Recent tab
    if instructions == HashtagInteractionType.RECENT_LIKERS:
        print("Switching to Recent tab")
        tab_layout = device.find(
            resourceId='com.instagram.android:id/tab_layout',
            className='android.widget.LinearLayout')
        if tab_layout.exists():
            tab_layout.child(index=1).click()
        else:
            print("Can't Find recent tab. Interacting with Popular.")

        sleeper.random_sleep()

    # Open first post
    print("Opening the first post")
    # Index 1 is reserved for hot Reels by this tag
    first_post_index = 2 if instructions == HashtagInteractionType.TOP_LIKERS else 1
    first_post_view = device.find(
        resourceId='com.instagram.android:id/image_button',
        className='android.widget.ImageView',
        index=first_post_index)
    first_post_view.click()
    sleeper.random_sleep()

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

    def pre_conditions(liker_username, liker_username_view):
        posts_end_detector.notify_username_iterated(liker_username)
        return iteration_callback_pre_conditions(liker_username,
                                                 liker_username_view)

    while True:
        if not open_likers(device):
            print(COLOR_OKGREEN + "No likes, let's scroll down." + COLOR_ENDC)
            posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
            continue

        print("List of likers is opened.")
        posts_end_detector.notify_new_page()
        sleeper.random_sleep()

        iterate_over_likers(device, iteration_callback, pre_conditions)

        if posts_end_detector.is_the_end():
            break
        else:
            posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
예제 #3
0
def _open_user(device,
               username,
               open_followers=False,
               open_followings=False,
               refresh=False,
               deep_link_usage_percentage=0,
               on_action=None):
    if refresh:
        print("Refreshing profile status...")
        coordinator_layout = device.find(
            resourceId=f'{device.app_id}:id/coordinator_root_layout')
        if coordinator_layout.exists():
            coordinator_layout.scroll(DeviceFacade.Direction.TOP)

    if username is None:
        if open_followers:
            print("Open your followers")
            ProfileView(device, is_own_profile=True).navigate_to_followers()

        if open_followings:
            print("Open your following")
            ProfileView(device, is_own_profile=True).navigate_to_following()
    else:
        should_open_user_with_search = True
        deep_link_usage_chance = randint(1, 100)
        if deep_link_usage_chance <= deep_link_usage_percentage:
            print(f"Going to open {username} using deeplink")
            should_open_user_with_search = False

            should_continue, is_profile_opened = _open_profile_using_deeplink(
                device, username)
            if not should_continue:
                return False

            if not is_profile_opened:
                print(
                    f"Failed to open profile using deeplink. Using search instead"
                )
                should_open_user_with_search = True

        if should_open_user_with_search:
            if not search_for(device, username=username, on_action=on_action):
                return False

            sleeper.random_sleep()

        is_profile_empty = softban_indicator.detect_empty_profile(device)
        if is_profile_empty:
            return False

        if open_followers:
            print("Open @" + username + " followers")
            ProfileView(device, is_own_profile=True).navigate_to_followers()

        if open_followings:
            print("Open @" + username + " following")
            ProfileView(device, is_own_profile=True).navigate_to_following()

    return True
예제 #4
0
def extract_hashtag_profiles_and_interact(device,
                                          hashtag,
                                          instructions,
                                          iteration_callback,
                                          iteration_callback_pre_conditions,
                                          on_action):
    print("Interacting with #{0}-{1}".format(hashtag, instructions.value))

    if not search_for(device, hashtag=hashtag, on_action=on_action):
        return

    # Switch to Recent tab
    if instructions == HashtagInteractionType.RECENT_LIKERS:
        print("Switching to Recent tab")
        tab_layout = device.find(resourceId=f'{device.app_id}:id/tab_layout',
                                 className='android.widget.LinearLayout')
        if tab_layout.exists():
            tab_layout.child(index=1).click()
        else:
            print("Can't Find recent tab. Interacting with Popular.")

    # Sleep longer because posts loading takes time
    sleeper.random_sleep(multiplier=2.0)

    # Open post
    posts_view_list = PostsGridView(device).open_random_post()
    if posts_view_list is None:
        return

    posts_end_detector = ScrollEndDetector(repeats_to_end=2)

    def pre_conditions(liker_username, liker_username_view):
        posts_end_detector.notify_username_iterated(liker_username)
        return iteration_callback_pre_conditions(liker_username, liker_username_view)

    while True:
        if not open_likers(device):
            print(COLOR_OKGREEN + "No likes, let's scroll down." + COLOR_ENDC)
            posts_view_list.scroll_down()
            continue

        print("List of likers is opened.")
        posts_end_detector.notify_new_page()
        sleeper.random_sleep()

        should_continue_using_source = iterate_over_likers(device, iteration_callback, pre_conditions)

        if not should_continue_using_source:
            break

        if posts_end_detector.is_the_end():
            break
        else:
            posts_view_list.scroll_down()
예제 #5
0
def _open_user(device,
               username,
               open_followers=False,
               open_followings=False,
               refresh=False,
               on_action=None):
    if refresh:
        print("Refreshing profile status...")
        coordinator_layout = device.find(
            resourceId=f'{device.app_id}:id/coordinator_root_layout')
        if coordinator_layout.exists():
            coordinator_layout.scroll(DeviceFacade.Direction.TOP)

    if username is None:
        if open_followers:
            print("Open your followers")
            followers_button = device.find(
                resourceIdMatches=FOLLOWERS_BUTTON_ID_REGEX.format(
                    device.app_id, device.app_id))
            followers_button.click()

        if open_followings:
            print("Open your followings")
            followings_button = device.find(
                resourceIdMatches=FOLLOWING_BUTTON_ID_REGEX.format(
                    device.app_id, device.app_id))
            followings_button.click()
    else:
        if not search_for(device, username=username, on_action=on_action):
            return False

        sleeper.random_sleep()

        is_profile_empty = softban_indicator.detect_empty_profile(device)
        if is_profile_empty:
            return False

        if open_followers:
            print("Open @" + username + " followers")
            followers_button = device.find(
                resourceIdMatches=FOLLOWERS_BUTTON_ID_REGEX.format(
                    device.app_id, device.app_id))
            followers_button.click()

        if open_followings:
            print("Open @" + username + " followings")
            followings_button = device.find(
                resourceIdMatches=FOLLOWING_BUTTON_ID_REGEX.format(
                    device.app_id, device.app_id))
            followings_button.click()

    return True
예제 #6
0
def extract_hashtag_likers_and_interact(device, hashtag, iteration_callback,
                                        iteration_callback_pre_conditions,
                                        on_action):
    print("Interacting with #{0} recent-likers".format(hashtag))

    if not search_for(device, hashtag=hashtag, on_action=on_action):
        return

    # Switch to Recent tab
    print("Switching to Recent tab")
    tab_layout = device.find(resourceId='com.instagram.android:id/tab_layout',
                             className='android.widget.LinearLayout')
    tab_layout.child(index=1).click()
    random_sleep()

    # Open first post
    print("Opening the first post")
    first_post_view = device.find(
        resourceId='com.instagram.android:id/image_button',
        className='android.widget.ImageView',
        index=1)
    first_post_view.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)

    def pre_conditions(liker_username, liker_username_view):
        posts_end_detector.notify_username_iterated(liker_username)
        return iteration_callback_pre_conditions(liker_username,
                                                 liker_username_view)

    while True:
        if not open_likers(device):
            print(COLOR_OKGREEN + "No likes, let's scroll down." + COLOR_ENDC)
            posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
            continue

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

        iterate_over_likers(device, iteration_callback, pre_conditions)

        if posts_end_detector.is_the_end():
            break
        else:
            posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
예제 #7
0
def _open_user_followers(device, username):
    if username is None:
        print("Open your followers")
        followers_button = device.find(resourceIdMatches=FOLLOWERS_BUTTON_ID_REGEX)
        followers_button.click()
    else:
        if not search_for(device, username=username):
            return False

        print("Open @" + username + " followers")
        followers_button = device.find(resourceIdMatches=FOLLOWERS_BUTTON_ID_REGEX)
        followers_button.click()

    return True
예제 #8
0
    def navigate_to_feed():
        if not search_for(device, hashtag=hashtag, on_action=on_action):
            return None

        # Switch to Recent tab
        if instructions == HashtagInteractionType.RECENT_LIKERS or instructions == HashtagInteractionType.RECENT_POSTS:
            print("Switching to Recent tab")
            tab_layout = device.find(
                resourceId=f'{device.app_id}:id/tab_layout',
                className='android.widget.LinearLayout')
            if tab_layout.exists():
                tab_layout.child(index=1).click()
            else:
                print("Can't Find recent tab. Interacting with Popular.")

        # Sleep longer because posts loading takes time
        sleeper.random_sleep(multiplier=2.0)

        # Open post
        posts_view_list = PostsGridView(device).open_random_post()
        if posts_view_list is None:
            return None

        return posts_view_list
예제 #9
0
def handle_place(device, place, instructions, session_state, likes_count,
                 stories_count, follow_percentage, like_percentage,
                 comment_percentage, comments_list, storage, on_action,
                 is_limit_reached, is_passed_filters, action_status):
    if not search_for(device, place=place, on_action=on_action):
        return None

    # Switch to Recent tab if needed
    if instructions == PlaceInteractionType.RECENT_LIKERS or instructions == PlaceInteractionType.RECENT_POSTS:
        sleeper.random_sleep()
        print("Switching to Recent tab")
        tab_layout = device.find(resourceId=f'{device.app_id}:id/tab_layout',
                                 className='android.widget.LinearLayout')
        if tab_layout.exists():
            tab_layout.child(index=1).click()
        else:
            print("Can't Find recent tab. Interacting with Popular.")

    # Sleep longer because posts loading takes time
    sleeper.random_sleep(multiplier=2.0)

    source_type = f'{SourceType.PLACE.value}-{instructions.value}'
    interaction = partial(interact_with_user,
                          device=device,
                          user_source=place,
                          source_type=source_type,
                          my_username=session_state.my_username,
                          on_action=on_action)

    def pre_conditions(liker_username, liker_username_view):
        if storage.is_user_in_blacklist(liker_username):
            print("@" + liker_username + " is in blacklist. Skip.")
            return False
        elif storage.check_user_was_filtered(liker_username):
            print("@" + liker_username + ": already filtered in past. Skip.")
            return False
        elif storage.check_user_was_interacted(liker_username):
            print("@" + liker_username + ": already interacted. Skip.")
            return False

        return True

    def interact_with_profile(liker_username, liker_username_view):
        """
        :return: whether we should continue interaction with other users after this one
        """
        is_interact_limit_reached, interact_reached_source_limit, interact_reached_session_limit = \
            is_limit_reached(InteractAction(source_name=place, source_type=source_type, user=liker_username, succeed=True), session_state)

        if not process_limits(
                is_interact_limit_reached, interact_reached_session_limit,
                interact_reached_source_limit, action_status, "Interaction"):
            return False

        is_get_profile_limit_reached, get_profile_reached_source_limit, get_profile_reached_session_limit = \
            is_limit_reached(GetProfileAction(user=liker_username), session_state)

        if not process_limits(is_get_profile_limit_reached,
                              get_profile_reached_session_limit,
                              get_profile_reached_source_limit, action_status,
                              "Get-Profile"):
            return False

        is_all_filters_satisfied = False
        if is_passed_filters is not None:
            print_debug(f"Running filter-ahead on @{liker_username}")
            should_continue, is_all_filters_satisfied = is_passed_filters(
                device,
                liker_username,
                reset=True,
                filters_tags=['BEFORE_PROFILE_CLICK'])
            if not should_continue:
                on_action(FilterAction(liker_username))
                return True

            if not is_all_filters_satisfied:
                print_debug(
                    "Not all filters are satisfied with filter-ahead, continue filtering inside the profile-page"
                )

        print("@" + liker_username + ": interact")
        liker_username_view.click()
        on_action(GetProfileAction(user=liker_username))

        sleeper.random_sleep()
        is_profile_empty = softban_indicator.detect_empty_profile(device)

        if is_profile_empty:
            print("Back to likers list")
            device.back()
            return True

        if is_passed_filters is not None:
            if not is_all_filters_satisfied:
                should_continue, _ = is_passed_filters(device,
                                                       liker_username,
                                                       reset=False)
                if not should_continue:
                    on_action(FilterAction(liker_username))
                    # Continue to next follower
                    print("Back to likers list")
                    device.back()
                    return True

        is_like_limit_reached, like_reached_source_limit, like_reached_session_limit = \
            is_limit_reached(LikeAction(source_name=place, source_type=source_type, user=liker_username), session_state)

        is_follow_limit_reached, follow_reached_source_limit, follow_reached_session_limit = \
            is_limit_reached(FollowAction(source_name=place, source_type=source_type, user=liker_username), session_state)

        is_watch_limit_reached, watch_reached_source_limit, watch_reached_session_limit = \
            is_limit_reached(StoryWatchAction(source_name=place, source_type=source_type, user=liker_username), session_state)

        is_comment_limit_reached, comment_reached_source_limit, comment_reached_session_limit = \
            is_limit_reached(CommentAction(source_name=place, source_type=source_type, user=liker_username, comment=""), session_state)

        is_private = is_private_account(device)
        if is_private:
            if is_passed_filters is None:
                print(COLOR_OKGREEN + "@" + liker_username +
                      " has private account, won't interact." + COLOR_ENDC)
                on_action(FilterAction(liker_username))
                on_action(
                    InteractAction(source_name=place,
                                   source_type=source_type,
                                   user=liker_username,
                                   succeed=False))
                print("Back to likers list")
                device.back()
                return True
            print("@" + liker_username +
                  ": Private account - images wont be liked.")

        do_have_stories = do_have_story(device)
        if not do_have_stories:
            print("@" + liker_username +
                  ": seems there are no stories to be watched.")

        is_likes_enabled = likes_count != '0'
        is_stories_enabled = stories_count != '0'
        is_follow_enabled = follow_percentage != 0
        is_comment_enabled = comment_percentage != 0

        likes_value = get_value(likes_count,
                                "Likes count: {}",
                                2,
                                max_count=12)
        stories_value = get_value(stories_count, "Stories to watch: {}", 1)

        can_like = not is_like_limit_reached and not is_private and likes_value > 0
        can_follow = (
            not is_follow_limit_reached
        ) and storage.get_following_status(
            liker_username) == FollowingStatus.NONE and follow_percentage > 0
        can_watch = (not is_watch_limit_reached
                     ) and do_have_stories and stories_value > 0
        can_comment = (not is_comment_limit_reached
                       ) and not is_private and comment_percentage > 0
        can_interact = can_like or can_follow or can_watch or can_comment

        if not can_interact:
            print(
                "@" + liker_username +
                ": Cant be interacted (due to limits / already followed). Skip."
            )
            on_action(
                InteractAction(source_name=place,
                               source_type=source_type,
                               user=liker_username,
                               succeed=False))
        else:
            print_interaction_types(liker_username, can_like, can_follow,
                                    can_watch, can_comment)
            interaction_strategy = InteractionStrategy(
                do_like=can_like,
                do_follow=can_follow,
                do_story_watch=can_watch,
                do_comment=can_comment,
                likes_count=likes_value,
                follow_percentage=follow_percentage,
                like_percentage=like_percentage,
                stories_count=stories_value,
                comment_percentage=comment_percentage,
                comments_list=comments_list)

            is_liked, is_followed, is_watch, is_commented = interaction(
                username=liker_username,
                interaction_strategy=interaction_strategy)
            if is_liked or is_followed or is_watch or is_commented:
                on_action(
                    InteractAction(source_name=place,
                                   source_type=source_type,
                                   user=liker_username,
                                   succeed=True))
                print_short_report(f"P-{place}", session_state)
            else:
                on_action(
                    InteractAction(source_name=place,
                                   source_type=source_type,
                                   user=liker_username,
                                   succeed=False))

        can_continue = True

        if ((is_like_limit_reached and is_likes_enabled) or not is_likes_enabled) and \
           ((is_follow_limit_reached and is_follow_enabled) or not is_follow_enabled) and \
           ((is_comment_limit_reached and is_comment_enabled) or not is_comment_enabled) and \
           ((is_watch_limit_reached and is_stories_enabled) or not is_stories_enabled):
            # If one of the limits reached for source-limit, move to next source
            if (like_reached_source_limit is not None and like_reached_session_limit is None) or \
                    (follow_reached_source_limit is not None and follow_reached_session_limit is None):
                can_continue = False
                action_status.set_limit(ActionState.SOURCE_LIMIT_REACHED)

            # If all of the limits reached for session-limit, finish the session
            if ((like_reached_session_limit is not None and is_likes_enabled) or not is_likes_enabled) and \
                    ((follow_reached_session_limit is not None and is_follow_enabled) or not is_follow_enabled):
                can_continue = False
                action_status.set_limit(ActionState.SESSION_LIMIT_REACHED)

        print("Back to followers list")
        device.back()

        return can_continue

    def navigate_to_feed():
        # Open post
        posts_view_list = PostsGridView(device).open_random_post()
        if posts_view_list is None:
            return None

        return posts_view_list

    def should_continue_interact_with_feed():
        return True

    def interact_with_feed_post(posts_views_list):
        is_interact_limit_reached, interact_reached_source_limit, interact_reached_session_limit = \
            is_limit_reached(
                InteractAction(source_name=place, source_type=source_type, user=None, succeed=True),
                session_state)

        if not process_limits(
                is_interact_limit_reached, interact_reached_session_limit,
                interact_reached_source_limit, action_status, "Interaction"):
            return False

        is_like_limit_reached, like_reached_source_limit, like_reached_session_limit = \
            is_limit_reached(LikeAction(source_name=place, source_type=source_type, user=None),
                             session_state)

        if not process_limits(
                is_like_limit_reached, like_reached_session_limit,
                like_reached_source_limit, action_status, "Likes"):
            return False

        opened_post_view = posts_views_list.get_current_post()
        author_name = opened_post_view.get_author_name()

        like_chance = randint(1, 100)
        if like_chance > like_percentage:
            print("Not going to like image due to like-percentage hit")
            on_action(
                InteractAction(source_name=place,
                               source_type=source_type,
                               user=author_name,
                               succeed=False))
        else:
            print("Like post")
            opened_post_view.like()
            if author_name is not None:
                on_action(
                    LikeAction(source_name=place,
                               source_type=source_type,
                               user=author_name))
                on_action(
                    InteractAction(source_name=place,
                                   source_type=source_type,
                                   user=author_name,
                                   succeed=True))

        return True

    if instructions == PlaceInteractionType.RECENT_LIKERS or instructions == PlaceInteractionType.TOP_LIKERS:
        extract_place_likers_and_interact(device, place, instructions,
                                          navigate_to_feed,
                                          interact_with_profile,
                                          pre_conditions, on_action)
    elif instructions == PlaceInteractionType.RECENT_POSTS or instructions == PlaceInteractionType.TOP_POSTS:
        interact_with_feed(navigate_to_feed,
                           should_continue_interact_with_feed,
                           interact_with_feed_post)
예제 #10
0
def extract_hashtag_profiles_and_interact(device, hashtag, instructions,
                                          iteration_callback,
                                          iteration_callback_pre_conditions,
                                          on_action):
    print("Interacting with #{0}-{1}".format(hashtag, instructions.value))

    if not search_for(device, hashtag=hashtag, on_action=on_action):
        return

    # Switch to Recent tab
    if instructions == HashtagInteractionType.RECENT_LIKERS:
        print("Switching to Recent tab")
        tab_layout = device.find(resourceId=f'{device.app_id}:id/tab_layout',
                                 className='android.widget.LinearLayout')
        if tab_layout.exists():
            tab_layout.child(index=1).click()
        else:
            print("Can't Find recent tab. Interacting with Popular.")

        sleeper.random_sleep()

    # Open post
    # Scroll down several times to pick random post
    scroll_times = randint(0, 5)
    posts_grid = device.find(
        resourceId=f'{device.app_id}:id/recycler_view',
        className='androidx.recyclerview.widget.RecyclerView')
    print(f"Scroll down {scroll_times} times.")
    for _ in range(0, scroll_times):
        posts_grid.scroll(DeviceFacade.Direction.BOTTOM)
        sleeper.random_sleep()

    # Scan for available posts' coordinates
    available_posts_coords = []
    print("Choosing a random post from those on the screen")
    for post_view in posts_grid.child(
            resourceId=f'{device.app_id}:id/image_button',
            className='android.widget.ImageView'):
        bounds = post_view.get_bounds()
        left = bounds["left"]
        top = bounds["top"]
        right = bounds["right"]
        bottom = bounds["bottom"]
        coords = (left + (right - left) / 2, top + (bottom - top) / 2)
        available_posts_coords.append(coords)
    if len(available_posts_coords) == 0:
        print(COLOR_FAIL + f"No posts for #{hashtag}. Abort." + COLOR_ENDC)
        return

    # Pick random post from available ones
    coords = random.choice(available_posts_coords)
    print(f"Open the post at {coords}")
    device.screen_click_by_coordinates(coords[0], coords[1])
    sleeper.random_sleep()
    posts_list_view = device.find(
        resourceId='android:id/list',
        className='androidx.recyclerview.widget.RecyclerView')
    if not posts_list_view.exists():
        print("Couldn't open a post, will try again.")
        device.screen_click_by_coordinates(coords[0], coords[1])
        sleeper.random_sleep()

    posts_end_detector = ScrollEndDetector(repeats_to_end=2)

    def pre_conditions(liker_username, liker_username_view):
        posts_end_detector.notify_username_iterated(liker_username)
        return iteration_callback_pre_conditions(liker_username,
                                                 liker_username_view)

    while True:
        if not open_likers(device):
            print(COLOR_OKGREEN + "No likes, let's scroll down." + COLOR_ENDC)
            posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
            continue

        print("List of likers is opened.")
        posts_end_detector.notify_new_page()
        sleeper.random_sleep()

        should_continue_using_source = iterate_over_likers(
            device, iteration_callback, pre_conditions)

        if not should_continue_using_source:
            break

        if posts_end_detector.is_the_end():
            break
        else:
            posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
예제 #11
0
def extract_place_profiles_and_interact(device, place, instructions,
                                        iteration_callback,
                                        iteration_callback_pre_conditions,
                                        on_action):
    print("Interacting with place-{0}-{1}".format(place, instructions.value))

    if not search_for(device, place=place, on_action=on_action):
        return

    # Switch to Recent tab
    if instructions == PlaceInteractionType.RECENT_LIKERS:
        print("Switching to Recent tab")
        tab_layout = device.find(resourceId=f'{device.app_id}:id/tab_layout',
                                 className='android.widget.LinearLayout')
        if tab_layout.exists():
            tab_layout.child(index=1).click()
        else:
            print("Can't Find recent tab. Interacting with Popular.")

        sleeper.random_sleep()

    # Open post
    first_post_index = 2
    post_num = randint(first_post_index, 20)
    print(f"Opening post #{post_num}")
    post_view = device.find(resourceId=f'{device.app_id}:id/image_button',
                            className='android.widget.ImageView',
                            index=post_num)

    for _ in range(0, 10):
        if post_view.exists(quick=True):
            break

        print(f"Cannot find post #{post_num}. Swiping down a bit.")
        device.swipe(DeviceFacade.Direction.TOP)

    if not post_view.exists(quick=True):
        print(f"Cannot find post #{post_num} after 10 swipes. Aborting.")

    post_view.click()
    sleeper.random_sleep()

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

    def pre_conditions(liker_username, liker_username_view):
        posts_end_detector.notify_username_iterated(liker_username)
        return iteration_callback_pre_conditions(liker_username,
                                                 liker_username_view)

    while True:
        if not open_likers(device):
            print(COLOR_OKGREEN + "No likes, let's scroll down." + COLOR_ENDC)
            posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
            continue

        print("List of likers is opened.")
        posts_end_detector.notify_new_page()
        sleeper.random_sleep()

        should_continue_using_source = iterate_over_likers(
            device, iteration_callback, pre_conditions)

        if not should_continue_using_source:
            break

        if posts_end_detector.is_the_end():
            break
        else:
            posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
예제 #12
0
def _open_user(device,
               username,
               open_followers=False,
               open_followings=False,
               refresh=False,
               deep_link_usage_percentage=0,
               on_action=None):
    if refresh:
        print("Refreshing profile status...")
        coordinator_layout = device.find(
            resourceId=f'{device.app_id}:id/coordinator_root_layout')
        if coordinator_layout.exists():
            coordinator_layout.scroll(DeviceFacade.Direction.TOP)

    if username is None:
        if open_followers:
            print("Open your followers")
            followers_button = device.find(
                resourceIdMatches=FOLLOWERS_BUTTON_ID_REGEX.format(
                    device.app_id, device.app_id))
            followers_button.click()

        if open_followings:
            print("Open your followings")
            followings_button = device.find(
                resourceIdMatches=FOLLOWING_BUTTON_ID_REGEX.format(
                    device.app_id, device.app_id))
            followings_button.click()
            sleeper.random_sleep()
            followings_tab = device.find(
                classNameMatches=TEXTVIEW_OR_BUTTON_REGEX,
                clickable=True,
                textContains=' Following')
            followings_tab.click()
    else:
        should_open_user_with_search = True
        deep_link_usage_chance = randint(1, 100)
        if deep_link_usage_chance <= deep_link_usage_percentage:
            print(f"Going to open {username} using deeplink")
            should_open_user_with_search = False

            should_continue, is_profile_opened = _open_profile_using_deeplink(
                device, username)
            if not should_continue:
                return False

            if not is_profile_opened:
                print(
                    f"Failed to open profile using deeplink. Using search instead"
                )
                should_open_user_with_search = True

        if should_open_user_with_search:
            if not search_for(device, username=username, on_action=on_action):
                return False

            sleeper.random_sleep()

        is_profile_empty = softban_indicator.detect_empty_profile(device)
        if is_profile_empty:
            return False

        if open_followers:
            print("Open @" + username + " followers")
            followers_button = device.find(
                resourceIdMatches=FOLLOWERS_BUTTON_ID_REGEX.format(
                    device.app_id, device.app_id))
            followers_button.click()

        if open_followings:
            print("Open @" + username + " followings")
            followings_button = device.find(
                resourceIdMatches=FOLLOWING_BUTTON_ID_REGEX.format(
                    device.app_id, device.app_id))
            followings_button.click()
            sleeper.random_sleep()
            followings_tab = device.find(
                classNameMatches=TEXTVIEW_OR_BUTTON_REGEX,
                clickable=True,
                textContains=' Following')
            followings_tab.click()

    return True