From 085200f52cffbc4a0632fa22a834b5220dc849fd Mon Sep 17 00:00:00 2001 From: Dennis Date: Sat, 9 Mar 2024 14:14:59 +0100 Subject: [PATCH 1/5] fix: get people to stop asking this --- GramAddict/core/bot_flow.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/GramAddict/core/bot_flow.py b/GramAddict/core/bot_flow.py index 3cab4c4b..214af562 100644 --- a/GramAddict/core/bot_flow.py +++ b/GramAddict/core/bot_flow.py @@ -162,6 +162,9 @@ def start_bot(**kwargs): logger.warning( "If you press ENTER, you are aware of this and will not ask for support in case of a crash." ) + logger.warning( + "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)" + ) input() except Exception as e: From 1559c8af20ebe2e6b2e16551d76b776fd690d6fd Mon Sep 17 00:00:00 2001 From: Dennis Date: Sat, 9 Mar 2024 14:16:59 +0100 Subject: [PATCH 2/5] fix: specialize functions and add more info in console messages --- GramAddict/core/interaction.py | 102 ++++++++++++++++----------------- 1 file changed, 48 insertions(+), 54 deletions(-) diff --git a/GramAddict/core/interaction.py b/GramAddict/core/interaction.py index e3eb2402..ea53c484 100644 --- a/GramAddict/core/interaction.py +++ b/GramAddict/core/interaction.py @@ -5,7 +5,7 @@ from os import path from random import choice, randint, shuffle, uniform from time import sleep, time -from typing import Optional, Tuple +from typing import Optional, Tuple, List import emoji import spintax @@ -734,7 +734,7 @@ def _send_PM( message = load_random_message(my_username) if message is None: logger.warning( - "You forgot to populate your PM list! If you don't want to comment set 'pm-percentage: 0'" + "If you don't want to comment set 'pm-percentage: 0' in your config.yml." ) device.back() return False @@ -780,7 +780,9 @@ def _send_PM( return False -def load_random_message(my_username: str) -> Optional[str]: +def _load_and_clean_txt_file( + my_username: str, txt_filename: str +) -> Optional[List[str]]: def nonblank_lines(f): for ln in f: line = ln.rstrip() @@ -788,68 +790,60 @@ def nonblank_lines(f): yield line lines = [] - file_name = os.path.join(storage.ACCOUNTS, my_username, storage.FILENAME_MESSAGES) + file_name = os.path.join(storage.ACCOUNTS, my_username, txt_filename) if path.isfile(file_name): try: with open(file_name, "r", encoding="utf-8") as f: for line in nonblank_lines(f): lines.append(line) - random_message = choice(lines) - if random_message != "": - return emoji.emojize( - spintax.spin(random_message.replace("\\n", "\n")), - use_aliases=True, - ) - else: - return None + if lines: + return lines + logger.warning(f"{file_name} is empty! Check your account folder.") + return None except Exception as e: logger.error(f"Error: {e}.") + return None + logger.warning(f"{file_name} not found! Check your account folder.") + return None -def load_random_comment(my_username: str, media_type: MediaType) -> Optional[str]: - def nonblank_lines(f): - for ln in f: - line = ln.rstrip() - if line: - yield line +def load_random_message(my_username: str) -> Optional[str]: + lines = _load_and_clean_txt_file(my_username, storage.FILENAME_MESSAGES) + if lines is not None: + random_message = choice(lines) + return emoji.emojize( + spintax.spin(random_message.replace("\\n", "\n")), + use_aliases=True, + ) + return None - lines = [] - file_name = os.path.join(storage.ACCOUNTS, my_username, storage.FILENAME_COMMENTS) - if path.isfile(file_name): - with open(file_name, "r", encoding="utf-8") as f: - for line in nonblank_lines(f): - lines.append(line) - try: - photo_header = lines.index("%PHOTO") - video_header = lines.index("%VIDEO") - carousel_header = lines.index("%CAROUSEL") - except ValueError: - logger.warning( - f"You didn't follow the rules of sections for {file_name}! Look at config example." - ) - return None - photo_comments = lines[photo_header + 1 : video_header] - video_comments = lines[video_header + 1 : carousel_header] - carousel_comments = lines[carousel_header + 1 :] - random_comment = "" - if media_type == MediaType.PHOTO: - random_comment = ( - choice(photo_comments) if len(photo_comments) > 0 else "" - ) - elif media_type in (MediaType.VIDEO, MediaType.IGTV, MediaType.REEL): - random_comment = ( - choice(video_comments) if len(video_comments) > 0 else "" - ) - elif media_type == MediaType.CAROUSEL: - random_comment = ( - choice(carousel_comments) if len(carousel_comments) > 0 else "" - ) - if random_comment != "": - return emoji.emojize(spintax.spin(random_comment), use_aliases=True) - else: - return None + +def load_random_comment(my_username: str, media_type: MediaType) -> Optional[str]: + lines = _load_and_clean_txt_file(my_username, storage.FILENAME_COMMENTS) + if lines is None: + return None + try: + photo_header = lines.index("%PHOTO") + video_header = lines.index("%VIDEO") + carousel_header = lines.index("%CAROUSEL") + except ValueError: + logger.warning( + f"You didn't follow the rules for sections in your {storage.FILENAME_COMMENTS} txt file! Look at config example." + ) + return None + photo_comments = lines[photo_header + 1 : video_header] + video_comments = lines[video_header + 1 : carousel_header] + carousel_comments = lines[carousel_header + 1 :] + random_comment = "" + if media_type == MediaType.PHOTO: + random_comment = choice(photo_comments) if len(photo_comments) > 0 else "" + elif media_type in (MediaType.VIDEO, MediaType.IGTV, MediaType.REEL): + random_comment = choice(video_comments) if len(video_comments) > 0 else "" + elif media_type == MediaType.CAROUSEL: + random_comment = choice(carousel_comments) if len(carousel_comments) > 0 else "" + if random_comment != "": + return emoji.emojize(spintax.spin(random_comment), use_aliases=True) else: - logger.warning(f"{file_name} not found!") return None From 6fad04cab34ffb81a4c0b51ef6aebe5f9b3fde66 Mon Sep 17 00:00:00 2001 From: Dennis Date: Sat, 9 Mar 2024 14:21:12 +0100 Subject: [PATCH 3/5] test: add load and clean txt file test --- test/test_load_txt.py | 24 ++++++++++++++++++++++++ test/txt/txt_empty.txt | 5 +++++ test/txt/txt_ok.txt | 6 ++++++ 3 files changed, 35 insertions(+) create mode 100644 test/test_load_txt.py create mode 100644 test/txt/txt_empty.txt create mode 100644 test/txt/txt_ok.txt diff --git a/test/test_load_txt.py b/test/test_load_txt.py new file mode 100644 index 00000000..c9bcc93c --- /dev/null +++ b/test/test_load_txt.py @@ -0,0 +1,24 @@ +from GramAddict.core.interaction import _load_and_clean_txt_file + + +def test_load_txt_ok(mocker): + mocker.patch("os.path.join", return_value="txt/txt_ok.txt") + message = _load_and_clean_txt_file("test_user", "txt_filename") + assert message is not None + assert message == [ + "Hello, test_user! How are you today?", + "Hello everyone!", + "Goodbye, test_user! Have a great day!", + ] + + +def test_load_txt_empty(mocker): + mocker.patch("os.path.join", return_value="txt/txt_empty.txt") + message = _load_and_clean_txt_file("test_user", "txt_filename") + assert message is None + + +def test_load_txt_not_exists(mocker): + mocker.patch("os.path.join", return_value="txt/txt_not_exists.txt") + message = _load_and_clean_txt_file("test_user", "txt_filename") + assert message is None diff --git a/test/txt/txt_empty.txt b/test/txt/txt_empty.txt new file mode 100644 index 00000000..3f2ff2d6 --- /dev/null +++ b/test/txt/txt_empty.txt @@ -0,0 +1,5 @@ + + + + + diff --git a/test/txt/txt_ok.txt b/test/txt/txt_ok.txt new file mode 100644 index 00000000..7e3585ae --- /dev/null +++ b/test/txt/txt_ok.txt @@ -0,0 +1,6 @@ + +Hello, test_user! How are you today? +Hello everyone! + +Goodbye, test_user! Have a great day! + From c2f7d14b67395a98ab4eec2184c41c5f749242e0 Mon Sep 17 00:00:00 2001 From: Dennis Date: Sat, 9 Mar 2024 14:21:47 +0100 Subject: [PATCH 4/5] fix: account selecting --- GramAddict/core/resources.py | 1 + GramAddict/core/views.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/GramAddict/core/resources.py b/GramAddict/core/resources.py index 7d731592..af31e55d 100644 --- a/GramAddict/core/resources.py +++ b/GramAddict/core/resources.py @@ -182,6 +182,7 @@ def __init__(self, APP_ID): self.UNIFIED_FOLLOW_LIST_TAB_LAYOUT = ( f"{APP_ID}:id/unified_follow_list_tab_layout" ) + self.USERNAME_TEXTVIEW = f"{APP_ID}:id/username_textview" self.VIDEO_CONTAINER = f"{APP_ID}:id/video_container" self.VIEW_PLAY_BUTTON = f"{APP_ID}:id/view_play_button" self.ZOOMABLE_VIEW_CONTAINER = f"{APP_ID}:id/zoomable_view_container" diff --git a/GramAddict/core/views.py b/GramAddict/core/views.py index e91f77a3..6dcda336 100644 --- a/GramAddict/core/views.py +++ b/GramAddict/core/views.py @@ -1080,7 +1080,7 @@ def changeToUsername(self, username: str): def _find_username(self, username, has_scrolled=False): list_view = self.device.find(resourceId=ResourceID.LIST) username_obj = self.device.find( - resourceId=ResourceID.ROW_USER_TEXTVIEW, + resourceIdMatches=f"{ResourceID.ROW_USER_TEXTVIEW}|{ResourceID.USERNAME_TEXTVIEW}", textMatches=case_insensitive_re(username), ) if username_obj.exists(Timeout.SHORT): From 886f31460f1b01f50acc3e1b36f0d8f40e30982b Mon Sep 17 00:00:00 2001 From: Dennis Date: Sat, 9 Mar 2024 14:25:40 +0100 Subject: [PATCH 5/5] bump: new version --- .gitignore | 2 -- CHANGELOG.md | 8 ++++++++ GramAddict/__init__.py | 4 ++-- GramAddict/version.py | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 5c023de5..59ddc736 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ /dist /gramaddict.egg-info /.idea -/test /.vscode */*.yml */*.json @@ -17,7 +16,6 @@ accounts Pipfile Pipfile.lock *.pdf -*.txt *.mp4 *.log* *.ini diff --git a/CHANGELOG.md b/CHANGELOG.md index ae6566b7..35a41fcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,12 @@ # Changelog +## 3.2.10 (2024-03-09) +### Fix +- account selecting +- function specialization for load and clean txt file +- better logging for the user +### Others +- test for load and clean txt file + ## 3.2.9 (2024-02-10) ### Fix - remove pandas as dependency for telegram reports diff --git a/GramAddict/__init__.py b/GramAddict/__init__.py index 1a81c795..82f18f0d 100644 --- a/GramAddict/__init__.py +++ b/GramAddict/__init__.py @@ -1,7 +1,7 @@ """Human-like Instagram bot powered by UIAutomator2""" -__version__ = "3.2.9" -__tested_ig_version__ = "263.2.0.19.104" +__version__ = "3.2.10" +__tested_ig_version__ = "300.0.0.29.110" from GramAddict.core.bot_flow import start_bot diff --git a/GramAddict/version.py b/GramAddict/version.py index 46f53016..9f2df45c 100644 --- a/GramAddict/version.py +++ b/GramAddict/version.py @@ -1,2 +1,2 @@ # that file is deprecated, current version is now stored in GramAddict/__init__.py -__version__ = "3.2.9" +__version__ = "3.2.10"