def iteration_callback(following_name, following_name_view): """ :return: True to continue unfollowing after given user, False to stop """ print("Unfollow @" + following_name) is_unfollow_limit_reached, unfollow_reached_source_limit, unfollow_reached_session_limit = \ is_limit_reached(UnfollowAction(user=following_name), session_state) if not process_limits( is_unfollow_limit_reached, unfollow_reached_session_limit, unfollow_reached_source_limit, action_status, "Unfollowing"): return False is_get_profile_limit_reached, get_profile_reached_source_limit, get_profile_reached_session_limit = \ is_limit_reached(GetProfileAction(user=following_name), 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 check_if_is_follower = unfollow_restriction == UnfollowRestriction.FOLLOWED_BY_SCRIPT_NON_FOLLOWERS unfollowed = do_unfollow(device, following_name, session_state.my_username, check_if_is_follower, on_action) if unfollowed: storage.add_interacted_user(following_name, unfollowed=True) on_action(UnfollowAction(user=following_name)) return True
def iteration_callback(following_name, following_name_view, follow_status_button_view): """ :return: True to continue unfollowing after given user, False to stop """ print("Running Unfollow-action on @" + following_name) is_unfollow_limit_reached, unfollow_reached_source_limit, unfollow_reached_session_limit = \ is_limit_reached(UnfollowAction(user=following_name), session_state) if not process_limits(is_unfollow_limit_reached, unfollow_reached_session_limit, unfollow_reached_source_limit, action_status, "Unfollowing"): return False is_get_profile_limit_reached, get_profile_reached_source_limit, get_profile_reached_session_limit = \ is_limit_reached(GetProfileAction(user=following_name), 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 check_if_is_follower = unfollow_restriction == UnfollowRestriction.FOLLOWED_BY_SCRIPT_NON_FOLLOWERS or \ unfollow_restriction == UnfollowRestriction.ANY_NON_FOLLOWERS unfollowed = do_unfollow(device, session_state.my_username, following_name, storage, check_if_is_follower, following_name_view, follow_status_button_view, on_action) if unfollowed: storage.add_interacted_user(following_name, unfollowed=True) on_action(UnfollowAction(user=following_name)) print(COLOR_OKGREEN + f"Unfollowed @{following_name}" + COLOR_ENDC) print_short_unfollow_report(session_state) return True
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 search_for(device, username=None, hashtag=None, on_action=None): navigate(device, Tabs.SEARCH) search_edit_text = device.find( resourceId='com.instagram.android:id/action_bar_search_edit_text', className='android.widget.EditText') search_edit_text.click() if username is not None: print("Open user @" + username) search_edit_text.set_text(username) username_view = device.find( resourceId='com.instagram.android:id/row_search_user_username', className='android.widget.TextView', text=username) sleeper.random_sleep() if not username_view.exists(): print_timeless(COLOR_FAIL + "Cannot find user @" + username + ", abort." + COLOR_ENDC) return False username_view.click() if on_action is not None: on_action(GetProfileAction(user=username)) return True if hashtag is not None: print("Open hashtag #" + hashtag) tab_layout = device.find( resourceId='com.instagram.android:id/fixed_tabbar_tabs_container', className='android.widget.LinearLayout') if not tab_layout.exists(): print(COLOR_FAIL + "Cannot find tabs." + COLOR_ENDC) return False tab_layout.child(index=2).click() search_edit_text.set_text(hashtag) hashtag_view = device.find( resourceId='com.instagram.android:id/row_hashtag_textview_tag_name', className='android.widget.TextView', text=f"#{hashtag}") sleeper.random_sleep() if not hashtag_view.exists(): print_timeless(COLOR_FAIL + "Cannot find hashtag #" + hashtag + ", abort." + COLOR_ENDC) return False hashtag_view.click() return True return False
def navigate_to_username(self, username, on_action): print_debug("Navigate to profile @" + username) search_edit_text = self._get_search_edit_text() search_edit_text.click() search_edit_text.set_text(username) username_view = self._get_username_row(username) if not username_view.exists(): print(COLOR_FAIL + "Cannot find user @" + username + ", abort." + COLOR_ENDC) return None username_view.click() on_action(GetProfileAction(user=username)) return ProfileView(self.device, is_own_profile=False)
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 interact_with_follower(follower_name, follower_name_view): is_interact_limit_reached, interact_reached_source_limit, interact_reached_session_limit = \ is_limit_reached(InteractAction(source=username, user=follower_name, 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=follower_name), 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 print("@" + follower_name + ": interact") follower_name_view.click() on_action(GetProfileAction(user=follower_name)) sleeper.random_sleep() is_profile_empty = softban_indicator.detect_empty_profile(device) if is_profile_empty: print("Back to followers list") device.back() return True follower_profile_view = ProfileView(device, follower_name == session_state.my_username) if is_passed_filters is not None: if not is_passed_filters(device, follower_name, reset=False): storage.add_filtered_user(follower_name) # Continue to next follower print("Back to profiles list") device.back() return True is_like_limit_reached, like_reached_source_limit, like_reached_session_limit = \ is_limit_reached(LikeAction(source=username, user=follower_name), session_state) is_follow_limit_reached, follow_reached_source_limit, follow_reached_session_limit = \ is_limit_reached(FollowAction(source=username, user=follower_name), session_state) is_watch_limit_reached, watch_reached_source_limit, watch_reached_session_limit = \ is_limit_reached(StoryWatchAction(user=follower_name), session_state) is_private = follower_profile_view.is_private_account() if is_private: print("@" + follower_name + ": Private account - images wont be liked.") do_have_stories = follower_profile_view.is_story_available() if not do_have_stories: print("@" + follower_name + ": 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 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(follower_name) == FollowingStatus.NONE and follow_percentage > 0 can_watch = (not is_watch_limit_reached) and do_have_stories and stories_value > 0 can_interact = can_like or can_follow or can_watch if not can_interact: print("@" + follower_name + ": Cant be interacted (due to limits / already followed). Skip.") storage.add_interacted_user(follower_name, followed=False, source=f"@{username}", interaction_type=instructions.value, provider=Provider.INTERACTION) on_action(InteractAction(source=username, user=follower_name, succeed=False)) else: print_interaction_types(follower_name, can_like, can_follow, can_watch) interaction_strategy = InteractionStrategy(do_like=can_like, do_follow=can_follow, do_story_watch=can_watch, likes_count=likes_value, follow_percentage=follow_percentage, like_percentage=like_percentage, stories_count=stories_value) is_liked, is_followed, is_watch = interaction(username=follower_name, interaction_strategy=interaction_strategy) if is_liked or is_followed or is_watch: storage.add_interacted_user(follower_name, followed=is_followed, source=f"@{username}", interaction_type=instructions.value, provider=Provider.INTERACTION) on_action(InteractAction(source=username, user=follower_name, succeed=True)) print_short_report(username, session_state) else: storage.add_interacted_user(follower_name, followed=False, source=f"@{username}", interaction_type=instructions.value, provider=Provider.INTERACTION) on_action(InteractAction(source=username, user=follower_name, 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_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 profiles list") device.back() return can_continue
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 interact_with_target(target_name, target_name_view): is_interact_limit_reached, interact_reached_source_limit, interact_reached_session_limit = \ is_limit_reached(InteractAction(source=target_name, user=target_name, succeed=True), session_state) if not process_limits( is_interact_limit_reached, interact_reached_session_limit, interact_reached_source_limit, action_status, "Interaction"): return is_get_profile_limit_reached, get_profile_reached_source_limit, get_profile_reached_session_limit = \ is_limit_reached(GetProfileAction(user=target_name), 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 print("@" + target_name + ": interact") if is_passed_filters is not None: if not is_all_filters_satisfied: should_continue, _ = is_passed_filters(device, target_name, reset=False) if not should_continue: storage.add_filtered_user(target_name) print("Moving to next target") return is_like_limit_reached, like_reached_source_limit, like_reached_session_limit = \ is_limit_reached(LikeAction(source=target_name, user=target_name), session_state) is_follow_limit_reached, follow_reached_source_limit, follow_reached_session_limit = \ is_limit_reached(FollowAction(source=target_name, user=target_name), session_state) is_watch_limit_reached, watch_reached_source_limit, watch_reached_session_limit = \ is_limit_reached(StoryWatchAction(user=target_name), session_state) is_comment_limit_reached, comment_reached_source_limit, comment_reached_session_limit = \ is_limit_reached(CommentAction(source=target_name, user=target_name, comment=""), session_state) is_private = is_private_account(device) if is_private: print("@" + target_name + ": Private account - images wont be liked.") do_have_stories = do_have_story(device) if not do_have_stories: print("@" + target_name + ": 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( target_name) == 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( "@" + target_name + ": Cant be interacted (due to limits / already followed). Skip." ) storage.add_interacted_user(target_name, followed=False, provider=provider) on_action( InteractAction(source=target_name, user=target_name, succeed=False)) else: print_interaction_types(target_name, 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=target_name, interaction_strategy=interaction_strategy) if is_liked or is_followed or is_watch or is_commented: storage.add_interacted_user(target_name, followed=is_followed, provider=provider) on_action( InteractAction(source=target_name, user=target_name, succeed=True)) print_short_report(target_name, session_state) else: storage.add_interacted_user(target_name, followed=False, provider=provider) on_action( InteractAction(source=target_name, user=target_name, succeed=False)) 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): 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): action_status.set_limit(ActionState.SESSION_LIMIT_REACHED) print("Moving to next target") return
def interact_with_liker(liker_username, liker_username_view): is_interact_limit_reached, interact_reached_source_limit, interact_reached_session_limit = \ is_limit_reached(InteractAction(source=interaction_source, 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 print("@" + liker_username + ": interact") liker_username_view.click() on_action(GetProfileAction(user=liker_username)) if is_passed_filters is not None: if not is_passed_filters(device, liker_username): # Continue to next follower print("Back to followers list") device.back() return True is_like_limit_reached, like_reached_source_limit, like_reached_session_limit = \ is_limit_reached(LikeAction(source=interaction_source, user=liker_username), session_state) is_follow_limit_reached, follow_reached_source_limit, follow_reached_session_limit = \ is_limit_reached(FollowAction(source=interaction_source, user=liker_username), session_state) is_watch_limit_reached, watch_reached_source_limit, watch_reached_session_limit = \ is_limit_reached(StoryWatchAction(user=liker_username), session_state) is_private = is_private_account(device) if is_private: 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.") 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_interact = can_like or can_follow if not can_interact: print( "@" + liker_username + ": Cant be interacted (due to limits / already followed). Skip." ) storage.add_interacted_user(liker_username, followed=False) on_action( InteractAction(source=interaction_source, user=liker_username, succeed=False)) else: print_interaction_types(liker_username, can_like, can_follow, can_watch) interaction_strategy = InteractionStrategy( do_like=can_like, do_follow=can_follow, do_story_watch=can_watch, likes_count=likes_value, follow_percentage=follow_percentage, stories_count=stories_value) is_liked, is_followed, is_watch = interaction( username=liker_username, interaction_strategy=interaction_strategy) if is_liked or is_followed or is_watch: storage.add_interacted_user(liker_username, followed=is_followed) on_action( InteractAction(source=interaction_source, user=liker_username, succeed=True)) print_short_report(interaction_source, session_state) else: storage.add_interacted_user(liker_username, followed=False) on_action( InteractAction(source=interaction_source, user=liker_username, succeed=False)) can_continue = True if is_like_limit_reached and is_follow_limit_reached and is_watch_limit_reached: # If one of the limits reached for source-limit, move to next source if like_reached_source_limit is not None or \ follow_reached_source_limit is not None or \ watch_reached_source_limit is not 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 \ follow_reached_session_limit is not None and \ watch_reached_session_limit is not None: can_continue = False action_status.set_limit(ActionState.SESSION_LIMIT_REACHED) print("Back to followers list") device.back() return can_continue
def interact_with_liker(liker_username, liker_username_view): is_interact_limit_reached, interact_reached_source_limit, interact_reached_session_limit = \ is_limit_reached(InteractAction(source=interaction_source, 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 print("@" + liker_username + ": interact") liker_username_view.click() on_action(GetProfileAction(user=liker_username)) if is_passed_filters is not None: if not is_passed_filters(device, liker_username): # Continue to next follower print("Back to followers list") device.back() return True is_like_limit_reached, like_reached_source_limit, like_reached_session_limit = \ is_limit_reached(LikeAction(source=interaction_source, user=liker_username), session_state) is_follow_limit_reached, follow_reached_source_limit, follow_reached_session_limit = \ is_limit_reached(FollowAction(source=interaction_source, user=liker_username), session_state) is_private = is_private_account(device) if is_private: print("@" + liker_username + ": Private account - images wont be liked.") can_like = not is_like_limit_reached and not is_private can_follow = ( not is_follow_limit_reached) and storage.get_following_status( liker_username) == FollowingStatus.NONE can_interact = can_like or can_follow if not can_interact: print( "@" + liker_username + ": Cant be interacted (due to limits / already followed). Skip." ) else: print("@" + liker_username + "interaction: going to {}{}{}.".format( "like" if can_like else "", " and " if can_like and can_follow else "", "follow" if can_follow else "")) interaction_strategy = InteractionStrategy( do_like=can_like, do_follow=can_follow, likes_count=likes_count, follow_percentage=follow_percentage) is_liked, is_followed = interaction( username=liker_username, interaction_strategy=interaction_strategy) if is_liked or is_followed: storage.add_interacted_user(liker_username, followed=is_followed) on_action( InteractAction(source=interaction_source, user=liker_username, succeed=True)) else: on_action( InteractAction(source=interaction_source, user=liker_username, succeed=False)) can_continue = True if is_like_limit_reached and is_follow_limit_reached: # If ont of the limits reached for source-limit, move to next source if like_reached_source_limit is not None or follow_reached_source_limit is not None: can_continue = False action_status.set_limit(ActionState.SOURCE_LIMIT_REACHED) # If both of the limits reached for session-limit, finish the session if like_reached_session_limit is not None and follow_reached_session_limit is not None: can_continue = False action_status.set_limit(ActionState.SESSION_LIMIT_REACHED) print("Back to followers list") device.back() return can_continue
def interact_with_follower(follower_name, follower_name_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=username, source_type=source_type, user=follower_name, 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=follower_name), 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 @{follower_name}") should_continue, is_all_filters_satisfied = is_passed_filters( device, follower_name, reset=True, filters_tags=['BEFORE_PROFILE_CLICK']) if not should_continue: on_action(FilterAction(user=follower_name)) 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("@" + follower_name + ": interact") follower_name_view.click() on_action(GetProfileAction(user=follower_name)) post_count = None followers_count = None following_count = None post_count_el = device.find( resourceId= 'com.instagram.android:id/row_profile_header_textview_post_count', className='android.widget.TextView') if post_count_el.exists(): post_count = to_int(post_count_el.get_text()) followers_count_el = device.find( resourceId= 'com.instagram.android:id/row_profile_header_textview_followers_count', className='android.widget.TextView') if followers_count_el.exists(): followers_count = to_int(followers_count_el.get_text()) following_count_el = device.find( resourceId= 'com.instagram.android:id/row_profile_header_textview_following_count', className='android.widget.TextView') if following_count_el.exists(): following_count = to_int(following_count_el.get_text()) print("@%s (PC=%s ERS=%s ING=%s): interact" % (follower_name, post_count, followers_count, following_count)) with open('filters.json') as json_file: filterz = json.load(json_file) json_file.close() skip = False if post_count and post_count < filterz['min_posts']: skip = True print('Skip because of %s < min_posts' % post_count) if not skip and followers_count and followers_count < filterz[ 'min_followers']: skip = True print('Skip because of %s < min_followers' % followers_count) if not skip and followers_count and followers_count > filterz[ 'max_followers']: skip = True print('Skip because of %s > max_followers' % followers_count) if not skip and followers_count and following_count and followers_count / ( following_count + 1) < filterz['min_potency_ratio']: skip = True print('Skip because of %s < min_potency_ratio' % (followers_count / (following_count + 1))) if not skip and followers_count and following_count and followers_count / ( following_count + 1) > filterz['max_potency_ratio']: skip = True print('Skip because of %s > max_potency_ratio' % (followers_count / (following_count + 1))) if not skip and not filterz[ 'follow_private_or_empty'] and is_private_account(device): skip = True print('Skipping private account') if skip: on_action(FilterAction(user=follower_name)) # Continue to next follower device.back() return True sleeper.random_sleep() is_profile_empty = softban_indicator.detect_empty_profile(device) if is_profile_empty: print("Back to followers list") device.back() return True follower_profile_view = ProfileView( device, follower_name == session_state.my_username) if is_passed_filters is not None: if not is_all_filters_satisfied: should_continue, _ = is_passed_filters(device, follower_name, reset=False) if not should_continue: on_action(FilterAction(user=follower_name)) # Continue to next follower print("Back to profiles list") device.back() return True is_like_limit_reached, like_reached_source_limit, like_reached_session_limit = \ is_limit_reached(LikeAction(source_name=username, source_type=source_type, user=follower_name), session_state) is_follow_limit_reached, follow_reached_source_limit, follow_reached_session_limit = \ is_limit_reached(FollowAction(source_name=username, source_type=source_type, user=follower_name), session_state) is_watch_limit_reached, watch_reached_source_limit, watch_reached_session_limit = \ is_limit_reached(StoryWatchAction(source_name=username, source_type=source_type,user=follower_name), session_state) is_comment_limit_reached, comment_reached_source_limit, comment_reached_session_limit = \ is_limit_reached(CommentAction(source_name=username, source_type=source_type, user=follower_name, comment=""), session_state) is_private = follower_profile_view.is_private_account() if is_private: if is_passed_filters is None: print(COLOR_OKGREEN + "@" + follower_name + " has private account, won't interact." + COLOR_ENDC) on_action(FilterAction(user=follower_name)) on_action( InteractAction(source_name=username, source_type=source_type, user=follower_name, succeed=False)) print("Back to profiles list") device.back() return True print("@" + follower_name + ": Private account - images wont be liked.") do_have_stories = follower_profile_view.is_story_available() if not do_have_stories: print("@" + follower_name + ": 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( follower_name) == 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( "@" + follower_name + ": Cant be interacted (due to limits / already followed). Skip." ) on_action( InteractAction(source_name=username, source_type=source_type, user=follower_name, succeed=False)) else: print_interaction_types(follower_name, 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=follower_name, interaction_strategy=interaction_strategy) if is_liked or is_followed or is_watch or is_commented: on_action( InteractAction(source_name=username, source_type=source_type, user=follower_name, succeed=True)) print_short_report(f"@{username}", session_state) else: on_action( InteractAction(source_name=username, source_type=source_type, user=follower_name, 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 profiles list") device.back() return can_continue
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