Repository: InstaPy/InstaPy

Issue:
Selenium exception: Cannot read property 'edges' of undefined
Hi everyone, i just git pulled then I got this error while using **interact_user_followers**

```
Traceback (most recent call last):
  File "like.py", line 57, in <module>
    session.interact_user_followers(['user'], amount=1500, randomize=False)
  File "/Users/users/Desktop/instagram/InstaPy/instapy/instapy.py", line 2799, in interact_user_followers
    self.user_interact_media)
  File "/Users/users/Desktop/instagram/InstaPy/instapy/instapy.py", line 2189, in interact_by_users
    self.logger))
  File "/Users/users/Desktop/instagram/InstaPy/instapy/like_util.py", line 537, in check_link
    ''', user_name)
  File "/usr/local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 636, in execute_script
    'args': converted_args})['value']
  File "/usr/local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: unknown error: Cannot read property 'edges' of undefined
  (Session info: chrome=)
  (Driver info: chromedriver= (),platform=Mac OS X 10.13.3 x86_64)
```


This is the code I am using:
```session.set_simulation(enabled=False)
session.set_skip_users(skip_private=True,
                       private_percentage=100,
                       skip_no_profile_pic=False,
                       no_profile_pic_percentage=100,
                       skip_business=False,
                       business_percentage=100,
                       skip_business_categories=[],
                       dont_skip_business_categories=[])
session.set_user_interact(amount=2, randomize=True, percentage=100, media='Photo')
session.set_do_like(enabled=True, percentage=100)
session.interact_user_followers(['user'], amount=1500, randomize=False)
```


Discussion:
same problem here.. what's the solution?
Same! I'm getting this over and over
same

same issue
I've been having the same issue while running this on Windows and Rasbian, although on Raspbian the last line of the error says "**shortcode_media.edge_media_to_comment is undefined**," but I assume it's the same error.

One thing I've noticed on both environments is that I can run my quickstart.py script without any errors while using my extra IG account - everything runs perfectly fine. But any scripts I try to run with my main IG account will result in these errors. The script fails any time an action is attempted (liking a photo, following, unfollowing, etc.). Not sure of any fixes.
it is a / b testing for media['edge_media_to_comment']
```
        # first comment might be owner hashtags
        try:
            try:
                image_first_comment = media['edge_media_to_comment']['edges'][0]['node']['text']
            except KeyError:
                image_first_comment = media['edge_media_to_parent_comment']['edges'][0]['node']['text']         
        except IndexError: # no comment in this section
            pass
```
in verify_commenting:
```
        if len(mand_words) != 0:
            try:
                try:
                    post_desc = browser.execute_script(
                        "return window._sharedData.entry_data."
                        "PostPage[0].graphql.shortcode_media."
                        "edge_media_to_caption.edges[0]['node']['text']"
                        ).lower()

                except WebDriverException:
                    post_desc = browser.execute_script(
                        "return window._sharedData.entry_data."
                        "PostPage[0].graphql.shortcode_media."
                        "edge_media_preview_comment.edges[0]['node']['text']"
                        ).lower()

            except Exception as e:
                post_desc = None

            try:
                try:
                    first_comment = browser.execute_script(
                        "return window._sharedData.entry_data."
                        "PostPage[0].graphql.shortcode_media."
                        "edge_media_to_comment.edges[0]['node']['text']"
                        ).lower()

                except WebDriverException:
                    first_comment = browser.execute_script(
                        "return window._sharedData.entry_data."
                        "PostPage[0].graphql.shortcode_media."
                        "edge_media_preview_comment.edges[0]['node']['text']"
                        ).lower()

            except Exception as e:
                first_comment = None
```
in get_comments_count:
```
def get_comments_count(browser, logger):
    """ Get the number of total comments in the post """
    try:
        try:
            comments_count = browser.execute_script(
                "return window._sharedData.entry_data."
                "PostPage[0].graphql.shortcode_media."
                "edge_media_to_comment.count")
    
        except WebDriverException:
            comments_count = browser.execute_script(
                "return window._sharedData.entry_data."
                "PostPage[0].graphql.shortcode_media."
                "edge_media_preview_comment.count")

    except Exception as e:
        msg = ("Failed to get comments' count!\n\t{}"
               .format(str(e).encode("utf-8")))
        return None, msg

    if not comments_count:
        if comments_count == 0:
            msg = "There are no any comments in the post."
            return 0, msg
        else:
            msg = "Couldn't get comments' count."
            return None, msg


    return comments_count, "Success"
```
I'm having the same issue, the script start, it start to retrieve the posts to interact with and then stops.

> ```
>         # first comment might be owner hashtags
>         try:
>             try:
>                 image_first_comment = media['edge_media_to_comment']['edges'][0]['node']['text']
>             except KeyError:
>                 image_first_comment = media['edge_media_to_parent_comment']['edges'][0]['node']['text']         
>         except IndexError: # no comment in this section
>             pass
> ```

Where does this code goes? @sionking 
> > ```
> >         # first comment might be owner hashtags
> >         try:
> >             try:
> >                 image_first_comment = media['edge_media_to_comment']['edges'][0]['node']['text']
> >             except KeyError:
> >                 image_first_comment = media['edge_media_to_parent_comment']['edges'][0]['node']['text']         
> >         except IndexError: # no comment in this section
> >             pass
> > ```
> 
> Where does this code goes? @sionking

You might not have it ...
> > > ```
> > >         # first comment might be owner hashtags
> > >         try:
> > >             try:
> > >                 image_first_comment = media['edge_media_to_comment']['edges'][0]['node']['text']
> > >             except KeyError:
> > >                 image_first_comment = media['edge_media_to_parent_comment']['edges'][0]['node']['text']         
> > >         except IndexError: # no comment in this section
> > >             pass
> > > ```
> > 
> > 
> > Where does this code goes? @sionking
> 
> You might not have it ...

I've updated my local repository and still can't figure out where to put this code
> > > ```
> > >         # first comment might be owner hashtags
> > >         try:
> > >             try:
> > >                 image_first_comment = media['edge_media_to_comment']['edges'][0]['node']['text']
> > >             except KeyError:
> > >                 image_first_comment = media['edge_media_to_parent_comment']['edges'][0]['node']['text']         
> > >         except IndexError: # no comment in this section
> > >             pass
> > > ```
> > 
> > 
> > Where does this code goes? @sionking
> 
> You might not have it ...

In which file should we update the code ? @sionking 
thanks !
@andreademasi I have some code not in this repo .... so ignore this
> @andreademasi I have some code not in this repo .... so ignore this

Ok so i've done the other modifications but the script is still not working.. thanks for your help anyway!
There might be some more places...
this change is good
WE now can replay to comments
I'm trying to fix the code by myself, i just need to apply the changes suggested by @sionking into like_util.py where the error is thrown. Basically `media['edge_media_to_comment']['edges']` needs to be replaced by `media['edge_media_preview_comment']['edges']`
Here's the fix which is working for now.
In like_util.py in check_link() from line 514 to 609 approximately:

```
    """Gets the description of the post's link and checks for the dont_like
    tags"""
    graphql = 'graphql' in post_page[0]
    if graphql:
        media = post_page[0]['graphql']['shortcode_media']
        is_video = media['is_video']
        user_name = media['owner']['username']
        image_text = media['edge_media_to_caption']['edges']
        image_text = image_text[0]['node']['text'] if image_text else None
        location = media['location']
        location_name = location['name'] if location else None
        try:
            owner_comments = browser.execute_script('''
                latest_comments = window._sharedData.entry_data.PostPage[
                0].graphql.shortcode_media.edge_media_to_comment.edges;
                if (latest_comments === undefined) {
                    latest_comments = Array();
                    owner_comments = latest_comments
                        .filter(item => item.node.owner.username == arguments[0])
                        .map(item => item.node.text)
                        .reduce((item, total) => item + '\\n' + total, '');
                    return owner_comments;}
                else {
                    return null;}
            ''', user_name)

        except WebDriverException:
            owner_comments = browser.execute_script('''
                latest_comments = window._sharedData.entry_data.PostPage[
                0].graphql.shortcode_media.edge_media_preview_comment.edges;
                if (latest_comments === undefined) {
                    latest_comments = Array();
                    owner_comments = latest_comments
                        .filter(item => item.node.owner.username == arguments[0])
                        .map(item => item.node.text)
                        .reduce((item, total) => item + '\\n' + total, '');
                    return owner_comments;}
                else {
                    return null;}
            ''', user_name)


    else:
        media = post_page[0]['media']
        is_video = media['is_video']
        user_name = media['owner']['username']
        image_text = media['caption']
        try:
            owner_comments = browser.execute_script('''
                latest_comments = window._sharedData.entry_data.PostPage[
                0].graphql.shortcode_media.edge_media_to_comment.edges;
                if (latest_comments === undefined) {
                    latest_comments = Array();
                    owner_comments = latest_comments
                        .filter(item => item.node.owner.username == arguments[0])
                        .map(item => item.node.text)
                        .reduce((item, total) => item + '\\n' + total, '');
                    return owner_comments;}
                else {
                    return null;}
            ''', user_name)

        except WebDriverException:
            owner_comments = browser.execute_script('''
                latest_comments = window._sharedData.entry_data.PostPage[
                0].graphql.shortcode_media.edge_media_preview_comment.edges;
                if (latest_comments === undefined) {
                    latest_comments = Array();
                    owner_comments = latest_comments
                        .filter(item => item.node.owner.username == arguments[0])
                        .map(item => item.node.text)
                        .reduce((item, total) => item + '\\n' + total, '');
                    return owner_comments;}
                else {
                    return null;}
            ''', user_name)

    if owner_comments == '':
        owner_comments = None

    """Append owner comments to description as it might contain further tags"""
    if image_text is None:
        image_text = owner_comments

    elif owner_comments:
        image_text = image_text + '\n' + owner_comments

    """If the image still has no description gets the first comment"""
    if image_text is None:
        if graphql:
                image_text = media['edge_media_preview_comment']['edges']
                image_text = image_text[0]['node']['text'] if image_text else None
```
I've enclosed every occurrence of `media['edge_media_to_comment']['edges']` in a try-except, this may be needed in other places too.
@andreademasi  not replaced, but use both!
some might be using old version/
You're right, can you fix the code I posted before?
did someone find a fix for this?
There are two places changes must be made (both in [`like_util.py`](https://github.com/timgrossmann/InstaPy/blob/master/instapy/like_util.py)):

Line [527](https://github.com/timgrossmann/InstaPy/blob/master/instapy/like_util.py#L527):

    0].graphql.shortcode_media.edge_media_to_comment.edges;

Line [571](https://github.com/timgrossmann/InstaPy/blob/master/instapy/like_util.py#L571):

    image_text = media['edge_media_to_comment']['edges']

For both of these, change `edge_media_to_comment` to `edge_media_preview_comment`. The try-accept method above is probably the best way to do it in a patch, but there should be a way to detect which it is and select the proper name from the start without waiting for a crash to occur.
> There are two places changes must be made (both in [`like_util.py`](https://github.com/timgrossmann/InstaPy/blob/master/instapy/like_util.py)):
> 
> Line [527](https://github.com/timgrossmann/InstaPy/blob/master/instapy/like_util.py#L527):
> 
> ```
> 0].graphql.shortcode_media.edge_media_to_comment.edges;
> ```
> Line [571](https://github.com/timgrossmann/InstaPy/blob/master/instapy/like_util.py#L571):
> 
> ```
> image_text = media['edge_media_to_comment']['edges']
> ```
> For both of these, change `edge_media_to_comment` to `edge_media_preview_comment`. The try-accept method above is probably the best way to do it in a patch, but there should be a way to detect which it is and select the proper name from the start without waiting for a crash to occur.

For me it worked!
@sionking @ReagentX Could you guys create a PR for that change, please?

@reagentx thank you so much it worked. can't believe it's that simple. And yes @timgrossmann we should create a PR
@timgrossmann I don’t know that just changing those two lines is the proper fix; I think this is for an A/B test so if I push that fix it will break other accounts. Need to implement a way to find what string to use.

Before I make a PR, can someone confirm for me that this is the case? The only account I work with happens to be in the A/B test. Does the repo currently work with some accounts?

Edit: per some people in Discord, this does not affect all accounts.
@ReagentX Thank you for getting back so quickly.
It seems that the option @sionking proposed is suitable for both cases, isn't it?


Possibly, but it won't handle future changes. If you think `try… except` is appropriate here I don't mind, but I think there should be a way to detect the string that they use so we don't have to add except blocks for every possible future permutation.

Resolving patch:
diff --git a/instapy/like_util.py b/instapy/like_util.py
--- a/instapy/like_util.py
+++ b/instapy/like_util.py
@@ -465,6 +465,17 @@ def get_links_for_username(browser,
     return links[:amount]
 
 
+def get_media_edge_comment_string(media):
+    """AB test (Issue 3712) alters the string for media edge, this resoves it"""
+    options = ['edge_media_to_comment', 'edge_media_preview_comment']
+    for option in options:
+        try:
+            media[option]
+        except KeyError:
+            continue
+        return option
+
+
 def check_link(browser, post_link, dont_like, mandatory_words,
                mandatory_language, mandatory_character,
                is_mandatory_character, check_character_set, ignore_if_contains,
@@ -522,19 +533,21 @@ def check_link(browser, post_link, dont_like, mandatory_words,
         image_text = image_text[0]['node']['text'] if image_text else None
         location = media['location']
         location_name = location['name'] if location else None
+        media_edge_string = get_media_edge_comment_string(media)
+        # double {{ allows us to call .format here:
         owner_comments = browser.execute_script('''
             latest_comments = window._sharedData.entry_data.PostPage[
-            0].graphql.shortcode_media.edge_media_to_comment.edges;
-            if (latest_comments === undefined) {
+            0].graphql.shortcode_media.{}.edges;
+            if (latest_comments === undefined) {{
                 latest_comments = Array();
                 owner_comments = latest_comments
                     .filter(item => item.node.owner.username == arguments[0])
                     .map(item => item.node.text)
                     .reduce((item, total) => item + '\\n' + total, '');
-                return owner_comments;}
-            else {
-                return null;}
-        ''', user_name)
+                return owner_comments;}}
+            else {{
+                return null;}}
+        '''.format(media_edge_string), user_name)
 
     else:
         media = post_page[0]['media']
@@ -568,7 +581,8 @@ def check_link(browser, post_link, dont_like, mandatory_words,
     """If the image still has no description gets the first comment"""
     if image_text is None:
         if graphql:
-            image_text = media['edge_media_to_comment']['edges']
+            media_edge_string = get_media_edge_comment_string(media)
+            image_text = media[media_edge_string]['edges']
             image_text = image_text[0]['node']['text'] if image_text else None
 
         else:


Test patch: