예제 #1
0
def _comment(device, my_username, comments_list, on_comment):
    comment_button = device.find(resourceId=f'{device.app_id}:id/row_feed_button_comment',
                                 className="android.widget.ImageView")
    if not comment_button.exists(quick=True) or not ActionBarView.is_in_interaction_rect(comment_button):
        print("Cannot find comment button – will try to swipe down a bit")
        device.swipe(DeviceFacade.Direction.TOP)
    if not comment_button.exists(quick=True):
        print("Still cannot find comment button – won't comment")
        return

    comment_box_exists = False
    comment_box = None

    for _ in range(2):
        print("Open comments of post")
        comment_button.click()
        sleeper.random_sleep()

        comment_box = device.find(resourceId=f'{device.app_id}:id/layout_comment_thread_edittext')
        if comment_box.exists(quick=True):
            if not comment_box.is_enabled():
                print("Comments are restricted – not commenting...")
                device.back()
                return
            comment_box_exists = True
            break

    if not comment_box_exists:
        print("Couldn't open comments properly - not commenting...")
        return

    comment = spin(choice(comments_list))
    print(f"Commenting: {comment}")

    comment_box.set_text(comment)
    sleeper.random_sleep()

    post_button = device.find(resourceId=f'{device.app_id}:id/layout_comment_thread_post_button_click_area')
    post_button.click()

    sleeper.random_sleep()
    softban_indicator.detect_action_blocked_dialog(device)

    device.close_keyboard()

    just_post = device.find(
        resourceId=f'{device.app_id}:id/row_comment_textview_comment',
        text=f"{my_username} {comment}",
    )

    if just_post.exists(True):
        print("Comment succeed.")
        on_comment(comment)
    else:
        print(COLOR_FAIL + "Failed to check if comment succeed." + COLOR_ENDC)

    sleeper.random_sleep()
    print("Go back to post view.")
    device.back()
예제 #2
0
def do_unfollow(device, username, my_username, check_if_is_follower,
                on_action):
    """
    :return: whether unfollow was successful
    """
    username_view = device.find(
        resourceId=f'{device.app_id}:id/follow_list_username',
        className='android.widget.TextView',
        text=username)
    if not username_view.exists():
        print(COLOR_FAIL + "Cannot find @" + username + ", skip." + COLOR_ENDC)
        return False
    username_view.click()
    on_action(GetProfileAction(user=username))
    sleeper.random_sleep()
    if_profile_empty = softban_indicator.detect_empty_profile(device)

    if if_profile_empty:
        print("Back to the followings list.")
        device.back()
        return False

    if check_if_is_follower and _check_is_follower(device, username,
                                                   my_username):
        print("Skip @" + username + ". This user is following you.")
        print("Back to the followings list.")
        device.back()
        return False

    unfollow_button = device.find(classNameMatches=TEXTVIEW_OR_BUTTON_REGEX,
                                  clickable=True,
                                  text='Following')
    if not unfollow_button.exists():
        print(
            COLOR_FAIL +
            "Cannot find Following button. Maybe not English language is set?"
            + COLOR_ENDC)
        save_crash(device)
        switch_to_english(device)
        raise LanguageChangedException()
    unfollow_button.click()

    confirm_unfollow_button = device.find(
        resourceId=f'{device.app_id}:id/follow_sheet_unfollow_row',
        className='android.widget.TextView')
    if not confirm_unfollow_button.exists():
        print(COLOR_FAIL + "Cannot confirm unfollow." + COLOR_ENDC)
        save_crash(device)
        device.back()
        return False
    confirm_unfollow_button.click()

    sleeper.random_sleep()
    _close_confirm_dialog_if_shown(device)
    softban_indicator.detect_action_blocked_dialog(device)

    print("Back to the followings list.")
    device.back()
    return True
예제 #3
0
def _open_photo_and_like_and_comment(device, row, column, do_like, do_comment,
                                     like_percentage, on_like,
                                     comment_percentage, comments_list,
                                     my_username, on_comment):
    def open_photo():
        # recycler_view has a className 'androidx.recyclerview.widget.RecyclerView' on modern Android versions and
        # 'android.view.View' on Android 5.0.1 and probably earlier versions
        recycler_view = device.find(resourceId='android:id/list')
        row_view = recycler_view.child(index=row + 1)
        if not row_view.exists():
            return False
        item_view = row_view.child(index=column)
        if not item_view.exists():
            return False
        item_view.click()
        if not OpenedPostView(device).is_visible():
            print(COLOR_OKGREEN +
                  "Didn't open the post by click, trying again..." +
                  COLOR_ENDC)
            item_view.click()
            if not OpenedPostView(device).is_visible():
                print(COLOR_FAIL + "Couldn't open this post twice, abort." +
                      COLOR_ENDC)
                return False
        return True

    if not open_photo():
        return False

    sleeper.random_sleep()

    to_like = False
    to_comment = False
    if do_like:
        to_like = True
        like_chance = randint(1, 100)
        if like_chance > like_percentage:
            print("Not going to like image due to like-percentage hit")
            to_like = False

    if do_comment:
        to_comment = True
        comment_chance = randint(1, 100)
        if comment_chance > comment_percentage:
            print("Not going to comment image due to comment-percentage hit")
            to_comment = False

    if to_like:
        OpenedPostView(device).like()
        softban_indicator.detect_action_blocked_dialog(device)
        on_like()

    if to_comment:
        _comment(device, my_username, comments_list, on_comment)

    print("Back to profile")
    device.back()
    return True
예제 #4
0
def _follow(device, username, follow_percentage):
    follow_chance = randint(1, 100)
    if follow_chance > follow_percentage:
        return False

    print("Following...")
    coordinator_layout = device.find(resourceId=f'{device.app_id}:id/coordinator_root_layout')
    if coordinator_layout.exists():
        coordinator_layout.scroll(DeviceFacade.Direction.TOP)

    sleeper.random_sleep()

    profile_header_main_layout = device.find(resourceId=f"{device.app_id}:id/profile_header_fixed_list",
                                             className='android.widget.LinearLayout')

    shop_button = profile_header_main_layout.child(className='android.widget.Button',
                                                   clickable=True,
                                                   textMatches=SHOP_REGEX)

    if shop_button.exists(quick=True):
        follow_button = profile_header_main_layout.child(className='android.widget.Button',
                                                         clickable=True,
                                                         textMatches=FOLLOW_REGEX)
        if not follow_button.exists():
            print(COLOR_FAIL + "Look like a shop profile without an option to follow, continue." + COLOR_ENDC)
            return False
    else:
        profile_header_actions_layout = device.find(resourceId=f'{device.app_id}:id/profile_header_actions_top_row',
                                                    className='android.widget.LinearLayout')
        if not profile_header_actions_layout.exists():
            print(COLOR_FAIL + "Cannot find profile actions." + COLOR_ENDC)
            return False

        follow_button = profile_header_actions_layout.child(classNameMatches=TEXTVIEW_OR_BUTTON_REGEX,
                                                            clickable=True,
                                                            textMatches=FOLLOW_REGEX)

        if not follow_button.exists():
            unfollow_button = profile_header_actions_layout.child(classNameMatches=TEXTVIEW_OR_BUTTON_REGEX,
                                                                  clickable=True,
                                                                  textMatches=UNFOLLOW_REGEX)
            if unfollow_button.exists():
                print(COLOR_OKGREEN + "You already follow @" + username + "." + COLOR_ENDC)
                return False
            else:
                print(COLOR_FAIL + "Cannot find neither Follow button, nor Unfollow button. Maybe not "
                                   "English language is set?" + COLOR_ENDC)
                save_crash(device)
                switch_to_english(device)
                return False

    follow_button.click()
    softban_indicator.detect_action_blocked_dialog(device)
    print(COLOR_OKGREEN + "Followed @" + username + COLOR_ENDC)
    sleeper.random_sleep()
    return True
예제 #5
0
def _comment(device, my_username, comments_list, on_comment):
    comment_button = device.find(
        resourceId=f'{device.app_id}:id/row_feed_button_comment',
        className="android.widget.ImageView",
    )
    if not comment_button.exists(quick=True):
        print("Couldn't find comment button - not commenting...")

    comment_box_exists = False
    comment_box = None

    for _ in range(2):
        print("Open comments of post")
        comment_button.click()
        sleeper.random_sleep()

        comment_box = device.find(
            resourceId=f'{device.app_id}:id/layout_comment_thread_edittext')
        if comment_box.exists(quick=True):
            comment_box_exists = True
            break

    if not comment_box_exists:
        print("Couldn't open comments properly - not commenting...")
        return

    comment = choice(comments_list)
    print(f"Commenting: {comment}")

    comment_box.set_text(comment)
    sleeper.random_sleep()

    post_button = device.find(
        resourceId=
        f'{device.app_id}:id/layout_comment_thread_post_button_click_area')
    post_button.click()

    sleeper.random_sleep()
    softban_indicator.detect_action_blocked_dialog(device)

    device.close_keyboard()

    just_post = device.find(
        resourceId=f'{device.app_id}:id/row_comment_textview_comment',
        text=f"{my_username} {comment}",
    )

    if just_post.exists(True):
        print("Comment succeed.")
        on_comment(comment)
    else:
        print("Failed to check if comment succeed.")

    sleeper.random_sleep()
    print("Go back to post view.")
    device.back()
예제 #6
0
def _open_photo_and_like(device, row, column, like_percentage, on_like):
    def open_photo():
        # recycler_view has a className 'androidx.recyclerview.widget.RecyclerView' on modern Android versions and
        # 'android.view.View' on Android 5.0.1 and probably earlier versions
        recycler_view = device.find(resourceId='android:id/list')
        row_view = recycler_view.child(index=row + 1)
        if not row_view.exists():
            return False
        item_view = row_view.child(index=column)
        if not item_view.exists():
            return False
        item_view.click()
        return True

    if not open_photo():
        return False

    sleeper.random_sleep()

    to_like = True
    like_chance = randint(1, 100)
    if like_chance > like_percentage:
        print("Not going to like image due to like-percentage hit")
        to_like = False

    if to_like:
        print("Double click!")
        photo_view = device.find(
            resourceId=f'{device.app_id}:id/layout_container_main',
            className='android.widget.FrameLayout')
        photo_view.double_click()
        sleeper.random_sleep()

        # If double click didn't work, set like by icon click
        try:
            # Click only button which is under the action bar and above the tab bar.
            # It fixes bugs with accidental back / home clicks.
            for like_button in device.find(
                    resourceId=f'{device.app_id}:id/row_feed_button_like',
                    className='android.widget.ImageView',
                    selected=False):
                if ActionBarView.is_in_interaction_rect(like_button):
                    print("Double click didn't work, click on icon.")
                    like_button.click()
                    sleeper.random_sleep()
                    break
        except DeviceFacade.JsonRpcError:
            print("Double click worked successfully.")

        softban_indicator.detect_action_blocked_dialog(device)
        on_like()

    print("Back to profile")
    device.back()
    return True
예제 #7
0
def do_unfollow(device, my_username, username, storage, check_if_is_follower,
                username_view, follow_status_button_view, on_action):
    """
    :return: whether unfollow was successful
    """
    need_to_go_back_to_list = True
    unfollow_from_list_chance = randint(1, 100)

    if follow_status_button_view is not None and not check_if_is_follower and unfollow_from_list_chance > 50:
        # We can unfollow directly here instead of getting inside to profile
        need_to_go_back_to_list = False
        print("Unfollowing a profile directly from the following list.")
        follow_status_button_view.click()
    else:
        print("Unfollowing a profile from his profile page.")
        username_view.click()
        on_action(GetProfileAction(user=username))
        sleeper.random_sleep()
        if_profile_empty = softban_indicator.detect_empty_profile(device)

        if if_profile_empty:
            print("Back to the followings list.")
            device.back()
            return False

        if check_if_is_follower and _check_is_follower(device, username,
                                                       my_username):
            print("Skip @" + username + ". This user is following you.")
            storage.update_follow_status(username, True, True)
            print("Back to the followings list.")
            device.back()
            return False

        unfollow_button = device.find(
            classNameMatches=TEXTVIEW_OR_BUTTON_REGEX,
            clickable=True,
            text='Following')
        if not unfollow_button.exists():
            print(
                COLOR_FAIL +
                "Cannot find Following button. Maybe not English language is set?"
                + COLOR_ENDC)
            save_crash(device)
            switch_to_english(device)
            raise LanguageChangedException()

        print(f"Unfollowing @{username}...")
        unfollow_button.click()

        sleeper.random_sleep()

        confirm_unfollow_button = device.find(
            resourceId=f'{device.app_id}:id/follow_sheet_unfollow_row',
            className='android.widget.TextView')
        if not confirm_unfollow_button.exists():
            print(COLOR_FAIL + "Cannot confirm unfollow." + COLOR_ENDC)
            save_crash(device)
            device.back()
            return False
        confirm_unfollow_button.click()

    sleeper.random_sleep()
    _close_confirm_dialog_if_shown(device)
    softban_indicator.detect_action_blocked_dialog(device)

    if need_to_go_back_to_list:
        print("Back to the followings list.")
        device.back()

    return True
예제 #8
0
def _open_photo_and_like_and_comment(device, row, column, do_like, do_comment,
                                     like_percentage, on_like,
                                     comment_percentage, comments_list,
                                     my_username, on_comment):
    def open_photo():
        # recycler_view has a className 'androidx.recyclerview.widget.RecyclerView' on modern Android versions and
        # 'android.view.View' on Android 5.0.1 and probably earlier versions
        recycler_view = device.find(resourceId='android:id/list')
        row_view = recycler_view.child(index=row + 1)
        if not row_view.exists():
            return False
        item_view = row_view.child(index=column)
        if not item_view.exists():
            return False
        item_view.click()
        return True

    if not open_photo():
        return False

    sleeper.random_sleep()

    to_like = False
    to_comment = False
    if do_like:
        to_like = True
        like_chance = randint(1, 100)
        if like_chance > like_percentage:
            print("Not going to like image due to like-percentage hit")
            to_like = False

    if do_comment:
        to_comment = True
        comment_chance = randint(1, 100)
        if comment_chance > comment_percentage:
            print("Not going to comment image due to comment-percentage hit")
            to_comment = False

    if to_like:
        print("Double click!")

        post_view = device.find(resourceIdMatches=POST_VIEW_ID_REGEX.format(
            device.app_id, device.app_id),
                                className='android.widget.FrameLayout')
        if post_view.exists:
            post_view.double_click()
            sleeper.random_sleep()
            if not post_view.exists(quick=True):
                print(COLOR_OKGREEN +
                      "Accidentally went out of the post page, going back..." +
                      COLOR_ENDC)
                device.back()
        else:
            print(
                COLOR_FAIL +
                "Cannot find zoomable_view_container, fallback to the old liking algorithm"
                + COLOR_ENDC)
            post_view = device.find(
                resourceId=f'{device.app_id}:id/layout_container_main',
                className='android.widget.FrameLayout')
            post_view.double_click()
            sleeper.random_sleep()

        # If like button is not visible, scroll down
        like_button = device.find(
            resourceId=f'{device.app_id}:id/row_feed_button_like',
            className='android.widget.ImageView')
        if not like_button.exists(
                quick=True) or not ActionBarView.is_in_interaction_rect(
                    like_button):
            print("Swiping down a bit to see if is liked")
            device.swipe(DeviceFacade.Direction.TOP)

        # If double click didn't work, set like by icon click
        try:
            # Click only button which is under the action bar and above the tab bar.
            # It fixes bugs with accidental back / home clicks.
            for like_button in device.find(
                    resourceId=f'{device.app_id}:id/row_feed_button_like',
                    className='android.widget.ImageView',
                    selected=False):
                if ActionBarView.is_in_interaction_rect(like_button):
                    print("Double click didn't work, click on icon.")
                    like_button.click()
                    sleeper.random_sleep()
                    break
        except DeviceFacade.JsonRpcError:
            print("Double click worked successfully.")

        softban_indicator.detect_action_blocked_dialog(device)
        on_like()

    if to_comment:
        _comment(device, my_username, comments_list, on_comment)

    print("Back to profile")
    device.back()
    return True
예제 #9
0
def do_unfollow(device, my_username, username, storage, check_if_is_follower, username_view, follow_status_button_view, on_action):
    """
    :return: whether unfollow was successful
    """
    need_to_go_back_to_list = True
    unfollow_from_list_chance = randint(1, 100)

    if follow_status_button_view is not None and not check_if_is_follower and unfollow_from_list_chance > 50:
        # We can unfollow directly here instead of getting inside to profile
        need_to_go_back_to_list = False
        print("Unfollowing a profile directly from the following list.")
        follow_status_button_view.click()
    else:
        print("Unfollowing a profile from their profile page.")
        username_view.click()
        on_action(GetProfileAction(user=username))
        sleeper.random_sleep()
        if_profile_empty = softban_indicator.detect_empty_profile(device)

        if if_profile_empty:
            print("Back to the followings list.")
            device.back()
            return False

        if check_if_is_follower:
            if _check_is_follower(device, username, my_username):
                print("Skip @" + username + ". This user is following you.")
                storage.update_follow_status(username, is_follow_me=True, do_i_follow_him=True)
                print("Back to the followings list.")
                device.back()
                return False
            storage.update_follow_status(username, is_follow_me=False, do_i_follow_him=True)

        unfollow_button = device.find(classNameMatches=TEXTVIEW_OR_BUTTON_REGEX,
                                      clickable=True,
                                      text='Following')
        if not unfollow_button.exists():
            print(COLOR_FAIL + "Cannot find Following button. Maybe not English language is set?" + COLOR_ENDC)
            save_crash(device)
            switch_to_english(device)
            raise LanguageChangedException()

        print(f"Unfollowing @{username}...")
        unfollow_button.click()
        sleeper.random_sleep()

    unfollow_confirmed = False
    dialog_view = DialogView(device)
    if dialog_view.is_visible():
        print("Confirming unfollow...")
        unfollow_confirmed = dialog_view.click_unfollow()

    if unfollow_confirmed:
        try:
            # If the account is private, another popup is shown
            confirm_button = device.find(classNameMatches=TEXTVIEW_OR_BUTTON_REGEX,
                                         clickable=True,
                                         text='Unfollow')
            # If it exists, click unfollow
            if confirm_button.exists():
                print("Private account, confirming unfollow...")
                confirm_button.click()
            # Either way, sleep
        except:
            pass
        finally:
            sleeper.random_sleep()
    else:
        softban_indicator.detect_action_blocked_dialog(device)

    if need_to_go_back_to_list:
        print("Back to the followings list.")
        device.back()

    return True