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()
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
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
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
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()
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
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
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
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