def wrapper(*args, **kwargs): session_state = sessions[-1] try: func(*args, **kwargs) except KeyboardInterrupt: close_instagram(device_id) logger.info( f"-------- FINISH: {datetime.now().time()} --------", extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"}, ) print_full_report(sessions) sessions.persist(directory=session_state.my_username) sys.exit(0) except (DeviceFacade.JsonRpcError, IndexError, HTTPException, timeout): logger.error(traceback.format_exc()) save_crash(device) logger.info("No idea what it was. Let's try again.") # Hack for the case when IGTV was accidentally opened close_instagram(device_id) random_sleep() open_instagram(device_id) TabBarView(device).navigateToProfile() except LanguageNotEnglishException: logger.info( "Language was changed. We'll have to start from the beginning." ) TabBarView(device).navigateToProfile() except Exception as e: save_crash(device) close_instagram(device_id) print_full_report(sessions) sessions.persist(directory=session_state.my_username) raise e
def open_user_followers(self, device, username): if username is None: logger.info("Open your followers") profile_view = TabBarView(device).navigateToProfile() profile_view.navigateToFollowers() else: search_view = TabBarView(device).navigateToSearch() profile_view = search_view.navigateToUsername(username) random_sleep() if not profile_view: return False logger.info(f"Open @{username} followers") profile_view.navigateToFollowers() return True
def handle_hashtag( self, device, hashtag, likes_count, follow_percentage, follow_limit, storage, profile_filter, on_like, on_interaction, ): interaction = partial( interact_with_user, my_username=self.session_state.my_username, likes_count=likes_count, follow_percentage=follow_percentage, on_like=on_like, profile_filter=profile_filter, ) is_follow_limit_reached = partial( is_follow_limit_reached_for_source, follow_limit=follow_limit, source=hashtag, session_state=self.session_state, ) search_view = TabBarView(device).navigateToSearch() random_sleep() if not search_view.navigateToHashtag(hashtag): return logger.info("Opening the first result") first_result_view = device.find( resourceId="com.instagram.android:id/recycler_view", className="androidx.recyclerview.widget.RecyclerView", ) first_result_view.child(index=3).click() random_sleep() posts_list_view = device.find( resourceId="android:id/list", className="androidx.recyclerview.widget.RecyclerView", ) posts_end_detector = ScrollEndDetector(repeats_to_end=2) while True: if not self.open_likers(device): logger.info( "No likes, let's scroll down.", extra={"color": f"{Fore.GREEN}"} ) posts_list_view.scroll(DeviceFacade.Direction.BOTTOM) continue logger.info("List of likers is opened.") posts_end_detector.notify_new_page() random_sleep() likes_list_view = device.find( resourceId="android:id/list", className="android.widget.ListView" ) prev_screen_iterated_likers = [] while True: logger.info("Iterate over visible likers.") screen_iterated_likers = [] try: for item in device.find( resourceId="com.instagram.android:id/row_user_container_base", className="android.widget.LinearLayout", ): username_view = item.child( resourceId="com.instagram.android:id/row_user_primary_name", className="android.widget.TextView", ) if not username_view.exists(quick=True): logger.info( "Next item not found: probably reached end of the screen.", extra={"color": f"{Fore.GREEN}"}, ) break username = username_view.get_text() screen_iterated_likers.append(username) posts_end_detector.notify_username_iterated(username) if storage.is_user_in_blacklist(username): logger.info(f"@{username} is in blacklist. Skip.") continue elif storage.check_user_was_interacted(username): logger.info(f"@{username}: already interacted. Skip.") continue else: logger.info(f"@{username}: interact") username_view.click() can_follow = ( not is_follow_limit_reached() and storage.get_following_status(username) == FollowingStatus.NONE ) interaction_succeed, followed = interaction( device, username=username, can_follow=can_follow ) storage.add_interacted_user(username, followed=followed) can_continue = on_interaction( succeed=interaction_succeed, followed=followed ) if not can_continue: return logger.info("Back to likers list") device.back() random_sleep() except IndexError: logger.info( "Cannot get next item: probably reached end of the screen.", extra={"color": f"{Fore.GREEN}"}, ) if screen_iterated_likers == prev_screen_iterated_likers: logger.info( "Iterated exactly the same likers twice, finish.", extra={"color": f"{Fore.GREEN}"}, ) logger.info(f"Back to #{hashtag}") device.back() break prev_screen_iterated_likers.clear() prev_screen_iterated_likers += screen_iterated_likers logger.info("Need to scroll now", extra={"color": f"{Fore.GREEN}"}) likes_list_view.scroll(DeviceFacade.Direction.BOTTOM) if posts_end_detector.is_the_end(): break else: posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
def handle_hashtag( self, device, hashtag, likes_count, stories_count, stories_percentage, follow_percentage, follow_limit, current_job, storage, profile_filter, on_like, on_watch, on_interaction, ): interaction = partial( interact_with_user, my_username=self.session_state.my_username, likes_count=likes_count, stories_count=stories_count, stories_percentage=stories_percentage, follow_percentage=follow_percentage, on_like=on_like, on_watch=on_watch, profile_filter=profile_filter, args=self.args, session_state=self.session_state, current_mode=self.current_mode, ) is_follow_limit_reached = partial( is_follow_limit_reached_for_source, follow_limit=follow_limit, source=hashtag, session_state=self.session_state, ) search_view = TabBarView(device).navigateToSearch() if not search_view.navigateToHashtag(hashtag): return if current_job == "hashtag-likers-recent": logger.info("Switching to Recent tab") HashTagView(device)._getRecentTab().click() random_sleep(5, 10) if HashTagView(device)._check_if_no_posts(): HashTagView(device)._reload_page() random_sleep(4, 8) logger.info("Opening the first result") result_view = HashTagView(device)._getRecyclerView() HashTagView(device)._getFistImageView(result_view).click() random_sleep() skipped_list_limit = get_value(self.args.skipped_list_limit, None, 15) skipped_fling_limit = get_value(self.args.fling_when_skipped, None, 0) posts_end_detector = ScrollEndDetector( repeats_to_end=2, skipped_list_limit=skipped_list_limit, skipped_fling_limit=skipped_fling_limit, ) post_description = "" nr_same_post = 0 nr_same_posts_max = 3 while True: likers_container_exists = PostsViewList(device)._find_likers_container() has_one_liker_or_none = PostsViewList( device )._check_if_only_one_liker_or_none() flag, post_description = PostsViewList(device)._check_if_last_post( post_description ) if flag: nr_same_post += 1 logger.info( f"Warning: {nr_same_post}/{nr_same_posts_max} repeated posts." ) if nr_same_post == nr_same_posts_max: logger.info( f"Scrolled through {nr_same_posts_max} posts with same description and author. Finish." ) break else: nr_same_post = 0 if likers_container_exists and not has_one_liker_or_none: PostsViewList(device).open_likers_container() else: PostsViewList(device).swipe_to_fit_posts(SwipeTo.NEXT_POST) continue posts_end_detector.notify_new_page() random_sleep() likes_list_view = OpenedPostView(device)._getListViewLikers() prev_screen_iterated_likers = [] while True: logger.info("Iterate over visible likers.") screen_iterated_likers = [] opened = False try: for item in OpenedPostView(device)._getUserCountainer(): username_view = OpenedPostView(device)._getUserName(item) if not username_view.exists(quick=True): logger.info( "Next item not found: probably reached end of the screen.", extra={"color": f"{Fore.GREEN}"}, ) break username = username_view.get_text() profile_interact = profile_filter.check_profile_from_list( device, item, username ) screen_iterated_likers.append(username) posts_end_detector.notify_username_iterated(username) if not profile_interact: continue elif storage.is_user_in_blacklist(username): logger.info(f"@{username} is in blacklist. Skip.") continue elif storage.check_user_was_interacted(username): logger.info(f"@{username}: already interacted. Skip.") continue else: logger.info(f"@{username}: interact") username_view.click() can_follow = not is_follow_limit_reached() and ( storage.get_following_status(username) == FollowingStatus.NONE or storage.get_following_status(username) == FollowingStatus.NOT_IN_LIST ) interaction_succeed, followed = interaction( device, username=username, can_follow=can_follow ) storage.add_interacted_user(username, followed=followed) opened = True can_continue = on_interaction( succeed=interaction_succeed, followed=followed ) if not can_continue: return logger.info("Back to likers list.") device.back() random_sleep() except IndexError: logger.info( "Cannot get next item: probably reached end of the screen.", extra={"color": f"{Fore.GREEN}"}, ) break go_back = False if not opened: logger.info( "All likers skipped.", extra={"color": f"{Fore.GREEN}"}, ) posts_end_detector.notify_skipped_all() if posts_end_detector.is_skipped_limit_reached(): posts_end_detector.reset_skipped_all() device.back() PostsViewList(device).swipe_to_fit_posts(False) break if screen_iterated_likers == prev_screen_iterated_likers: logger.info( "Iterated exactly the same likers twice.", extra={"color": f"{Fore.GREEN}"}, ) go_back = True if go_back: prev_screen_iterated_likers.clear() prev_screen_iterated_likers += screen_iterated_likers logger.info( f"Back to {hashtag}'s posts list.", extra={"color": f"{Fore.GREEN}"}, ) device.back() logger.info("Going to the next post.") PostsViewList(device).swipe_to_fit_posts(SwipeTo.NEXT_POST) break if posts_end_detector.is_fling_limit_reached(): prev_screen_iterated_likers.clear() prev_screen_iterated_likers += screen_iterated_likers logger.info( "Reached fling limit. Fling to see other likers", extra={"color": f"{Fore.GREEN}"}, ) likes_list_view.fling(DeviceFacade.Direction.BOTTOM) else: prev_screen_iterated_likers.clear() prev_screen_iterated_likers += screen_iterated_likers logger.info( "Scroll to see other likers", extra={"color": f"{Fore.GREEN}"}, ) likes_list_view.scroll(DeviceFacade.Direction.BOTTOM) if posts_end_detector.is_the_end(): break
def wrapper(*args, **kwargs): session_state = sessions[-1] try: func(*args, **kwargs) except KeyboardInterrupt: try: # Catch Ctrl-C and ask if user wants to pause execution logger.info( "CTRL-C detected . . .", extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"}, ) logger.info( f"-------- PAUSED: {datetime.now().time()} --------", extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"}, ) logger.info( "NOTE: This is a rudimentary pause. It will restart the action, while retaining session data.", extra={"color": Style.BRIGHT}, ) logger.info( "Press RETURN to resume or CTRL-C again to Quit: ", extra={"color": Style.BRIGHT}, ) input("") logger.info( f"-------- RESUMING: {datetime.now().time()} --------", extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"}, ) TabBarView(device).navigateToProfile() except KeyboardInterrupt: close_instagram(device, screen_record) logger.info( f"-------- FINISH: {datetime.now().time()} --------", extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"}, ) print_full_report(sessions) sessions.persist(directory=session_state.my_username) sys.exit(0) except ( DeviceFacade.JsonRpcError, IndexError, HTTPException, timeout, UiObjectNotFoundErrorv2, ): logger.error(traceback.format_exc()) save_crash(device) logger.info("No idea what it was. Let's try again.") # Hack for the case when IGTV was accidentally opened close_instagram(device, screen_record) random_sleep() open_instagram(device, screen_record) TabBarView(device).navigateToProfile() except LanguageNotEnglishException: logger.info( "Language was changed. We'll have to start from the beginning." ) TabBarView(device).navigateToProfile() except Exception as e: logger.error(traceback.format_exc()) save_crash(device) close_instagram(device, screen_record) print_full_report(sessions) sessions.persist(directory=session_state.my_username) raise e
def run(): global device_id global first_run loaded = load_plugins() args = get_args() enabled = [] if not args: return dargs = vars(args) for k in loaded: if dargs[k.replace("-", "_")[2:]] != None: if k == "--interact": logger.warn( 'Using legacy argument "--interact". Please switch to new arguments as this will be deprecated in the near future.' ) if "#" in args.interact[0]: enabled.append("--hashtag-likers") args.hashtag_likers = args.interact else: enabled.append("--blogger-followers") args.blogger_followers = args.interact else: enabled.append(k) enabled = list(dict.fromkeys(enabled)) if len(enabled) < 1: logger.error("You have to specify one of the actions: " + ", ".join(loaded)) return if len(enabled) > 1: logger.error( "Running GramAddict with two or more actions is not supported yet." ) return device_id = args.device if not check_adb_connection(is_device_id_provided=(device_id is not None)): return logger.info("Instagram version: " + get_instagram_version(device_id)) device = create_device(device_id) if device is None: return while True: session_state = SessionState() session_state.args = args.__dict__ sessions.append(session_state) logger.info( "-------- START: " + str(session_state.startTime) + " --------", extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"}, ) if args.screen_sleep: screen_sleep(device_id, "on") # Turn on the device screen open_instagram(device_id) try: profileView = TabBarView(device).navigateToProfile() ( session_state.my_username, session_state.my_followers_count, session_state.my_following_count, ) = profileView.getProfileInfo() except Exception as e: logger.error(f"Exception: {e}") save_crash(device) switch_to_english(device) # Try again on the correct language profileView = TabBarView(device).navigateToProfile() ( session_state.my_username, session_state.my_followers_count, session_state.my_following_count, ) = profileView.getProfileInfo() if ( session_state.my_username == None or session_state.my_followers_count == None or session_state.my_following_count == None ): logger.critical( "Could not get one of the following from your profile: username, # of followers, # of followings. This is typically due to a soft ban. Review the crash screenshot to see if this is the case." ) logger.critical( f"Username: {session_state.my_username}, Followers: {session_state.my_followers_count}, Following: {session_state.my_following_count}" ) save_crash(device) exit(1) if first_run: try: update_log_file_name(session_state.my_username) except Exception as e: logger.error( f"Failed to update log file name. Will continue anyway. {e}" ) save_crash(device) report_string = f"Hello, @{session_state.my_username}! You have {session_state.my_followers_count} followers and {session_state.my_following_count} followings so far." logger.info(report_string, extra={"color": f"{Style.BRIGHT}"}) storage = Storage(session_state.my_username) loaded[enabled[0]].run(device, device_id, args, enabled, storage, sessions) close_instagram(device_id) session_state.finishTime = datetime.now() if args.screen_sleep: screen_sleep(device_id, "off") # Turn off the device screen logger.info( "-------- FINISH: " + str(session_state.finishTime) + " --------", extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"}, ) if args.repeat: print_full_report(sessions) repeat = get_value(args.repeat, "Sleep for {} minutes", 180) try: sleep(60 * repeat) except KeyboardInterrupt: print_full_report(sessions) sessions.persist(directory=session_state.my_username) sys.exit(0) else: break first_run = False print_full_report(sessions) sessions.persist(directory=session_state.my_username)
def run(): # Some plugins need config values without being passed # through. Because we do a weird config/argparse hybrid, # we need to load the configs in a weird way load_filter(configs) load_interaction(configs) load_utils(configs) load_views(configs) if not configs.args or not check_adb_connection(): return if len(configs.enabled) < 1: logger.error("You have to specify one of the actions: " + ", ".join(configs.actions)) return logger.info("Instagram version: " + get_instagram_version()) device = create_device(configs.device_id, configs.args.uia_version) if device is None: return while True: session_state = SessionState(configs) sessions.append(session_state) device.wake_up() logger.info( "-------- START: " + str(session_state.startTime) + " --------", extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"}, ) if not device.get_info()["screenOn"]: device.press_power() if device.is_screen_locked(): device.unlock() if device.is_screen_locked(): logger.error( "Can't unlock your screen. There may be a passcode on it. If you would like your screen to be turned on and unlocked automatically, please remove the passcode." ) exit(0) logger.info("Device screen on and unlocked.") open_instagram(device, configs.args.screen_record) try: profileView = TabBarView(device).navigateToProfile() random_sleep() if configs.args.username is not None: success = AccountView(device).changeToUsername( configs.args.username) if not success: logger.error( f"Not able to change to {configs.args.username}, abort!" ) device.back() break ( session_state.my_username, session_state.my_followers_count, session_state.my_following_count, ) = profileView.getProfileInfo() except Exception as e: logger.error(f"Exception: {e}") save_crash(device) switch_to_english(device) # Try again on the correct language profileView = TabBarView(device).navigateToProfile() random_sleep() ( session_state.my_username, session_state.my_followers_count, session_state.my_following_count, ) = profileView.getProfileInfo() if (session_state.my_username is None or session_state.my_followers_count is None or session_state.my_following_count is None): logger.critical( "Could not get one of the following from your profile: username, # of followers, # of followings. This is typically due to a soft ban. Review the crash screenshot to see if this is the case." ) logger.critical( f"Username: {session_state.my_username}, Followers: {session_state.my_followers_count}, Following: {session_state.my_following_count}" ) save_crash(device) exit(1) if not is_log_file_updated(): try: update_log_file_name(session_state.my_username) except Exception as e: logger.error( f"Failed to update log file name. Will continue anyway. {e}" ) save_crash(device) report_string = f"Hello, @{session_state.my_username}! You have {session_state.my_followers_count} followers and {session_state.my_following_count} followings so far." logger.info(report_string, extra={"color": f"{Style.BRIGHT}"}) storage = Storage(session_state.my_username) for plugin in configs.enabled: if not session_state.check_limit( configs.args, limit_type=session_state.Limit.ALL, output=False): logger.info(f"Current job: {plugin}", extra={"color": f"{Fore.BLUE}"}) if ProfileView( device).getUsername() != session_state.my_username: logger.debug("Not in your main profile.") TabBarView(device).navigateToProfile() configs.actions[plugin].run(device, configs, storage, sessions, plugin) else: logger.info( "Successful or Total Interactions limit reached. Ending session." ) break close_instagram(device, configs.args.screen_record) session_state.finishTime = datetime.now() if configs.args.screen_sleep: device.screen_off() logger.info("Screen turned off for sleeping time") logger.info( "-------- FINISH: " + str(session_state.finishTime) + " --------", extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"}, ) if configs.args.repeat: print_full_report(sessions) repeat = get_value(configs.args.repeat, "Sleep for {} minutes", 180) try: sleep(60 * repeat) except KeyboardInterrupt: print_full_report(sessions) sessions.persist(directory=session_state.my_username) exit(0) else: break print_full_report(sessions) sessions.persist(directory=session_state.my_username)
def handle_hashtag( self, device, hashtag, likes_count, stories_count, stories_percentage, follow_percentage, follow_limit, interact_percentage, current_job, storage, profile_filter, on_like, on_watch, on_interaction, ): interaction = partial( interact_with_user, my_username=self.session_state.my_username, likes_count=likes_count, stories_count=stories_count, stories_percentage=stories_percentage, follow_percentage=follow_percentage, on_like=on_like, on_watch=on_watch, profile_filter=profile_filter, args=self.args, session_state=self.session_state, current_mode=self.current_mode, ) is_follow_limit_reached = partial( is_follow_limit_reached_for_source, follow_limit=follow_limit, source=hashtag, session_state=self.session_state, ) search_view = TabBarView(device).navigateToSearch() if not search_view.navigateToHashtag(hashtag): return if current_job == "hashtag-posts-recent": logger.info("Switching to Recent tab") HashTagView(device)._getRecentTab().click() random_sleep(5, 10) if HashTagView(device)._check_if_no_posts(): UniversalActions(device)._reload_page() random_sleep(4, 8) logger.info("Opening the first result") result_view = HashTagView(device)._getRecyclerView() HashTagView(device)._getFistImageView(result_view).click() random_sleep() def interact(): can_follow = not is_follow_limit_reached() and ( storage.get_following_status(username) == FollowingStatus.NONE or storage.get_following_status(username) == FollowingStatus.NOT_IN_LIST ) interaction_succeed, followed = interaction( device, username=username, can_follow=can_follow ) storage.add_interacted_user(username, followed=followed) can_continue = on_interaction( succeed=interaction_succeed, followed=followed ) if not can_continue: return False else: return True def random_choice(): from random import randint random_number = randint(1, 100) if interact_percentage > random_number: return True else: return False post_description = "" nr_same_post = 0 nr_same_posts_max = 3 while True: flag, post_description = PostsViewList(device)._check_if_last_post( post_description ) if flag: nr_same_post += 1 logger.info( f"Warning: {nr_same_post}/{nr_same_posts_max} repeated posts." ) if nr_same_post == nr_same_posts_max: logger.info( f"Scrolled through {nr_same_posts_max} posts with same description and author. Finish." ) break else: nr_same_post = 0 if random_choice(): username = PostsViewList(device)._post_owner(Owner.GET_NAME)[:-3] if storage.is_user_in_blacklist(username): logger.info(f"@{username} is in blacklist. Skip.") elif storage.check_user_was_interacted(username): logger.info(f"@{username}: already interacted. Skip.") else: logger.info(f"@{username}: interact") PostsViewList(device)._like_in_post_view(LikeMode.DOUBLE_CLICK) detect_block(device) if not PostsViewList(device)._check_if_liked(): PostsViewList(device)._like_in_post_view(LikeMode.SINGLE_CLICK) detect_block(device) random_sleep(1, 2) if PostsViewList(device)._post_owner(Owner.OPEN): if not interact(): break device.back() PostsViewList(device).swipe_to_fit_posts(SwipeTo.HALF_PHOTO) random_sleep(0, 1) PostsViewList(device).swipe_to_fit_posts(SwipeTo.NEXT_POST) random_sleep() continue
def run(): global device_id loaded = load_plugins() args = get_args() enabled = [] if not args: return dargs = vars(args) for item in sys.argv[1:]: if item in loaded: if item != "--interact" and item != "--hashtag-likers": enabled.append(item) for k in loaded: if dargs[k.replace("-", "_")[2:]] != None: if k == "--interact": logger.warn( 'Using legacy argument "--interact". Please switch to new arguments as this will be deprecated in the near future.' ) for source in args.interact: if "@" in source: enabled.append("--blogger-followers") if type(args.blogger_followers) != list: args.blogger_followers = [source] else: args.blogger_followers.append(source) else: enabled.append("--hashtag-likers-top") if type(args.hashtag_likers_top) != list: args.hashtag_likers_top = [source] else: args.hashtag_likers_top.append(source) elif k == "--hashtag-likers": logger.warn( 'Using legacy argument "--hashtag-likers". Please switch to new arguments as this will be deprecated in the near future.' ) for source in args.hashtag_likers: enabled.append("--hashtag-likers-top") if type(args.hashtag_likers_top) != list: args.hashtag_likers_top = [source] else: args.hashtag_likers_top.append(source) enabled = list(dict.fromkeys(enabled)) if len(enabled) < 1: logger.error("You have to specify one of the actions: " + ", ".join(loaded)) return device_id = args.device if not check_adb_connection(is_device_id_provided=(device_id is not None)): return logger.info("Instagram version: " + get_instagram_version(device_id)) device = create_device(device_id) if device is None: return while True: session_state = SessionState() session_state.args = args.__dict__ sessions.append(session_state) device.wake_up() logger.info( "-------- START: " + str(session_state.startTime) + " --------", extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"}, ) if not DeviceFacade(device_id).get_info()["screenOn"]: DeviceFacade(device_id).press_power() if DeviceFacade(device_id).is_screen_locked(): DeviceFacade(device_id).unlock() if DeviceFacade(device_id).is_screen_locked(): logger.error( "Can't unlock your screen. There may be a passcode on it. If you would like your screen to be turned on and unlocked automatically, please remove the passcode." ) sys.exit() logger.info("Device screen on and unlocked.") open_instagram(device_id) try: profileView = TabBarView(device).navigateToProfile() random_sleep() ( session_state.my_username, session_state.my_followers_count, session_state.my_following_count, ) = profileView.getProfileInfo() except Exception as e: logger.error(f"Exception: {e}") save_crash(device) switch_to_english(device) # Try again on the correct language profileView = TabBarView(device).navigateToProfile() random_sleep() ( session_state.my_username, session_state.my_followers_count, session_state.my_following_count, ) = profileView.getProfileInfo() if (session_state.my_username == None or session_state.my_followers_count == None or session_state.my_following_count == None): logger.critical( "Could not get one of the following from your profile: username, # of followers, # of followings. This is typically due to a soft ban. Review the crash screenshot to see if this is the case." ) logger.critical( f"Username: {session_state.my_username}, Followers: {session_state.my_followers_count}, Following: {session_state.my_following_count}" ) save_crash(device) exit(1) if not is_log_file_updated(): try: update_log_file_name(session_state.my_username) except Exception as e: logger.error( f"Failed to update log file name. Will continue anyway. {e}" ) save_crash(device) report_string = f"Hello, @{session_state.my_username}! You have {session_state.my_followers_count} followers and {session_state.my_following_count} followings so far." logger.info(report_string, extra={"color": f"{Style.BRIGHT}"}) storage = Storage(session_state.my_username) for plugin in enabled: if not session_state.check_limit( args, limit_type=session_state.Limit.ALL, output=False): loaded[plugin].run(device, device_id, args, enabled, storage, sessions, plugin) else: logger.info( "Successful or Total Interactions limit reached. Ending session." ) break close_instagram(device_id) session_state.finishTime = datetime.now() if args.screen_sleep: DeviceFacade(device_id).screen_off() logger.info("Screen turned off for sleeping time") logger.info( "-------- FINISH: " + str(session_state.finishTime) + " --------", extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"}, ) if args.repeat: print_full_report(sessions) repeat = get_value(args.repeat, "Sleep for {} minutes", 180) try: sleep(60 * repeat) except KeyboardInterrupt: print_full_report(sessions) sessions.persist(directory=session_state.my_username) sys.exit(0) else: break print_full_report(sessions) sessions.persist(directory=session_state.my_username)
def handle_hashtag( self, device, hashtag, likes_count, stories_count, stories_percentage, follow_percentage, follow_limit, hashtag_likers_recent, # recent_tab, storage, profile_filter, on_like, on_watch, on_interaction, ): interaction = partial( interact_with_user, my_username=self.session_state.my_username, likes_count=likes_count, stories_count=stories_count, stories_percentage=stories_percentage, follow_percentage=follow_percentage, on_like=on_like, on_watch=on_watch, profile_filter=profile_filter, args=self.args, session_state=self.session_state, ) is_follow_limit_reached = partial( is_follow_limit_reached_for_source, follow_limit=follow_limit, source=hashtag, session_state=self.session_state, ) search_view = TabBarView(device).navigateToSearch() random_sleep() if not search_view.navigateToHashtag(hashtag): return if hashtag_likers_recent != None: logger.info("Switching to Recent tab") HashTagView(device)._getRecentTab().click() random_sleep() random_sleep( ) # wonder if it possible to check if everything is loaded instead of doing multiple random_sleep.. logger.info("Opening the first result") result_view = HashTagView(device)._getRecyclerView() HashTagView(device)._getFistImageView(result_view).click() random_sleep() posts_list_view = ProfileView(device)._getRecyclerView() posts_end_detector = ScrollEndDetector(repeats_to_end=2) first_post = True post_description = "" while True: if first_post: PostsViewList(device).swipe_to_fit_posts(True) first_post = False if not OpenedPostView(device).open_likers(): logger.info("No likes, let's scroll down.", extra={"color": f"{Fore.GREEN}"}) PostsViewList(device).swipe_to_fit_posts(False) flag, post_description = PostsViewList( device).check_if_last_post(post_description) if not flag: continue else: break logger.info("List of likers is opened.") posts_end_detector.notify_new_page() random_sleep() likes_list_view = OpenedPostView(device)._getListViewLikers() prev_screen_iterated_likers = [] while True: logger.info("Iterate over visible likers.") screen_iterated_likers = [] try: for item in OpenedPostView(device)._getUserCountainer(): username_view = OpenedPostView(device)._getUserName( item) if not username_view.exists(quick=True): logger.info( "Next item not found: probably reached end of the screen.", extra={"color": f"{Fore.GREEN}"}, ) break username = username_view.get_text() screen_iterated_likers.append(username) posts_end_detector.notify_username_iterated(username) if storage.is_user_in_blacklist(username): logger.info(f"@{username} is in blacklist. Skip.") continue elif storage.check_user_was_interacted(username): logger.info( f"@{username}: already interacted. Skip.") continue else: logger.info(f"@{username}: interact") username_view.click() can_follow = not is_follow_limit_reached() and ( storage.get_following_status(username) == FollowingStatus.NONE or storage.get_following_status(username) == FollowingStatus.NOT_IN_LIST) interaction_succeed, followed = interaction( device, username=username, can_follow=can_follow) storage.add_interacted_user(username, followed=followed) can_continue = on_interaction( succeed=interaction_succeed, followed=followed) if not can_continue: return logger.info("Back to likers list") device.back() random_sleep() except IndexError: logger.info( "Cannot get next item: probably reached end of the screen.", extra={"color": f"{Fore.GREEN}"}, ) if screen_iterated_likers == prev_screen_iterated_likers: logger.info( "Iterated exactly the same likers twice, finish.", extra={"color": f"{Fore.GREEN}"}, ) logger.info(f"Back to {hashtag}") device.back() break prev_screen_iterated_likers.clear() prev_screen_iterated_likers += screen_iterated_likers logger.info("Need to scroll now", extra={"color": f"{Fore.GREEN}"}) likes_list_view.scroll(DeviceFacade.Direction.BOTTOM) if posts_end_detector.is_the_end(): break else: posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
def handle_username_file( self, device, current_file, likes_count, stories_count, stories_percentage, follow_percentage, follow_limit, current_job, storage, profile_filter, on_like, on_watch, on_interaction, ): interaction = partial( interact_with_user, my_username=self.session_state.my_username, likes_count=likes_count, stories_count=stories_count, stories_percentage=stories_percentage, follow_percentage=follow_percentage, on_like=on_like, on_watch=on_watch, profile_filter=profile_filter, args=self.args, session_state=self.session_state, current_mode=self.current_mode, ) is_follow_limit_reached = partial( is_follow_limit_reached_for_source, follow_limit=follow_limit, source=current_file, session_state=self.session_state, ) need_to_refresh = True if path.isfile(current_file): with open(current_file, "r") as f: for line in f: username = line.strip() if username != "": if storage.is_user_in_blacklist(username): logger.info(f"@{username} is in blacklist. Skip.") continue elif storage.check_user_was_interacted(username): logger.info( f"@{username}: already interacted. Skip.") continue if need_to_refresh: search_view = TabBarView(device).navigateToSearch() random_sleep() profile_view = search_view.navigateToUsername( username, True, need_to_refresh) need_to_refresh = False if not profile_view: continue random_sleep() def interact(): can_follow = not is_follow_limit_reached() and ( storage.get_following_status(username) == FollowingStatus.NONE or storage.get_following_status(username) == FollowingStatus.NOT_IN_LIST) interaction_succeed, followed = interaction( device, username=username, can_follow=can_follow) storage.add_interacted_user(username, followed=followed) can_continue = on_interaction( succeed=interaction_succeed, followed=followed) if not can_continue: return False else: return True logger.info(f"@{username}: interact") if not interact(): break device.back() else: logger.info("Line in file is blank, skip.") remaining = f.readlines() if self.args.delete_interacted_users: with open(current_file, "w") as f: f.writelines(remaining) else: logger.warning(f"File {current_file} not found.") return logger.info(f"Interact with users in {current_file} complete.") device.back()