Skip to content

Commit 0686761

Browse files
committed
Merge branch 'master' of https://github.com/GramAddict/bot
2 parents 470bb0e + 015d461 commit 0686761

File tree

11 files changed

+625
-115
lines changed

11 files changed

+625
-115
lines changed

GramAddict/core/bot_flow.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
open_instagram,
4242
pre_post_script,
4343
print_telegram_reports,
44+
restart_atx_agent,
4445
save_crash,
4546
set_time_delta,
4647
show_ending_conditions,
@@ -119,6 +120,8 @@ def start_bot(**kwargs):
119120
if not inside_working_hours:
120121
wait_for_next_session(time_left, session_state, sessions, device)
121122
pre_post_script(path=configs.args.pre_script)
123+
if configs.args.restart_atx_agent:
124+
restart_atx_agent(device)
122125
get_device_info(device)
123126
session_state = SessionState(configs)
124127
session_state.set_limits_session()
@@ -163,7 +166,7 @@ def start_bot(**kwargs):
163166
"If you press ENTER, you are aware of this and will not ask for support in case of a crash."
164167
)
165168
logger.warning(
166-
"If you want to avoid pressing ENTER next run, add allow-untested-ig-version: True in your config.yml file. (read the docs for more info)"
169+
"If you want to avoid pressing ENTER next run, add allow-untested-ig-version: true in your config.yml file. (read the docs for more info)"
167170
)
168171
input()
169172

@@ -357,7 +360,8 @@ def start_bot(**kwargs):
357360
device.screen_off()
358361
logger.info("Screen turned off for sleeping time.")
359362

360-
kill_atx_agent(device)
363+
if configs.args.kill_atx_agent:
364+
kill_atx_agent(device)
361365
head_up_notifications(enabled=True)
362366
logger.info(
363367
"-------- FINISH: "

GramAddict/core/device_facade.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,11 @@ def stop_screenrecord(self, crash=True):
185185
if self.deviceV2.screenrecord.stop(crash=crash):
186186
logger.warning("Screen recorder has been stopped successfully!")
187187

188-
def screenshot(self, path):
189-
self.deviceV2.screenshot(path)
188+
def screenshot(self, path=None):
189+
if path is None:
190+
return self.deviceV2.screenshot()
191+
else:
192+
self.deviceV2.screenshot(path)
190193

191194
def dump_hierarchy(self, path):
192195
xml_dump = self.deviceV2.dump_hierarchy()
@@ -352,7 +355,7 @@ def ui_info(self):
352355
except uiautomator2.JSONRPCError as e:
353356
raise DeviceFacade.JsonRpcError(e)
354357

355-
def content_desc(self):
358+
def get_desc(self):
356359
try:
357360
return self.viewV2.info["contentDescription"]
358361
except uiautomator2.JSONRPCError as e:

GramAddict/core/utils.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -429,11 +429,30 @@ def kill_atx_agent(device):
429429
_restore_keyboard(device)
430430
logger.info("Kill atx agent.")
431431
cmd: str = (
432-
f"adb{'' if configs.device_id is None else ' -s ' + configs.device_id} shell pkill atx-agent"
432+
f"adb{'' if configs.device_id is None else f' -s {configs.device_id}'} shell pkill atx-agent"
433433
)
434434
subprocess.run(cmd, stdout=PIPE, stderr=PIPE, shell=True, encoding="utf8")
435435

436436

437+
def restart_atx_agent(device):
438+
kill_atx_agent(device)
439+
logger.info("Restarting atx agent.")
440+
cmd: str = (
441+
f"adb{'' if configs.device_id is None else f' -s {configs.device_id}'} shell /data/local/tmp/atx-agent server -d"
442+
)
443+
444+
try:
445+
result = subprocess.run(
446+
cmd, stdout=PIPE, stderr=PIPE, shell=True, encoding="utf8", check=True
447+
)
448+
if result.returncode != 0:
449+
logger.error(f"Failed to restart atx-agent: {result.stderr}")
450+
else:
451+
logger.info("atx-agent restarted successfully.")
452+
except subprocess.CalledProcessError as e:
453+
logger.error(f"Error occurred while restarting atx-agent: {e}")
454+
455+
437456
def _restore_keyboard(device):
438457
logger.debug("Back to default keyboard!")
439458
device.deviceV2.set_fastinput_ime(False)
@@ -524,7 +543,8 @@ def trim_txt(source: str, target: str) -> None:
524543

525544
def stop_bot(device, sessions, session_state, was_sleeping=False):
526545
close_instagram(device)
527-
kill_atx_agent(device)
546+
if args.kill_atx_agent:
547+
kill_atx_agent(device)
528548
head_up_notifications(enabled=True)
529549
logger.info(
530550
f"-------- FINISH: {datetime.now().strftime('%H:%M:%S')} --------",
@@ -704,7 +724,8 @@ def set_time_delta(args):
704724
def wait_for_next_session(time_left, session_state, sessions, device):
705725
hours, remainder = divmod(time_left.seconds, 3600)
706726
minutes, seconds = divmod(remainder, 60)
707-
kill_atx_agent(device)
727+
if args.kill_atx_agent:
728+
kill_atx_agent(device)
708729
logger.info(
709730
f'Next session will start at: {(datetime.now()+ time_left).strftime("%H:%M:%S (%Y/%m/%d)")}.',
710731
extra={"color": f"{Fore.GREEN}"},

GramAddict/core/views.py

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import datetime
22
import logging
33
import re
4+
import platform
45
from enum import Enum, auto
56
from random import choice, randint, uniform
67
from time import sleep
@@ -128,7 +129,7 @@ def navigateToProfile(self):
128129
def _get_new_profile_position(self) -> Optional[DeviceFacade.View]:
129130
buttons = self.device.find(className=ResourceID.BUTTON)
130131
for button in buttons:
131-
if button.content_desc() == "Profile":
132+
if button.get_desc() == "Profile":
132133
return button
133134
return None
134135

@@ -871,7 +872,7 @@ def _get_post_owner_name(self):
871872

872873
def _get_media_container(self):
873874
media = self.device.find(resourceIdMatches=ResourceID.CAROUSEL_AND_MEDIA_GROUP)
874-
content_desc = media.content_desc() if media.exists() else None
875+
content_desc = media.get_desc() if media.exists() else None
875876
return media, content_desc
876877

877878
@staticmethod
@@ -988,23 +989,61 @@ def _check_if_ad_or_hashtag(
988989
) -> Tuple[bool, bool, Optional[str]]:
989990
is_hashtag = False
990991
is_ad = False
991-
real_username = None
992992
logger.debug("Checking if it's an AD or an hashtag..")
993993
ad_like_obj = post_owner_obj.sibling(
994994
resourceId=ResourceID.SECONDARY_LABEL,
995995
)
996-
if post_owner_obj.get_text().startswith("#"):
997-
is_hashtag = True
998-
logger.debug("Looks like an hashtag, skip.")
996+
997+
owner_name = post_owner_obj.get_text() or post_owner_obj.get_desc()
998+
if not owner_name:
999+
logger.info("Can't find the owner name, need to use OCR.")
1000+
try:
1001+
import pytesseract as pt
1002+
1003+
owner_name = self.get_text_from_screen(pt, post_owner_obj)
1004+
except ImportError:
1005+
logger.error(
1006+
"You need to install pytesseract (the wrapper: pip install pytesseract) in order to use OCR feature."
1007+
)
1008+
except pt.TesseractNotFoundError:
1009+
logger.error(
1010+
"You need to install Tesseract (the engine: it depends on your system) in order to use OCR feature."
1011+
)
1012+
if owner_name.startswith("#"):
1013+
is_hashtag = True
1014+
logger.debug("Looks like an hashtag, skip.")
9991015
if ad_like_obj.exists():
1000-
sponsored = "Sponsored"
1001-
if ad_like_obj.get_text() == sponsored:
1016+
sponsored_txt = "Sponsored"
1017+
ad_like_txt = ad_like_obj.get_text() or ad_like_obj.get_desc()
1018+
if ad_like_txt.casefold() == sponsored_txt.casefold():
10021019
logger.debug("Looks like an AD, skip.")
10031020
is_ad = True
10041021
elif is_hashtag:
1005-
real_username = ad_like_obj.get_text().split("•")[0].strip()
1022+
owner_name = owner_name.split("•")[0].strip()
1023+
1024+
return is_ad, is_hashtag, owner_name
1025+
1026+
def get_text_from_screen(self, pt, obj) -> Optional[str]:
10061027

1007-
return is_ad, is_hashtag, real_username
1028+
if platform.system() == "Windows":
1029+
pt.pytesseract.tesseract_cmd = (
1030+
r"C:\Program Files\Tesseract-OCR\tesseract.exe"
1031+
)
1032+
1033+
screenshot = self.device.screenshot()
1034+
bounds = obj.ui_info().get("visibleBounds", None)
1035+
if bounds is None:
1036+
logger.info("Can't find the bounds of the object.")
1037+
return None
1038+
screenshot_cropped = screenshot.crop(
1039+
[
1040+
bounds.get("left"),
1041+
bounds.get("top"),
1042+
bounds.get("right"),
1043+
bounds.get("bottom"),
1044+
]
1045+
)
1046+
return pt.image_to_string(screenshot_cropped).split(" ")[0].rstrip()
10081047

10091048

10101049
class LanguageView:
@@ -1498,7 +1537,7 @@ def _new_ui_profile_button(self) -> bool:
14981537
found = False
14991538
buttons = self.device.find(className=ResourceID.BUTTON)
15001539
for button in buttons:
1501-
if button.content_desc() == "Profile":
1540+
if button.get_desc() == "Profile":
15021541
button.click()
15031542
found = True
15041543
return found

GramAddict/plugins/core_arguments.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,16 @@ def __init__(self):
205205
"help": "close all apps except IG, to avoid interference",
206206
"action": "store_true",
207207
},
208+
{
209+
"arg": "--kill-atx-agent",
210+
"help": "kill atx-agent when the script ends",
211+
"action": "store_true",
212+
},
213+
{
214+
"arg": "--restart-atx-agent",
215+
"help": "restart atx-agent before the script starts",
216+
"action": "store_true",
217+
},
208218
{
209219
"arg": "--interact",
210220
"nargs": "+",

0 commit comments

Comments
 (0)