Skip to content

Commit

Permalink
🎁 NEW FEATURE: COMMENT POSTS (#156)
Browse files Browse the repository at this point in the history
* Fix follow (#109)

* add NOT_IN_LIST check for can_follow

* Update version.py

Co-authored-by: Philip Ulrich <[email protected]>

* 🎁 adding --debug flag (#105)

* 🐈 pause option when quitting (#115)

if you ctrl-c out, give an option to pause or quit.

* 🐈 improvements for hashtag-likers on older devices and memu (#112)

* following and follower filter (#106)

🎁 add filter - following
🎁 add filter - follower
🐈 refactor resource ids
Co-authored-by: Uğur Kellecioğlu <[email protected]>

* Fix crash stories and private profile (#117)

🐛 add new resource ID for some devices.
🐛 add short sleep before checking if the screen is unlocked to reduce issues
🐛 modify story watching to reduce crashes
🐛 substitute the .down with .find that caused a crash
🐎 increase speed of things that don't need to be slow
🐈 slow down some views (e.g. recent hashtags) to reduce issues
📝 fix some issues with argument help not matching

* Fix --analytics Bugs with Missing Session Data (#103)

🐛 Fix analytics report when there is broken data
🐈 Include time in analytics report so you can generate multiple a day
🐈 Make pause better

* Changing to Pypi for Release (#118)

🐈 add files for pypi distro
🐛 fix errors related to resourceid refactor
🐛 fix unfollow after unfollowing a follower
🐎 sped up sleep after unfollow

* fixing bio expand (#120)

🐛 fix error on hashtag in biography

* noice (#121)

* 📝 typo

* speed multiplier and scrolls limit (#124)

🎁 add scroll repeat exiter
🎁 add speed multiplier

* Create interact_hashtag_posts.py

start point

* resolving conflicts

* resolving conflicts

* forget to remove old codes

forget to remove old codes

* small cleanups

* changing reference to old arguemnt name

* 😡 linting

* switching to get_value for session_state total_limits (#132)

* bugfixes + hashtag-post improve

- slow down a little bit the scroll speed from 0.3 to 0.4 min
- after liking post of an user, going back with the exact scroll (no longer unwanted refresh of the page)
- reunify some functions
- force_interact.dis updated
- likes_from_urls.py updated
Hashtag-post plug-in
- control if like in feed has successed otherwise single click
- if the view goes over the nickname of the owner for inertia, is not a problem anymore
- add the detect block in feed

* --hashtag-posts-top

-add the hashtag-posts-top feature

* black by hands

black by hands

* Update interact_hashtag_posts.py

fix lint

* Update interaction.py

imported but not used, removed

* Update interact_hashtag_posts.py

removed comment part and add one detect_block

* Update interact_hashtag_posts.py

:bug: forgot to end the loop when finish

TODO: "in each job we assume being on the top of the Profile tab already" is missing

* update readme (#125)

📝 add new logo
📝 add new demo
📝 update formatting and info

Co-authored-by: Arthur Silva <[email protected]>

* add logic to handle unfollowing any-non-followers (#133)

* add logic to handle unfollowing any-non-followers
* updating unfollow arguments

* fixes and improvements

- add some good verbose for debugging
- current job info
- fix bug to handle another job and not in the main profile view
- fix picking same orgument if -recent and -top where used at the same session
- random swipe points

* - fix another bug if recent and top are used toghetter

- fix another bug if recent and top are used toghetter
- add random in y for swipe end point: the 1st point it better not to touch for now because it can likely go outside the scollable area (can be done by a little reworking)
-  fixed unfollow actions that don't goes back to profile views
- moved the swipe_points in a new class called "UniversalActions" because it's not related to a specif view

TODO: change the scroll behaviour for unfollow actions

* Update interact_hashtag_likers.py

fix lint

* bugfixes and improvements

- fix bug whit a swipe when trying to sort followers and there are "categories" in the view, so it can't find the obj
- added two missing resources
- improve the usability of _swipe_points()
- add an info when unfollowed someone
- add a sleep between two action in hashtag-posts

* Update interaction.py

- forgot to change that

* fixs

- fix session state
TODO add unfollow
- discovered that after sorting follower the screen get refreshed, so left a random swipe at beginnig, and move the swipe after the sorting
- removed one multiple verbose (for unfollow any)

* Get rid of possible inifinite loops (#135)

🐛 fix an infinite loop issue when running unfollow plugin.
🐛 remove other unnecessary `while True`loops

* fixes

- fix the changed class in the follow/unfollow button
- fix a typo that prevent for using hashtag-likers-top

* config file update / uia1 support (#136)

🎁 add support for config files
🎁 add support for uia1
🎁 add support for cloned apps
🐛 fix follow button class
🐛 fix follow not count when profile private
🎁 add back optional fling support

Co-authored-by: Arthur Silva <[email protected]>

* merge things

need to test..

* porting missing resources

porting missing resources

* Update action_unfollow_followers.py

black

* cleaning and fixing things

- fix bug in hashtag-post when the name of hashtag comes down over the owner name
- look in recent before type in handle blogger
- add misses resources
- cleaning
- lint some expressions

* Update views.py

* Update session_state.py

* fixes (#143)

* fixing hashtag changes

* minor fixes

* updating verbiage on fling

* kill atx-agent and uia1

* Create interact_usernames.py (#128)

- 🎁 add feature - interact-usernames

* config updates (#145)

updating config file example and parameter names

* updating deployment info and file structure

* update varable name

* Hashtag-likers improvement (#147)

🐛 various fixes - does not need to be included in change log

* adding additional instructions for deployment

* fixing parameters and deployment files

* change username according to configuration file loaded (#149)

🎁 add feature - check the provided username and switch if not on that profile

* updating version

* new core argument --delete-interacted-user (#150)

- new core argument --delete-interacted-user


Co-authored-by: Philip Ulrich <[email protected]>

* 🎁 NEW FEATURE: COMMENT POSTS

🎁 NEW FEATURE: COMMENT POSTS
put a sentence in separate lines in the file comments_list.txt, the script will choose randomly among them
New arguments:
--comment-percentage
comment given percentage of interacted users, 0 by default
--total-comments-limit
limit on total comments per session, disabled by default

-add the file comments_list.txt
-fix: sometimes the search of an user in search bar fails, with that change it miss anymore for me (views.py)
-add resources for accomplish the comment plugin
-report will consider comments
-fix: the +1 on total likes was in a wrong position, if it fails to like it will not count

* Update all-parameters.yml

* Update all-parameters.yml

* revert a stupid change :)

* typo

* fix merge error

* removing unused variable

* fixing lint

Co-authored-by: Philip Ulrich <[email protected]>
Co-authored-by: narkopolo <[email protected]>
Co-authored-by: Philip Ulrich <[email protected]>
Co-authored-by: Arthur Silva <[email protected]>
  • Loading branch information
5 people authored Jan 17, 2021
1 parent bb28539 commit 21cdd58
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 17 deletions.
2 changes: 1 addition & 1 deletion GramAddict/core/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ def check_profile(self, device, username):
field_max_followers
):
logger.info(
f"@{username} has has more than {field_max_followers} followers, skip.",
f"@{username} has more than {field_max_followers} followers, skip.",
extra={"color": f"{Fore.GREEN}"},
)
return self.return_check_profile(
Expand Down
100 changes: 94 additions & 6 deletions GramAddict/core/interaction.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import logging
from random import randint, shuffle
from random import randint, shuffle, choice
from typing import Tuple
from time import time
from os import path
from colorama import Fore
from GramAddict.core.navigation import switch_to_english
from GramAddict.core.report import print_short_report
Expand Down Expand Up @@ -43,6 +44,7 @@ def interact_with_user(
on_watch,
can_follow,
follow_percentage,
comment_percentage,
profile_filter,
args,
session_state,
Expand Down Expand Up @@ -124,6 +126,9 @@ def interact_with_user(
shuffle(photos_indices)
photos_indices = photos_indices[:likes_value]
photos_indices = sorted(photos_indices)
like_done = False
comment_done = False
interacted = False
for i in range(0, len(photos_indices)):
photo_index = photos_indices[i]
row = photo_index // 3
Expand All @@ -134,12 +139,31 @@ def interact_with_user(

like_succeed = False
if opened_post_view:
logger.info("Double click post.")

like_succeed = do_like(opened_post_view, device, on_like)
if not like_succeed:
logger.debug("Double click failed. Try the like button.")
like_succeed = opened_post_view.likePost(click_btn_like=True)

if like_succeed is True:
number_of_liked += 1
like_done = True
logger.debug("Like succeed. Check for block.")
detect_block(device)
on_like()
else:
logger.warning("Fail to like post. Let's continue...")

logger.info("Back to profile.")
device.back()
comment_done = _comment(
device, my_username, comment_percentage, args, session_state
)
logger.info("Back to profile.")
device.back()
if like_done or comment_done:
interacted = True
else:
interacted = False

if not opened_post_view or not like_succeed:
reason = "open" if not opened_post_view else "like"
Expand All @@ -159,8 +183,7 @@ def interact_with_user(

if not followed:
logger.info("Skip user.", extra={"color": f"{Fore.GREEN}"})
return False, followed, number_of_liked, number_of_watched

return interacted, followed, number_of_liked, number_of_watched
random_sleep()
if can_follow:
return (
Expand All @@ -172,7 +195,7 @@ def interact_with_user(
number_of_watched,
)

return True, False, number_of_liked, number_of_watched
return interacted, False, number_of_liked, number_of_watched


def do_like(opened_post_view, device, on_like):
Expand Down Expand Up @@ -243,6 +266,71 @@ def _on_interaction(
return can_continue


def _comment(device, my_username, comment_percentage, args, session_state):
if not session_state.check_limit(
args, limit_type=session_state.Limit.COMMENTS, output=False
):
comment_chance = randint(1, 100)
if comment_chance > comment_percentage:
return False
UniversalActions(device)._swipe_points(
direction=Direction.DOWN, delta_y=randint(150, 250)
)
for _ in range(2):
comment_button = device.find(
resourceId=ResourceID.ROW_FEED_BUTTON_COMMENT,
className=ClassName.IMAGE_VIEW,
)
if comment_button.exists(True):
logger.info("Open comments of post.")
comment_button.click()
random_sleep()
comment_box = device.find(
resourceId=ResourceID.LAYOUT_COMMENT_THREAD_EDITTEXT
)
comment = load_random_comment()
logger.info(
f"Write comment: {comment}", extra={"color": f"{Fore.CYAN}"}
)
comment_box.set_text(comment)
random_sleep()
post_button = device.find(
resourceId=ResourceID.LAYOUT_COMMENT_THREAD_POST_BUTTON_CLICK_AREA
)
post_button.click()
random_sleep()
detect_block(device)
device.back()
logger.debug("Close keyboard.")
just_post = device.find(
resourceId=ResourceID.ROW_COMMENT_TEXTVIEW_COMMENT,
textMatches=f"{my_username} {comment}",
)
if just_post.exists(True):
logger.info("Comment succeed.", extra={"color": f"{Fore.GREEN}"})
session_state.totalComments += 1
else:
logger.warning("Failed to check if comment succeed.")
random_sleep(1, 2)
logger.info("Go back to post view.")
device.back()
return True
else:
UniversalActions(device)._swipe_points(
direction=Direction.DOWN, delta_y=randint(150, 250)
)
continue
return False


def load_random_comment():
file_name = "comments_list.txt"
if path.isfile(file_name):
with open(file_name, "r") as f:
lines = f.read().splitlines()
return choice(lines)


def _follow(device, username, follow_percentage, args, session_state, swipe_amount):
if not session_state.check_limit(
args, limit_type=session_state.Limit.FOLLOWS, output=False
Expand Down
14 changes: 11 additions & 3 deletions GramAddict/core/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ def print_full_report(sessions):
f"Total likes: {session.totalLikes}",
extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
)
logger.info(
f"Total comments: {session.totalComments}",
extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
)
logger.info(
f"Total watched: {session.totalWatched}",
extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
Expand Down Expand Up @@ -117,13 +121,16 @@ def print_full_report(sessions):
f"Total likes: {total_likes}",
extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
)

total_comments = sum(session.totalComments for session in sessions)
logger.info(
f"Total comments: {total_comments}",
extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
)
total_watched = sum(session.totalWatched for session in sessions)
logger.info(
f"Total watched: {total_watched}",
extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
)

total_unfollowed = sum(session.totalUnfollowed for session in sessions)
logger.info(
f"Total unfollowed: {total_unfollowed}",
Expand All @@ -133,11 +140,12 @@ def print_full_report(sessions):

def print_short_report(source, session_state):
total_likes = session_state.totalLikes
total_comments = session_state.totalComments
total_watched = session_state.totalWatched
total_followed = sum(session_state.totalFollowed.values())
interactions = session_state.successfulInteractions.get(source, 0)
logger.info(
f"Session progress: {total_likes} likes, {total_watched} watched, {total_followed} followed, {interactions} successful interaction(s) for {source}",
f"Session progress: {total_likes} likes, {total_comments} comments, {total_watched} watched, {total_followed} followed, {interactions} successful interaction(s) for {source}",
extra={"color": f"{Style.BRIGHT}{Fore.YELLOW}"},
)

Expand Down
7 changes: 7 additions & 0 deletions GramAddict/core/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ def __init__(self, APP_ID):
)
self.IMAGE_BUTTON = f"{APP_ID}:id/image_button"
self.LANGUAGE_LIST_LOCALE = f"{APP_ID}:id/language_locale_list"
self.LAYOUT_COMMENT_THREAD_EDITTEXT = (
f"{APP_ID}:id/layout_comment_thread_edittext"
)
self.LAYOUT_COMMENT_THREAD_POST_BUTTON_CLICK_AREA = (
f"{APP_ID}:id/layout_comment_thread_post_button_click_area"
)
self.LIST = "android:id/list"
self.MEDIA_GROUP = f"{APP_ID}:id/media_group"
self.MENU_SETTINGS_ROW = f"{APP_ID}:id/menu_settings_row"
Expand All @@ -43,6 +49,7 @@ def __init__(self, APP_ID):
self.REEL_VIEWER_IMAGE_VIEW = f"{APP_ID}:id/reel_viewer_image_view"
self.REEL_VIEWER_TIMESTAMP = f"{APP_ID}:id/reel_viewer_timestamp"
self.REEL_VIEWER_TITLE = f"{APP_ID}:id/reel_viewer_title"
self.ROW_COMMENT_TEXTVIEW_COMMENT = f"{APP_ID}:id/row_comment_textview_comment"
self.ROW_FEED_BUTTON_COMMENT = f"{APP_ID}:id/row_feed_button_comment"
self.ROW_FEED_BUTTON_LIKE = f"{APP_ID}:id/row_feed_button_like"
self.ROW_FEED_COMMENT_TEXTVIEW_LAYOUT = (
Expand Down
28 changes: 21 additions & 7 deletions GramAddict/core/session_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class SessionState:
successfulInteractions = {}
totalFollowed = {}
totalLikes = 0
totalComments = 0
totalWatched = 0
totalUnfollowed = 0
removedMassFollowers = []
Expand All @@ -34,6 +35,7 @@ def __init__(self, configs):
self.successfulInteractions = {}
self.totalFollowed = {}
self.totalLikes = 0
self.totalComments = 0
self.totalWatched = 0
self.totalUnfollowed = 0
self.removedMassFollowers = []
Expand Down Expand Up @@ -65,6 +67,8 @@ def check_limit(self, args, limit_type=None, output=False):
total_likes = self.totalLikes >= int(likes_limit)
follow_limit = get_value(args.total_follows_limit, None, 50)
total_followed = sum(self.totalFollowed.values()) >= int(follow_limit)
comments_limit = get_value(args.total_comments_limit, None, 50)
total_comments = self.totalComments >= int(comments_limit)
watch_limit = get_value(args.total_watches_limit, None, 50)
total_watched = self.totalWatched >= int(watch_limit)
success_limit = get_value(args.total_successful_interactions_limit, None, 100)
Expand All @@ -77,6 +81,7 @@ def check_limit(self, args, limit_type=None, output=False):
session_info = [
"Checking session limits:",
f"- Total Likes:\t\t\t\t{'Limit Reached' if total_likes else 'OK'} ({self.totalLikes}/{likes_limit})",
f"- Total Comments:\t\t\t\t{'Limit Reached' if total_likes else 'OK'} ({self.totalComments}/{comments_limit})",
f"- Total Followed:\t\t\t\t{'Limit Reached' if total_followed else 'OK'} ({sum(self.totalFollowed.values())}/{follow_limit})",
f"- Total Watched:\t\t\t\t{'Limit Reached' if total_watched else 'OK'} ({self.totalWatched}/{watch_limit})",
f"- Total Successful Interactions:\t\t{'Limit Reached' if total_successful else 'OK'} ({sum(self.successfulInteractions.values())}/{success_limit})",
Expand All @@ -102,32 +107,39 @@ def check_limit(self, args, limit_type=None, output=False):
logger.debug(session_info[1])
return total_likes or (total_interactions or total_successful)

elif limit_type == SessionState.Limit.FOLLOWS:
elif limit_type == SessionState.Limit.COMMENTS:
if output:
logger.info(session_info[2])
else:
logger.debug(session_info[2])
return total_followed or (total_interactions or total_successful)
return total_comments or (total_interactions or total_successful)

elif limit_type == SessionState.Limit.WATCHES:
elif limit_type == SessionState.Limit.FOLLOWS:
if output:
logger.info(session_info[3])
else:
logger.debug(session_info[3])
return total_watched or (total_interactions or total_successful)
return total_followed or (total_interactions or total_successful)

elif limit_type == SessionState.Limit.SUCCESS:
elif limit_type == SessionState.Limit.WATCHES:
if output:
logger.info(session_info[4])
else:
logger.debug(session_info[4])
return total_successful or total_interactions
return total_watched or (total_interactions or total_successful)

elif limit_type == SessionState.Limit.TOTAL:
elif limit_type == SessionState.Limit.SUCCESS:
if output:
logger.info(session_info[5])
else:
logger.debug(session_info[5])
return total_successful or total_interactions

elif limit_type == SessionState.Limit.TOTAL:
if output:
logger.info(session_info[6])
else:
logger.debug(session_info[6])
return total_interactions or total_successful

def is_finished(self):
Expand All @@ -136,6 +148,7 @@ def is_finished(self):
class Limit(Enum):
ALL = auto()
LIKES = auto()
COMMENTS = auto()
FOLLOWS = auto()
WATCHES = auto()
SUCCESS = auto()
Expand All @@ -152,6 +165,7 @@ def default(self, session_state: SessionState):
),
"total_followed": sum(session_state.totalFollowed.values()),
"total_likes": session_state.totalLikes,
"total_comments": session_state.totalComments,
"total_watched": session_state.totalWatched,
"total_unfollowed": session_state.totalUnfollowed,
"start_time": str(session_state.startTime),
Expand Down
14 changes: 14 additions & 0 deletions GramAddict/plugins/core_arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,18 @@ def __init__(self):
"help": "delete the user from the file after processing it",
"action": "store_true",
},
{
"arg": "--comment-percentage",
"nargs": None,
"help": "comment given percentage of interacted users, 0 by default",
"metavar": "50",
"default": "0",
},
{
"arg": "--total-comments-limit",
"nargs": None,
"help": "limit on total comments per session, disabled by default",
"metavar": "10-90",
"default": "0",
},
]
3 changes: 3 additions & 0 deletions GramAddict/plugins/force_interact.dis
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ class ForceIteract(Plugin):
stories_percentage,
int(args.follow_percentage),
int(args.follow_limit) if args.follow_limit else None,
int(self.args.comment_percentage),
plugin,
storage,
profile_filter,
Expand All @@ -151,6 +152,7 @@ class ForceIteract(Plugin):
stories_percentage,
follow_percentage,
follow_limit,
comment_percentage,
current_job,
storage,
profile_filter,
Expand All @@ -166,6 +168,7 @@ class ForceIteract(Plugin):
stories_count=stories_count,
stories_percentage=stories_percentage,
follow_percentage=follow_percentage,
comment_percentage=comment_percentage,
on_like=on_like,
on_watch=on_watch,
profile_filter=profile_filter,
Expand Down
3 changes: 3 additions & 0 deletions GramAddict/plugins/interact_blogger_followers.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ def job():
stories_percentage,
int(self.args.follow_percentage),
int(self.args.follow_limit) if self.args.follow_limit else None,
int(self.args.comment_percentage),
plugin,
storage,
profile_filter,
Expand Down Expand Up @@ -149,6 +150,7 @@ def handle_blogger(
stories_percentage,
follow_percentage,
follow_limit,
comment_percentage,
current_job,
storage,
profile_filter,
Expand All @@ -164,6 +166,7 @@ def handle_blogger(
stories_count=stories_count,
stories_percentage=stories_percentage,
follow_percentage=follow_percentage,
comment_percentage=comment_percentage,
on_like=on_like,
on_watch=on_watch,
profile_filter=profile_filter,
Expand Down
Loading

0 comments on commit 21cdd58

Please sign in to comment.