Skip to content

Commit 8c74ab2

Browse files
authored
Merge pull request #5990 from elulcao/pr_liked_comment
PR comment photo already liked and minor fixes
2 parents 3716865 + 2986ea3 commit 8c74ab2

13 files changed

Lines changed: 281 additions & 163 deletions

CHANGELOG.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ The **goal** of this file is explaining to the users of our project the notable
55
_The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)_
66

77

8-
## [0.6.13] - UNRELEASED
8+
## [0.6.14] - UNRELEASED
9+
10+
## [0.6.13] - 2020-12-30
911

1012
### Added
1113

@@ -16,6 +18,7 @@ _The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
1618
- Two Factor Authentication check when acct is protected
1719
- Added Pull Request Template
1820
- Added function `accept_igcookie_dialogue` that clicks accept at IG cookie dialogue
21+
- Added `comment_liked_photo` to `set_do_comment` to be able to comment twice a photo that is already liked; deactivated by default
1922

2023
### Fixed
2124

@@ -32,6 +35,9 @@ _The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
3235
- Fixed `login_session` for issues when cookie cannot be loaded
3336
- Fixed `likes_dialog_close_xpath` to generic format
3437
- Fixed `validate_username` to navigate user profile to read their Bio
38+
- Fixed `Liked button now found, might be a video` that could be floodig general log
39+
- Fixed `logger.warn` to `logger.warning` as default warning in Python
40+
- Fixed xpath for `watch_story`
3541

3642
## [0.6.12] - 2020-10-26
3743

@@ -61,7 +67,6 @@ _The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6167
- issue where `getTitle` was timing out
6268
- `get_users_through_dialog_with_graphql` with a new try/except
6369

64-
6570
## [0.6.11] - 2020-09-25
6671

6772
### Added

instapy/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# flake8: noqa
22

33
# __variables__ with double-quoted values will be available in setup.py
4-
__version__ = "0.6.12"
4+
__version__ = "0.6.13"
55

66
from .instapy import InstaPy
77
from .util import smart_run

instapy/browser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ def proxy_authentication(browser, logger, proxy_username, proxy_password):
162162

163163
# FIXME: https://github.com/SeleniumHQ/selenium/issues/7239
164164
# this feauture is not working anymore due to the Selenium bug report above
165-
logger.warn(
165+
logger.warning(
166166
"Proxy Authentication is not working anymore due to the Selenium bug "
167167
"report: https://github.com/SeleniumHQ/selenium/issues/7239"
168168
)
@@ -179,7 +179,7 @@ def proxy_authentication(browser, logger, proxy_username, proxy_password):
179179
)
180180
alert_popup.accept()
181181
except Exception:
182-
logger.warn("Unable to proxy authenticate")
182+
logger.warning("Unable to proxy authenticate")
183183

184184

185185
def close_browser(browser, threaded_session, logger):

instapy/comment_util.py

Lines changed: 108 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
# -*- coding: utf-8 -*-
22
""" Module which handles the commenting features """
3-
3+
# import built-in & third-party modules
44
import random
55
import emoji
66

7+
# import InstaPy modules
78
from .time_util import sleep
89
from .util import update_activity
910
from .util import add_user_to_blacklist
1011
from .util import click_element
1112
from .util import get_action_delay
1213
from .util import explicit_wait
13-
from .util import extract_text_from_element
1414
from .util import web_address_navigator
1515
from .util import evaluate_mandatory_words
1616
from .event import Event
1717
from .quota_supervisor import quota_supervisor
1818
from .xpath import read_xpath
1919

20+
# import exceptions
2021
from selenium.common.exceptions import WebDriverException
2122
from selenium.common.exceptions import InvalidElementStateException
2223
from selenium.common.exceptions import NoSuchElementException
@@ -157,16 +158,14 @@ def verify_commenting(browser, maximum, minimum, logger):
157158
return False, disapproval_reason
158159

159160
if maximum is not None and comments_count > maximum:
160-
disapproval_reason = (
161-
"Not commented on this post! ~more comments exist"
162-
" off maximum limit at {}".format(comments_count)
161+
disapproval_reason = "Not commented on this post! ~more comments exist off maximum limit at {}".format(
162+
comments_count
163163
)
164164
return False, disapproval_reason
165165

166166
elif minimum is not None and comments_count < minimum:
167-
disapproval_reason = (
168-
"Not commented on this post! ~less comments exist"
169-
" off minumum limit at {}".format(comments_count)
167+
disapproval_reason = "Not commented on this post! ~less comments exist off minumum limit at {}".format(
168+
comments_count
170169
)
171170
return False, disapproval_reason
172171

@@ -238,106 +237,97 @@ def get_comments_on_post(
238237
browser, owner, poster, amount, post_link, ignore_users, randomize, logger
239238
):
240239
""" Fetch comments data on posts """
241-
242240
web_address_navigator(browser, post_link)
243241

244-
orig_amount = amount
242+
comments = []
243+
commenters = []
244+
245245
if randomize is True:
246246
amount = amount * 3
247247

248248
# check if commenting on the post is enabled
249-
commenting_state, msg = is_commenting_enabled(browser, logger)
250-
if commenting_state is not True:
251-
logger.info(msg)
252-
return None
253-
254-
# check if there are any comments in the post
255-
comments_count, msg = get_comments_count(browser, logger)
256-
if not comments_count:
257-
logger.info(msg)
249+
(commenting_approved, disapproval_reason,) = verify_commenting(
250+
browser,
251+
None,
252+
None,
253+
logger,
254+
)
255+
if not commenting_approved:
256+
logger.info(disapproval_reason)
258257
return None
259258

260-
# get comments & commenters information
261-
262-
# efficient location
263-
comments_block_XPath = read_xpath(get_comments_on_post.__name__, "comments_block")
264-
# path
259+
# get comments & commenters information path
265260
like_button_full_XPath = read_xpath(
266261
get_comments_on_post.__name__, "like_button_full_XPath"
267262
)
268263
unlike_button_full_XPath = read_xpath(
269264
get_comments_on_post.__name__, "unlike_button_full_XPath"
270265
)
271266

272-
comments = []
273-
commenters = []
274267
# wait for page fully load [IMPORTANT!]
275268
explicit_wait(browser, "PFL", [], logger, 10)
276269

277270
try:
278271
all_comment_like_buttons = browser.find_elements_by_xpath(
279272
like_button_full_XPath
280273
)
274+
281275
if all_comment_like_buttons:
282-
comments_block = browser.find_elements_by_xpath(comments_block_XPath)
283-
for comment_line in comments_block:
284-
commenter_elem = comment_line.find_element_by_xpath(
285-
read_xpath(get_comments_on_post.__name__, "commenter_elem")
286-
)
287-
commenter = extract_text_from_element(commenter_elem)
276+
commenter = None
277+
comment = None
278+
279+
data = browser.execute_script(
280+
"return window.__additionalData[Object.keys(window.__additionalData)].data."
281+
"graphql.shortcode_media.edge_media_to_parent_comment"
282+
)
283+
for value in data["edges"]:
284+
commenter = value["node"]["owner"]["username"]
285+
comment = value["node"]["text"]
286+
288287
if (
289288
commenter
290-
and commenter not in [owner, poster, ignore_users]
291289
and commenter not in commenters
290+
and commenter not in [owner, poster, ignore_users]
291+
and comment
292292
):
293293
commenters.append(commenter)
294-
else:
295-
continue
296-
297-
comment_elem = comment_line.find_elements_by_tag_name("span")[0]
298-
comment = extract_text_from_element(comment_elem)
299-
if comment:
300294
comments.append(comment)
301295
else:
302-
commenters.remove(commenters[-1])
303-
continue
296+
logger.info("Could not grab any commenter from this post")
304297

305298
else:
306299
comment_unlike_buttons = browser.find_elements_by_xpath(
307300
unlike_button_full_XPath
308301
)
302+
309303
if comment_unlike_buttons:
310304
logger.info(
311-
"There are {} comments on this post and all "
312-
"of them are already liked.".format(len(comment_unlike_buttons))
305+
"Grabbed {} comment(s) on this post and already liked.".format(
306+
len(comment_unlike_buttons)
307+
)
313308
)
314309
else:
315310
logger.info("There are no any comments available on this post.")
316311
return None
317312

318313
except NoSuchElementException:
319-
logger.info("Failed to get comments on this post.")
314+
logger.info("Failed to grab comments on this post.")
320315
return None
321316

322317
if not comments:
323-
logger.info("Could not grab any usable comments from this post..")
318+
logger.info("Could not grab any usable comments from this post...")
324319
return None
325320

326321
else:
327322
comment_data = list(zip(commenters, comments))
328323
if randomize is True:
329324
random.shuffle(comment_data)
330325

331-
if len(comment_data) < orig_amount:
332-
logger.info(
333-
"Could grab only {} usable comments from this post..".format(
334-
len(comment_data)
335-
)
336-
)
337-
else:
338-
logger.info(
339-
"Grabbed {} usable comments from this post..".format(len(comment_data))
326+
logger.info(
327+
"Grabbed only {} usable comment(s) from this post...".format(
328+
len(comment_data)
340329
)
330+
)
341331

342332
return comment_data
343333

@@ -382,29 +372,52 @@ def get_comments_count(browser, logger):
382372
".graphql.shortcode_media.edge_media_preview_comment.count"
383373
)
384374

385-
# media_edge_string = get_media_edge_comment_string(media)
386-
# comments_count = media[media_edge_string]["count"]
387-
388375
except Exception as e:
389-
try:
390-
comments_count = browser.execute_script(
391-
"return window.__additionalData[Object.keys(window.__additionalData)[0]].data"
392-
".graphql.shortcode_media.edge_media_preview_comment.count"
393-
)
376+
msg = "Failed to get comments' count!\n\t{}".format(str(e).encode("utf-8"))
377+
return None, msg
394378

395-
except Exception as e:
396-
msg = "Failed to get comments' count!\n\t{}".format(str(e).encode("utf-8"))
397-
return None, msg
379+
return comments_count, "Success"
398380

399-
# if not comments_count:
400-
# if comments_count == 0:
401-
# msg = "There are no any comments in the post."
402-
# return 0, msg
403-
# else:
404-
# msg = "Couldn't get comments' count."
405-
# return None, msg
406381

407-
return comments_count, "Success"
382+
def verify_commented_image(browser, link, owner, logger):
383+
""" Fetch comments data on posts to determine if already commented """
384+
385+
web_address_navigator(browser, link)
386+
387+
# wait for page fully load [IMPORTANT!]
388+
explicit_wait(browser, "PFL", [], logger, 10)
389+
390+
try:
391+
commenter = None
392+
comment = None
393+
data = browser.execute_script(
394+
"return window.__additionalData[Object.keys(window.__additionalData)].data."
395+
"graphql.shortcode_media.edge_media_to_parent_comment"
396+
)
397+
for value in data["edges"]:
398+
commenter = value["node"]["owner"]["username"]
399+
comment = value["node"]["text"]
400+
401+
if commenter and commenter == owner:
402+
message = (
403+
"--> The post has already been commented on before: '{}'".format(
404+
comment
405+
)
406+
)
407+
return True, message
408+
409+
except NoSuchElementException:
410+
# Cannot be determined if the post has been comment by InstaPy user,
411+
# and then it will not be commented until next loop, maybe comments
412+
# on the post have been limited. Return True, to emulate or assume the
413+
# post has been commented by user.
414+
message = (
415+
"--> Failed to get comments on this post, will not comment the post..."
416+
)
417+
return True, message
418+
419+
message = "--> Could not found owner's comment in this post, trying to comment..."
420+
return None, message
408421

409422

410423
def process_comments(
@@ -414,9 +427,11 @@ def process_comments(
414427
max_comments,
415428
min_comments,
416429
comments_mandatory_words,
430+
owner,
417431
user_name,
418432
blacklist,
419433
browser,
434+
link,
420435
logger,
421436
logfolder,
422437
publish=True,
@@ -444,6 +459,7 @@ def process_comments(
444459
browser,
445460
logger,
446461
)
462+
447463
if not commenting_approved:
448464
logger.info(disapproval_reason)
449465
return False
@@ -453,6 +469,21 @@ def process_comments(
453469

454470
# smart commenting
455471
if comments and publish:
472+
# Check if InstaPy already commented on this post, it could be the
473+
# case that the image has been liked (manually) but not commented, so
474+
# we want to comment the post like usually we do.
475+
commented_image, message = verify_commented_image(browser, link, owner, logger)
476+
477+
if commented_image:
478+
# The post has already been commented, either manually or InstaPy
479+
# Commenting twice by InstaPy user is not allowd by now or could
480+
# not get comments on this post to check if InstaPy user commented
481+
# before, so will not comment until next check
482+
logger.info(message)
483+
return False
484+
else:
485+
logger.info(message)
486+
456487
comment_state, _ = comment_image(
457488
browser,
458489
user_name,
@@ -462,4 +493,8 @@ def process_comments(
462493
logfolder,
463494
)
464495

496+
# Return to the target uset page
497+
user_link = "https://www.instagram.com/{}/".format(user_name)
498+
web_address_navigator(browser, user_link)
499+
465500
return comment_state

instapy/feed_util.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
""" Module that handles the like features """
2+
# import built-in & third-party modules
3+
4+
# import InstaPy modules
25
from .util import update_activity
36

7+
# import exceptions
48
from selenium.common.exceptions import NoSuchElementException
59

610
LIKE_TAG_CLASS = "coreSpriteHeartOpen"
@@ -33,7 +37,7 @@ def get_like_on_feed(browser, amount):
3337
break
3438
yield button
3539

36-
print("---> Total Likes uptil now ->", likes_performed)
40+
print("--> Total Likes uptil now ->", likes_performed)
3741

3842
browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
3943
update_activity(browser, state=None)

0 commit comments

Comments
 (0)