Skip to content

Commit

Permalink
- Change the way of getting followers & followings: no more internet …
Browse files Browse the repository at this point in the history
…requests

- Fix crash when trying to follow already followed user #50
- Fix attempt to interact with yourself when seeing you in blogger's followers list
  • Loading branch information
Alexander Mishchenko committed Jul 11, 2020
1 parent 23e6c92 commit 565603d
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 113 deletions.
136 changes: 69 additions & 67 deletions insomniac.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Since of v1.2.3 this script works on Python 3

import argparse
import random
import sys
import traceback
from datetime import timedelta
Expand All @@ -15,7 +16,9 @@
from src.action_get_my_username import get_my_username
from src.action_handle_blogger import handle_blogger
from src.action_unfollow import unfollow
from src.counters_parser import LanguageChangedException
from src.filter import Filter
from src.navigation import navigate, Tabs
from src.session_state import SessionState
from src.storage import Storage
from src.utils import *
Expand All @@ -25,6 +28,7 @@


def main():
random.seed()
colorama.init()
print_timeless(COLOR_HEADER + "Insomniac " + get_version() + "\n" + COLOR_ENDC)

Expand Down Expand Up @@ -130,43 +134,23 @@ def on_likes_limit_reached():
is_myself = blogger == session_state.my_username
print_timeless("")
print(COLOR_BOLD + "Handle @" + blogger + (is_myself and " (it\'s you)" or "") + COLOR_ENDC)
completed = False
on_interaction = partial(on_interaction, blogger=blogger)
while not completed and not state.is_job_completed:
try:
username = None
if not is_myself:
username = blogger
handle_blogger(device,
username,
likes_count,
follow_percentage,
storage,
profile_filter,
_on_like,
on_interaction)
completed = True
except KeyboardInterrupt:
close_instagram(device_id)
print_copyright(session_state.my_username)
print_timeless(COLOR_WARNING + "-------- FINISH: " + str(datetime.now().time()) + " --------"
+ COLOR_ENDC)
_print_report()
sys.exit(0)
except (uiautomator.JsonRPCError, IndexError, HTTPException, timeout):
print(COLOR_FAIL + traceback.format_exc() + COLOR_ENDC)
take_screenshot(device)
print("Try again for @" + blogger + " from the beginning")
# Hack for the case when IGTV was accidentally opened
close_instagram(device_id)
random_sleep()
open_instagram(device_id)
get_my_username(device)
except Exception as e:
take_screenshot(device)
close_instagram(device_id)
_print_report()
raise e

@_run_safely(device=device)
def job():
handle_blogger(device,
blogger,
session_state.my_username,
likes_count,
follow_percentage,
storage,
profile_filter,
_on_like,
on_interaction)
state.is_job_completed = True

while not state.is_job_completed:
job()


def _job_unfollow(device, count, storage, only_non_followers):
Expand All @@ -175,6 +159,7 @@ def __init__(self):
pass

unfollowed_count = 0
is_job_completed = False

state = State()
session_state = sessions[-1]
Expand All @@ -183,37 +168,19 @@ def on_unfollow():
state.unfollowed_count += 1
session_state.totalUnfollowed += 1

completed = False
while not completed and state.unfollowed_count < count:
try:
unfollow(device,
count - state.unfollowed_count,
on_unfollow,
storage,
only_non_followers,
session_state.my_username)
print("Unfollowed " + str(state.unfollowed_count) + ", finish.")
completed = True
except KeyboardInterrupt:
close_instagram(device_id)
print_copyright(session_state.my_username)
print_timeless(COLOR_WARNING + "-------- FINISH: " + str(datetime.now().time()) + " --------" + COLOR_ENDC)
_print_report()
sys.exit(0)
except (uiautomator.JsonRPCError, IndexError, HTTPException, timeout):
print(COLOR_FAIL + traceback.format_exc() + COLOR_ENDC)
take_screenshot(device)
print("Try unfollowing again, " + str(count - state.unfollowed_count) + " users left")
# Hack for the case when IGTV was accidentally opened
close_instagram(device_id)
random_sleep()
open_instagram(device_id)
get_my_username(device)
except Exception as e:
take_screenshot(device)
close_instagram(device_id)
_print_report()
raise e
@_run_safely(device=device)
def job():
unfollow(device,
count - state.unfollowed_count,
on_unfollow,
storage,
only_non_followers,
session_state.my_username)
print("Unfollowed " + str(state.unfollowed_count) + ", finish.")
state.is_job_completed = True

while not state.is_job_completed and state.unfollowed_count < count:
job()


def _parse_arguments():
Expand Down Expand Up @@ -356,6 +323,41 @@ def _print_report():
print_timeless(COLOR_WARNING + "Total unfollowed: " + str(total_unfollowed) + COLOR_ENDC)


def _run_safely(device):
def actual_decorator(func):
def wrapper(*args, **kwargs):
session_state = sessions[-1]
try:
func(*args, **kwargs)
except KeyboardInterrupt:
close_instagram(device_id)
print_copyright(session_state.my_username)
print_timeless(COLOR_WARNING + "-------- FINISH: " + str(datetime.now().time()) + " --------" +
COLOR_ENDC)
_print_report()
sys.exit(0)
except (uiautomator.JsonRPCError, IndexError, HTTPException, timeout):
print(COLOR_FAIL + traceback.format_exc() + COLOR_ENDC)
take_screenshot(device)
print("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)
navigate(device, Tabs.PROFILE)
except LanguageChangedException:
print_timeless("")
print("Language was changed. We'll have to start from the beginning.")
navigate(device, Tabs.PROFILE)
except Exception as e:
take_screenshot(device)
close_instagram(device_id)
_print_report()
raise e
return wrapper
return actual_decorator


@unique
class Mode(Enum):
INTERACT = 0
Expand Down
10 changes: 2 additions & 8 deletions src/action_get_my_username.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
from src.navigation import navigate, Tabs
from src.utils import *


def get_my_username(device):
print("Press profile")
tab_bar = device(resourceId='com.instagram.android:id/tab_bar', className='android.widget.LinearLayout')
profile_button = tab_bar.child(index=4)

# Two clicks to reset tab content
profile_button.click.wait()
profile_button.click.wait()

navigate(device, Tabs.PROFILE)
title_view = device(resourceId='com.instagram.android:id/title_view',
className='android.widget.TextView')
if title_view.exists:
Expand Down
27 changes: 18 additions & 9 deletions src/action_handle_blogger.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@

import uiautomator

from src.navigation import navigate, Tabs
from src.storage import FollowingStatus
from src.utils import *


def handle_blogger(device,
username,
my_username,
likes_count,
follow_percentage,
storage,
profile_filter,
on_like,
on_interaction):
is_myself = username is None
is_myself = username == my_username
interaction = partial(_interact_with_user,
my_username=my_username,
likes_count=likes_count,
follow_percentage=follow_percentage,
on_like=on_like,
Expand All @@ -36,13 +39,7 @@ def _open_user_followers(device, username):
className='android.widget.LinearLayout')
followers_button.click.wait()
else:
print("Press search")
tab_bar = device(resourceId='com.instagram.android:id/tab_bar', className='android.widget.LinearLayout')
search_button = tab_bar.child(index=1)

# Two clicks to reset tab content
search_button.click.wait()
search_button.click.wait()
navigate(device, Tabs.SEARCH)

print("Open user @" + username)
search_edit_text = device(resourceId='com.instagram.android:id/action_bar_search_edit_text',
Expand Down Expand Up @@ -159,6 +156,7 @@ def scrolled_to_top():

def _interact_with_user(device,
username,
my_username,
likes_count,
on_like,
can_follow,
Expand All @@ -167,14 +165,19 @@ def _interact_with_user(device,
"""
:return: (whether interaction succeed, whether @username was followed during the interaction)
"""
if username == my_username:
print("It's you, skip.")
return False, False

random_sleep()

if not profile_filter.check_profile(device, username):
return False, False

if likes_count > 12:
print(COLOR_FAIL + "Max number of likes per user is 12" + COLOR_ENDC)
likes_count = 12

random_sleep()
coordinator_layout = device(resourceId='com.instagram.android:id/coordinator_root_layout')
if coordinator_layout.exists:
print("Scroll down to see more photos.")
Expand Down Expand Up @@ -285,6 +288,12 @@ def _follow(device, username, follow_percentage):

if follow_button.exists:
follow_button.click.wait()
bottom_sheet = device(resourceId='com.instagram.android:id/layout_container_bottom_sheet',
className='android.widget.FrameLayout')
if bottom_sheet.exists:
print_timeless(COLOR_FAIL + "Already followed" + COLOR_ENDC)
device.press.back()
return False
print(COLOR_OKGREEN + "Followed @" + username + COLOR_ENDC)
random_sleep()
return True
Expand Down
61 changes: 61 additions & 0 deletions src/counters_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from src.navigation import Tabs, navigate
from src.utils import *


def parse(device, text):
multiplier = 1
text = text.replace(",", "")
if "K" in text:
text = text.replace("K", "")
multiplier = 1_000
if "M" in text:
text = text.replace("M", "")
multiplier = 1_000_000
try:
count = int(float(text) * multiplier)
except ValueError:
print_timeless(COLOR_FAIL + "Cannot parse \"" + text + "\". Probably wrong language, will set English now." +
COLOR_ENDC)
take_screenshot(device)
_switch_to_english(device)
raise LanguageChangedException()
return count


def _switch_to_english(device):
print(COLOR_OKGREEN + "Switching to English locale" + COLOR_ENDC)
navigate(device, Tabs.PROFILE)
print("Changing language in settings")

action_bar = device(resourceId='com.instagram.android:id/action_bar',
className='android.widget.LinearLayout')
options_view = action_bar.child(index=1)
options_view.click.wait()

settings_button = device(resourceId='com.instagram.android:id/menu_settings_row',
className='android.widget.TextView')
settings_button.click.wait()

list_view = device(resourceId='android:id/list',
className='android.widget.ListView')
account_item = list_view.child(index=6)
account_item.click.wait()

list_view = device(resourceId='android:id/list',
className='android.widget.ListView')
language_item = list_view.child(index=3)
language_item.click.wait()

search_edit_text = device(resourceId='com.instagram.android:id/search',
className='android.widget.EditText')
search_edit_text.set_text("english")
device.wait.idle()

list_view = device(resourceId='com.instagram.android:id/language_locale_list',
className='android.widget.ListView')
english_item = list_view.child(index=0)
english_item.click.wait()


class LanguageChangedException(Exception):
pass
Loading

0 comments on commit 565603d

Please sign in to comment.