Skip to content

Commit

Permalink
Update to v3.7.11
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Mishchenko committed May 5, 2021
1 parent 0da22b1 commit 2c71d52
Show file tree
Hide file tree
Showing 12 changed files with 148 additions and 98 deletions.
3 changes: 3 additions & 0 deletions blacklist.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# Important: This file is shared as blacklist file across all of the accounts you run insomniac with.
# If you wish to create a blacklist file thats dedicated to a specific accout, copy this file and name it <PROFILE-NAME>-blacklist.txt (replace <PROFILE-NAME> with your profile-name)

username1
username2
4 changes: 4 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,10 @@ number (e.g. 4) or a range (e.g. 3-8)
### Special features
Other features that are unblocked by [joining Patreon $10 tier](https://www.patreon.com/join/insomniac_bot):

#### --warmup-time-before-session 2-6
Set warmup length in minutes, disabled by default.
It can be a number (e.g. 2) or a range (e.g. 1-3).

#### --remove-mass-followers 10-20
Remove given number of mass followers from the list of
your followers. "Mass followers" are those who has
Expand Down
2 changes: 1 addition & 1 deletion insomniac/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
__title__ = 'insomniac'
__description__ = 'Simple Instagram bot for automated Instagram interaction using Android.'
__url__ = 'https://github.com/alexal1/Insomniac/'
__version__ = '3.7.10'
__version__ = '3.7.11'
__debug_mode__ = False
__author__ = 'Insomniac Team'
__author_email__ = 'info@insomniac-bot.com'
Expand Down
1 change: 1 addition & 0 deletions insomniac/action_get_my_profile_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def get_my_profile_info(device, username):

report_string = ""
if username:
username = username.strip()
report_string += "Hello, @" + username + "! "
if followers is not None:
report_string += "You have " + str(followers) + " followers"
Expand Down
49 changes: 17 additions & 32 deletions insomniac/action_runners/interact/action_handle_place.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,23 @@ def handle_place(device,
is_limit_reached,
is_passed_filters,
action_status):
if not search_for(device, place=place, on_action=on_action):
return None

# Switch to Recent tab if needed
if instructions == PlaceInteractionType.RECENT_LIKERS or instructions == PlaceInteractionType.RECENT_POSTS:
sleeper.random_sleep()
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)

source_type = f'{SourceType.PLACE.value}-{instructions.value}'
interaction = partial(interact_with_user,
device=device,
Expand Down Expand Up @@ -215,22 +232,6 @@ def interact_with_profile(liker_username, liker_username_view):
return can_continue

def navigate_to_feed():
if not search_for(device, place=place, on_action=on_action):
return None

# Switch to Recent tab
if instructions == PlaceInteractionType.RECENT_LIKERS or instructions == PlaceInteractionType.RECENT_POSTS:
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:
Expand Down Expand Up @@ -296,22 +297,6 @@ def extract_place_likers_and_interact(device,
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 or instructions == PlaceInteractionType.RECENT_POSTS:
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 = navigate_to_feed()
if posts_view_list is None:
Expand Down
14 changes: 13 additions & 1 deletion insomniac/navigation.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from insomniac.sleeper import sleeper
from insomniac.utils import *
from insomniac.views import TabBarView, ProfileView, TabBarTabs, LanguageNotEnglishException

Expand All @@ -16,7 +17,18 @@ def navigate(device, tab, switch_to_english_on_exception=True):


def search_for(device, username=None, hashtag=None, place=None, on_action=None):
search_view = TabBarView(device).navigate_to_search()
tab_bar_view = TabBarView(device)

# There may be no TabBarView if Instagram was opened via a deeplink. Then we have to clear the backstack.
is_message_printed = False
while not tab_bar_view.is_visible():
if not is_message_printed:
print(COLOR_OKGREEN + "Clearing the back stack..." + COLOR_ENDC)
is_message_printed = True
tab_bar_view.press_back_arrow()
sleeper.random_sleep()

search_view = tab_bar_view.navigate_to_search()
target_view = None

if username is not None:
Expand Down
131 changes: 80 additions & 51 deletions insomniac/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def wrap(*args, **kwargs):


class Storage:
my_username = None
profile = None
scrape_for_account_list = []
recheck_follow_status_after = None
Expand All @@ -71,6 +72,7 @@ class Storage:
def _reset_state(self):
global IS_USING_DATABASE
IS_USING_DATABASE = False
self.my_username = None
self.profile = None
self.scrape_for_account_list = []
self.recheck_follow_status_after = None
Expand All @@ -93,6 +95,7 @@ def __init__(self, my_username, args):
global IS_USING_DATABASE
IS_USING_DATABASE = True

self.my_username = my_username
self.profile = get_ig_profile_by_profile_name(my_username)
scrape_for_account = args.__dict__.get('scrape_for_account', [])
self.scrape_for_account_list = scrape_for_account if isinstance(scrape_for_account, list) else [scrape_for_account]
Expand All @@ -108,17 +111,30 @@ def __init__(self, my_username, args):
blacklist_from_parameters = args.__dict__.get('blacklist_profiles', None)

# Whitelist and Blacklist
try:
with open(FILENAME_WHITELIST, encoding="utf-8") as file:
self.whitelist = [line.rstrip() for line in file]
except FileNotFoundError:
print_debug("No whitelist provided")

try:
with open(FILENAME_BLACKLIST, encoding="utf-8") as file:
self.blacklist = [line.rstrip() for line in file]
except FileNotFoundError:
print_debug("No blacklist provided")
whitelist_files = {
FILENAME_WHITELIST: "global-whitelist",
f"{self.my_username}-{FILENAME_WHITELIST}": "profile-whitelist"
}

blacklist_files = {
FILENAME_BLACKLIST: "global-blacklist",
f"{self.my_username}-{FILENAME_BLACKLIST}": "profile-blacklist"
}

for file_path, file_desc in whitelist_files.items():
try:
with open(file_path, encoding="utf-8") as file:
self.whitelist.extend([line.rstrip() for line in file if not line.startswith("#")])
except FileNotFoundError:
print_debug(f"No {file_desc} file provided")

for file_path, file_desc in blacklist_files.items():
try:
with open(file_path, encoding="utf-8") as file:
self.blacklist.extend([line.rstrip() for line in file if not line.startswith("#")])
except FileNotFoundError:
print_debug(f"No {file_desc} file provided")

if whitelist_from_parameters is not None:
if isinstance(whitelist_from_parameters, list) and len(whitelist_from_parameters) > 0:
Expand Down Expand Up @@ -289,32 +305,37 @@ def _get_target(self):
except IndexError:
pass

# From file
try:
with open(FILENAME_TARGETS, "r+", encoding="utf-8") as file:
lines = [line.rstrip() for line in file]

for i, line in enumerate(lines):
# Skip comments
if line.startswith("#"):
continue

# Skip already interacted
if "DONE" in line:
continue

data = line.strip()
if data.startswith("https://"):
target_type = TargetType.URL
else:
target_type = TargetType.USERNAME
lines[i] += " - DONE"
file.truncate(0)
file.seek(0)
file.write("\n".join(lines))
return data, target_type
except FileNotFoundError:
pass
targets_files = {
FILENAME_TARGETS: "global-targets",
f"{self.my_username}-{FILENAME_TARGETS}": "profile-targets"
}

for file_path, file_desc in targets_files.items():
try:
with open(file_path, "r+", encoding="utf-8") as file:
lines = [line.rstrip() for line in file]

for i, line in enumerate(lines):
# Skip comments
if line.startswith("#"):
continue

# Skip already interacted
if "DONE" in line:
continue

data = line.strip()
if data.startswith("https://"):
target_type = TargetType.URL
else:
target_type = TargetType.USERNAME
lines[i] += " - DONE"
file.truncate(0)
file.seek(0)
file.write("\n".join(lines))
return data, target_type
except FileNotFoundError:
pass

# From scrapping
scrapped_profile = self.profile.get_scrapped_profile_for_interaction()
Expand All @@ -330,22 +351,30 @@ def is_user_in_blacklist(self, username):

def _count_targets_from_file(self):
count = 0
try:
with open(FILENAME_TARGETS, encoding="utf-8") as file:
lines = [line.rstrip() for line in file]

for i, line in enumerate(lines):
# Skip comments
if line.startswith("#"):
continue

# Skip already interacted
if "DONE" in line:
continue

count += 1
except FileNotFoundError:
pass
# From file
targets_files = {
FILENAME_TARGETS: "global-targets",
f"{self.my_username}-{FILENAME_TARGETS}": "profile-targets"
}

for file_path, file_desc in targets_files.items():
try:
with open(file_path, encoding="utf-8") as file:
lines = [line.rstrip() for line in file]

for i, line in enumerate(lines):
# Skip comments
if line.startswith("#"):
continue

# Skip already interacted
if "DONE" in line:
continue

count += 1
except FileNotFoundError:
pass
return count


Expand Down
6 changes: 4 additions & 2 deletions insomniac/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
ENGINE_LOGS_DIR_NAME = 'logs'
UI_LOGS_DIR_NAME = 'ui-logs'

APP_REOPEN_WARNING = "Warning: Activity not started, intent has been delivered to currently running top-most instance."


def get_instagram_version(device_id, app_id):
stream = os.popen("adb" + ("" if device_id is None else " -s " + device_id) +
Expand Down Expand Up @@ -121,7 +123,7 @@ def open_instagram(device_id, app_id):

cmd_res = subprocess.run(cmd, stdout=PIPE, stderr=PIPE, shell=True, encoding="utf8")
err = cmd_res.stderr.strip()
if err:
if err and err != APP_REOPEN_WARNING:
print(COLOR_FAIL + err + COLOR_ENDC)


Expand All @@ -132,7 +134,7 @@ def open_instagram_with_url(device_id, app_id, url):
cmd_res = subprocess.run(cmd, stdout=PIPE, stderr=PIPE, shell=True, encoding="utf8")
err = cmd_res.stderr.strip()

if err:
if err and err != APP_REOPEN_WARNING:
print(COLOR_FAIL + err + COLOR_ENDC)
return False

Expand Down
27 changes: 19 additions & 8 deletions insomniac/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ def __init__(self, device: DeviceFacade):
super().__init__(device)
self.top = None

def is_visible(self) -> bool:
return self._get_tab_bar().exists()

def _get_tab_bar(self):
self.device.close_keyboard()

Expand Down Expand Up @@ -331,13 +334,21 @@ def _get_hashtag_row(self, hashtag):
)

def _get_place_row(self, place):
return self.device.find(
resourceIdMatches=case_insensitive_re(
f"{self.device.app_id}:id/row_place_title"
),
className="android.widget.TextView",
textMatches=case_insensitive_re(place)
)
if place is None:
return self.device.find(
resourceIdMatches=case_insensitive_re(
f"{self.device.app_id}:id/row_place_title"
),
className="android.widget.TextView"
)
else:
return self.device.find(
resourceIdMatches=case_insensitive_re(
f"{self.device.app_id}:id/row_place_title"
),
className="android.widget.TextView",
textMatches = case_insensitive_re(place)
)

def _get_tab_text_view(self, tab: SearchTabs):
tab_layout = self.device.find(
Expand Down Expand Up @@ -500,7 +511,7 @@ def navigate_to_place(self, place):
return None
places_tab.click()

place_view = self._get_place_row(place)
place_view = self._get_place_row(None) # just open first place we see
if not place_view.exists():
print(COLOR_FAIL + f"Cannot find place {place}, abort." + COLOR_ENDC)
save_crash(self.device)
Expand Down
4 changes: 1 addition & 3 deletions registration/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
## Registration Flow (experimental feature)

_IMPORTANT! This is an experimental feature. It means that the code is working, but we don't have an exact recipe how to avoid a CAPTCHA. Instagram is very strict when it comes to creating new accounts._
## Registration Flow

Insomniac gives the possibility to create Instagram accounts automatically. This can be done via `--register registration/users.txt` argument. Insomniac will do the following:
1. Open the app and **create new identity** if you're using a clone via [appcloner.app](https://appcloner.app), or just clear app data if you're not.
Expand Down
2 changes: 2 additions & 0 deletions targets.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Targets to interact with. Provide either usernames or posts urls.
# Important: This file is shared as targets file across all of the accounts you run insomniac with.
# If you wish to create a targets file thats dedicated to a specific accout, copy this file and name it <PROFILE-NAME>-targets.txt (replace <PROFILE-NAME> with your profile-name)
#
# Example:
# natgeo
Expand Down
3 changes: 3 additions & 0 deletions whitelist.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# Important: This file is shared as whitelist file across all of the accounts you run insomniac with.
# If you wish to create a whitelist file thats dedicated to a specific accout, copy this file and name it <PROFILE-NAME>-whitelist.txt (replace <PROFILE-NAME> with your profile-name)

username1
username2

0 comments on commit 2c71d52

Please sign in to comment.