def extract_hashtag_profiles_and_interact(device, hashtag, instructions, iteration_callback, iteration_callback_pre_conditions, on_action): print("Interacting with #{0}-{1}".format(hashtag, instructions.value)) if not search_for(device, hashtag=hashtag, on_action=on_action): return # Switch to Recent tab if instructions == HashtagInteractionType.RECENT_LIKERS: print("Switching to Recent tab") tab_layout = device.find( resourceId='com.instagram.android:id/tab_layout', className='android.widget.LinearLayout') if tab_layout.exists(): tab_layout.child(index=1).click() else: print("Can't Find recent tab. Interacting with Popular.") sleeper.random_sleep() # Open first post print("Opening the first post") # Index 1 is reserved for hot Reels by this tag first_post_index = 2 if instructions == HashtagInteractionType.TOP_LIKERS else 1 first_post_view = device.find( resourceId='com.instagram.android:id/image_button', className='android.widget.ImageView', index=first_post_index) first_post_view.click() sleeper.random_sleep() posts_list_view = device.find( resourceId='android:id/list', className='androidx.recyclerview.widget.RecyclerView') posts_end_detector = ScrollEndDetector(repeats_to_end=2) def pre_conditions(liker_username, liker_username_view): posts_end_detector.notify_username_iterated(liker_username) return iteration_callback_pre_conditions(liker_username, liker_username_view) while True: if not open_likers(device): print(COLOR_OKGREEN + "No likes, let's scroll down." + COLOR_ENDC) posts_list_view.scroll(DeviceFacade.Direction.BOTTOM) continue print("List of likers is opened.") posts_end_detector.notify_new_page() sleeper.random_sleep() iterate_over_likers(device, iteration_callback, pre_conditions) if posts_end_detector.is_the_end(): break else: posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
def extract_hashtag_likers_and_interact(device, hashtag, iteration_callback, iteration_callback_pre_conditions, on_action): print("Interacting with #{0} recent-likers".format(hashtag)) if not search_for(device, hashtag=hashtag, on_action=on_action): return # Switch to Recent tab print("Switching to Recent tab") tab_layout = device.find(resourceId='com.instagram.android:id/tab_layout', className='android.widget.LinearLayout') tab_layout.child(index=1).click() random_sleep() # Open first post print("Opening the first post") first_post_view = device.find( resourceId='com.instagram.android:id/image_button', className='android.widget.ImageView', index=1) first_post_view.click() random_sleep() posts_list_view = device.find( resourceId='android:id/list', className='androidx.recyclerview.widget.RecyclerView') posts_end_detector = ScrollEndDetector(repeats_to_end=2) def pre_conditions(liker_username, liker_username_view): posts_end_detector.notify_username_iterated(liker_username) return iteration_callback_pre_conditions(liker_username, liker_username_view) while True: if not open_likers(device): print(COLOR_OKGREEN + "No likes, let's scroll down." + COLOR_ENDC) posts_list_view.scroll(DeviceFacade.Direction.BOTTOM) continue print("List of likers is opened.") posts_end_detector.notify_new_page() random_sleep() iterate_over_likers(device, iteration_callback, pre_conditions) if posts_end_detector.is_the_end(): break else: posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
def extract_hashtag_profiles_and_interact(device, hashtag, instructions, iteration_callback, iteration_callback_pre_conditions, on_action): print("Interacting with #{0}-{1}".format(hashtag, instructions.value)) if not search_for(device, hashtag=hashtag, on_action=on_action): return # Switch to Recent tab if instructions == HashtagInteractionType.RECENT_LIKERS: print("Switching to Recent tab") tab_layout = device.find(resourceId=f'{device.app_id}:id/tab_layout', className='android.widget.LinearLayout') if tab_layout.exists(): tab_layout.child(index=1).click() else: print("Can't Find recent tab. Interacting with Popular.") # Sleep longer because posts loading takes time sleeper.random_sleep(multiplier=2.0) # Open post posts_view_list = PostsGridView(device).open_random_post() if posts_view_list is None: return posts_end_detector = ScrollEndDetector(repeats_to_end=2) def pre_conditions(liker_username, liker_username_view): posts_end_detector.notify_username_iterated(liker_username) return iteration_callback_pre_conditions(liker_username, liker_username_view) while True: if not open_likers(device): print(COLOR_OKGREEN + "No likes, let's scroll down." + COLOR_ENDC) posts_view_list.scroll_down() continue print("List of likers is opened.") posts_end_detector.notify_new_page() sleeper.random_sleep() should_continue_using_source = iterate_over_likers(device, iteration_callback, pre_conditions) if not should_continue_using_source: break if posts_end_detector.is_the_end(): break else: posts_view_list.scroll_down()
def extract_place_likers_and_interact(device, place, instructions, navigate_to_feed, iteration_callback, iteration_callback_pre_conditions, on_action): print("Interacting with place-{0}-{1}".format(place, instructions.value)) # Open post posts_view_list = navigate_to_feed() if posts_view_list is None: return posts_end_detector = ScrollEndDetector(repeats_to_end=2) def pre_conditions(liker_username, liker_username_view): posts_end_detector.notify_username_iterated(liker_username) return iteration_callback_pre_conditions(liker_username, liker_username_view) no_likes_count = 0 while True: if not open_likers(device): no_likes_count += 1 print(COLOR_OKGREEN + "No likes, let's scroll down." + COLOR_ENDC) posts_view_list.scroll_down() if no_likes_count == 10: print( COLOR_FAIL + "Seen this message too many times. Lets restart the job." + COLOR_ENDC) raise RestartJobRequiredException continue no_likes_count = 0 print("List of likers is opened.") posts_end_detector.notify_new_page() sleeper.random_sleep() should_continue_using_source = iterate_over_likers( device, iteration_callback, pre_conditions) if not should_continue_using_source: break if posts_end_detector.is_the_end(): break else: posts_view_list.scroll_down()
def extract_hashtag_profiles_and_interact(device, hashtag, instructions, iteration_callback, iteration_callback_pre_conditions, on_action): print("Interacting with #{0}-{1}".format(hashtag, instructions.value)) if not search_for(device, hashtag=hashtag, on_action=on_action): return # Switch to Recent tab if instructions == HashtagInteractionType.RECENT_LIKERS: print("Switching to Recent tab") tab_layout = device.find(resourceId=f'{device.app_id}:id/tab_layout', className='android.widget.LinearLayout') if tab_layout.exists(): tab_layout.child(index=1).click() else: print("Can't Find recent tab. Interacting with Popular.") sleeper.random_sleep() # Open post # Scroll down several times to pick random post scroll_times = randint(0, 5) posts_grid = device.find( resourceId=f'{device.app_id}:id/recycler_view', className='androidx.recyclerview.widget.RecyclerView') print(f"Scroll down {scroll_times} times.") for _ in range(0, scroll_times): posts_grid.scroll(DeviceFacade.Direction.BOTTOM) sleeper.random_sleep() # Scan for available posts' coordinates available_posts_coords = [] print("Choosing a random post from those on the screen") for post_view in posts_grid.child( resourceId=f'{device.app_id}:id/image_button', className='android.widget.ImageView'): bounds = post_view.get_bounds() left = bounds["left"] top = bounds["top"] right = bounds["right"] bottom = bounds["bottom"] coords = (left + (right - left) / 2, top + (bottom - top) / 2) available_posts_coords.append(coords) if len(available_posts_coords) == 0: print(COLOR_FAIL + f"No posts for #{hashtag}. Abort." + COLOR_ENDC) return # Pick random post from available ones coords = random.choice(available_posts_coords) print(f"Open the post at {coords}") device.screen_click_by_coordinates(coords[0], coords[1]) sleeper.random_sleep() posts_list_view = device.find( resourceId='android:id/list', className='androidx.recyclerview.widget.RecyclerView') if not posts_list_view.exists(): print("Couldn't open a post, will try again.") device.screen_click_by_coordinates(coords[0], coords[1]) sleeper.random_sleep() posts_end_detector = ScrollEndDetector(repeats_to_end=2) def pre_conditions(liker_username, liker_username_view): posts_end_detector.notify_username_iterated(liker_username) return iteration_callback_pre_conditions(liker_username, liker_username_view) while True: if not open_likers(device): print(COLOR_OKGREEN + "No likes, let's scroll down." + COLOR_ENDC) posts_list_view.scroll(DeviceFacade.Direction.BOTTOM) continue print("List of likers is opened.") posts_end_detector.notify_new_page() sleeper.random_sleep() should_continue_using_source = iterate_over_likers( device, iteration_callback, pre_conditions) if not should_continue_using_source: break if posts_end_detector.is_the_end(): break else: posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)
def extract_place_profiles_and_interact(device, place, instructions, iteration_callback, iteration_callback_pre_conditions, on_action): print("Interacting with place-{0}-{1}".format(place, instructions.value)) if not search_for(device, place=place, on_action=on_action): return # Switch to Recent tab if instructions == PlaceInteractionType.RECENT_LIKERS: print("Switching to Recent tab") tab_layout = device.find(resourceId=f'{device.app_id}:id/tab_layout', className='android.widget.LinearLayout') if tab_layout.exists(): tab_layout.child(index=1).click() else: print("Can't Find recent tab. Interacting with Popular.") sleeper.random_sleep() # Open post first_post_index = 2 post_num = randint(first_post_index, 20) print(f"Opening post #{post_num}") post_view = device.find(resourceId=f'{device.app_id}:id/image_button', className='android.widget.ImageView', index=post_num) for _ in range(0, 10): if post_view.exists(quick=True): break print(f"Cannot find post #{post_num}. Swiping down a bit.") device.swipe(DeviceFacade.Direction.TOP) if not post_view.exists(quick=True): print(f"Cannot find post #{post_num} after 10 swipes. Aborting.") post_view.click() sleeper.random_sleep() posts_list_view = device.find( resourceId='android:id/list', className='androidx.recyclerview.widget.RecyclerView') posts_end_detector = ScrollEndDetector(repeats_to_end=2) def pre_conditions(liker_username, liker_username_view): posts_end_detector.notify_username_iterated(liker_username) return iteration_callback_pre_conditions(liker_username, liker_username_view) while True: if not open_likers(device): print(COLOR_OKGREEN + "No likes, let's scroll down." + COLOR_ENDC) posts_list_view.scroll(DeviceFacade.Direction.BOTTOM) continue print("List of likers is opened.") posts_end_detector.notify_new_page() sleeper.random_sleep() should_continue_using_source = iterate_over_likers( device, iteration_callback, pre_conditions) if not should_continue_using_source: break if posts_end_detector.is_the_end(): break else: posts_list_view.scroll(DeviceFacade.Direction.BOTTOM)