예제 #1
0
    def update(self, obj=None, settings={}):
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if not isinstance(obj, UpdatableElement) and not obj is None:
            raise TypeError("obj must be UpdatableElement type or None")

        query = "https://www.instagram.com/"
        if not obj is None:
            query += obj._base_url + getattr(obj, obj._primary_key)

        response = self._get_request(query, **settings)

        try:
            match = re.search(
                r"<script[^>]*>\s*window._sharedData\s*=\s*((?!<script>).*)\s*;\s*</script>",
                response.text,
            )
            data = json.loads(match.group(1))
            self._rhx_gis = data["rhx_gis"]
            self._csrf_token = data["config"]["csrf_token"]

            if obj is None:
                return None

            data = data["entry_data"]
            for key in obj._entry_data_path:
                data = data[key]
            obj._set_data(data)

            return data
        except (AttributeError, KeyError, ValueError) as exception:
            raise UnexpectedResponse(exception, response.url, response.text)
예제 #2
0
    def get_likes(self, media, settings={}):
        # Check data
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if not isinstance(media, Media):
            raise TypeError("'media' must be Media type")

        data = self.update(media, settings)
        likes = []
        
        try:
            data = data["edge_media_preview_like"]
            edges = data["edges"]
            
            for edge in edges:
                node = edge["node"]
                account = Account(node["username"])
                account.id = node["id"]
                account.profile_pic_url = node["profile_pic_url"]
                if "is_verified" in node:
                    account.is_verified = node["is_verified"]
                if "full_name" in node:
                    account.full_name = node["full_name"]
                
                media.likes.add(account)
                likes.append(account)
        except (ValueError, KeyError):
            raise UnexpectedResponse()
        return likes, None
예제 #3
0
    def get_likes(self, media, pointer=None, count=20, settings={}, limit=50):
        if not isinstance(media, Media):
            raise TypeError("'media' must be Media type")
        if not isinstance(count, int):
            raise TypeError("'count' must be int type")
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if not isinstance(limit, int):
            raise TypeError("'limit' must be int type")

        self.update(media, settings)

        if pointer:
            variables_string = '{{"shortcode":"{shortcode}","first":{first},"after":"{after}"}}'
        else:
            variables_string = '{{"shortcode":"{shortcode}","first":{first}}}'
        likes = []

        while True:
            data = {"shortcode": media.code, "first": min(limit, count)}
            if pointer:
                data["after"] = pointer

            response = self._graphql_request(
                query_hash="1cb6ec562846122743b61e492c85999f",
                variables=variables_string.format(**data),
                settings=settings,
            )

            try:
                data = response.json(
                )["data"]["shortcode_media"]["edge_liked_by"]
                edges = data["edges"]
                page_info = data["page_info"]
                media.likes_count = data["count"]

                for index in range(min(len(edges), count)):
                    node = edges[index]["node"]
                    account = Account(node["username"])
                    account.id = node["id"]
                    account.profile_pic_url = node["profile_pic_url"]
                    account.is_verified = node["is_verified"]
                    account.full_name = node["full_name"]
                    media.likes.add(account)
                    likes.append(account)

                if page_info["has_next_page"]:
                    pointer = page_info["end_cursor"]
                else:
                    pointer = None

                if len(edges) < count and page_info["has_next_page"]:
                    count = count - len(edges)
                    variables_string = \
                        '{{"shortcode":"{shortcode}","first":{first},"after":"{after}"}}'
                else:
                    return likes, pointer
            except (ValueError, KeyError) as exception:
                raise UnexpectedResponse(exception, response.url,
                                         response.text)
예제 #4
0
    def add_comment(self, media, text, settings={}):
        if not isinstance(media, Media):
            raise TypeError("'media' must be Media type")
        if not isinstance(text, str):
            raise TypeError("'text' must be str type")
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if media.id is None:
            self.update(media)

        response = self._action_request(
            referer="https://www.instagram.com/p/%s/" % media.code,
            url="https://www.instagram.com/web/comments/%s/add/" % media.id,
            data={"comment_text": text},
        )

        try:
            data = response.json()
            if data["status"] == "ok":
                comment = Comment(
                    data["id"],
                    media=media,
                    owner=self,
                    text=data["text"],
                    created_at=data["created_time"],
                )
                return comment
            return None
        except (ValueError, KeyError) as exception:
            raise UnexpectedResponse(exception, response.url, response.text)
예제 #5
0
    def __init__(self, login, password, settings={}):
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")

        Account.__init__(self, login)
        Agent.__init__(self, settings=settings)

        data = {"username": self.login, "password": password}

        if "headers" in settings:
            settings["headers"]["X-CSRFToken"] = self._csrf_token
            settings["headers"]["referer"] = "https://www.instagram.com/"
        else:
            settings["headers"] = {
                "X-CSRFToken": self._csrf_token,
                "referer": "https://www.instagram.com/",
            }

        response = self._post_request(
            "https://www.instagram.com/accounts/login/ajax/",
            data=data,
            **settings,
        )

        try:
            data = response.json()
            if not data["authenticated"]:
                raise AuthException(self.login)
        except (ValueError, KeyError) as exception:
            raise UnexpectedResponse(exception, response.url, response.text)
예제 #6
0
    def feed(self, pointer=None, count=12, settings={}, limit=50):
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if not isinstance(count, int):
            raise TypeError("'count' must be int type")
        if not isinstance(limit, int):
            raise TypeError("'limit' must be int type")

        variables_string = '{{"fetch_media_item_count":{first},"fetch_media_item_cursor":"{after}",\
            "fetch_comment_count":4,"fetch_like":10,"has_stories":false}}'

        feed = []

        while True:
            response = self._graphql_request(
                query_hash="485c25657308f08317c1e4b967356828",
                variables=variables_string.format(
                    after=pointer,
                    first=min(limit, count),
                ) if pointer else "{}",
                settings=settings,
            )

            try:
                data = response.json(
                )["data"]["user"]["edge_web_feed_timeline"]
                edges = data["edges"]
                page_info = data["page_info"]
                length = len(edges)

                for index in range(min(length, count)):
                    node = edges[index]["node"]
                    if not "shortcode" in node:
                        length -= 1
                        continue
                    m = Media(node["shortcode"])
                    m._set_data(node)
                    feed.append(m)

                if page_info["has_next_page"]:
                    pointer = page_info["end_cursor"]
                else:
                    pointer = None

                if length < count and page_info["has_next_page"]:
                    count = count - length
                else:
                    return feed, pointer
            except (ValueError, KeyError) as exception:
                raise UnexpectedResponse(exception, response.url,
                                         response.text)
예제 #7
0
    def stories(self, settings={}):
        while True:
            response = self._graphql_request(
                query_hash="60b755363b5c230111347a7a4e242001",
                variables='{"only_stories":true}',
                settings=settings,
            )

            try:
                data = response.json(
                )["data"]["user"]["feed_reels_tray"]["edge_reels_tray_to_reel"]
                return [Story(edge["node"]["id"]) for edge in data["edges"]]
            except (ValueError, KeyError) as exception:
                raise UnexpectedResponse(exception, response.url,
                                         response.text)
예제 #8
0
    def unlike(self, media, settings={}):
        if not isinstance(media, Media):
            raise TypeError("'media' must be Media type")
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if media.id is None:
            self.update(media)

        response = self._action_request(
            referer="https://www.instagram.com/p/%s/" % media.code,
            url="https://www.instagram.com/web/likes/%s/unlike/" % media.id,
        )

        try:
            return response.json()["status"] == "ok"
        except (ValueError, KeyError) as exception:
            raise UnexpectedResponse(exception, response.url, response.text)
예제 #9
0
    def unfollow(self, account, settings={}):
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if not isinstance(account, Account):
            raise TypeError("'account' must be Account type")
        if account.id is None:
            self.update(account)

        response = self._action_request(
            referer="https://www.instagram.com/%s" % account.login,
            url="https://www.instagram.com/web/friendships/%s/unfollow/" %
            account.id,
        )

        try:
            return response.json()["status"] == "ok"
        except (ValueError, KeyError) as exception:
            raise UnexpectedResponse(exception, response.url, response.text)
예제 #10
0
    def delete_comment(self, comment, settings={}):
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if not isinstance(comment, Comment):
            raise TypeError("'comment' must be Comment type")
        if comment.media.id is None:
            self.update(comment.media)

        response = \
            self._action_request(referer="https://www.instagram.com/p/%s/" % comment.media.code,
                                 url="https://www.instagram.com/web/comments/%s/delete/%s/" % \
                                    (comment.media.id, comment.id)
                                )

        try:
            if response.json()["status"] == "ok":
                del comment
                return True
            else:
                return False
        except (ValueError, KeyError):
            raise UnexpectedResponse(response.url, response.text)
예제 #11
0
    def get_media(self, obj, pointer=None, count=12, settings={}, limit=50):
        if not isinstance(obj, HasMediaElement):
            raise TypeError("'obj' must be HasMediaElement type")
        if not isinstance(count, int):
            raise TypeError("'count' must be int type")
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if not isinstance(limit, int):
            raise TypeError("'limit' must be int type")

        data = self.update(obj, settings)

        variables_string = '{{"{name}":"{name_value}","first":{first},"after":"{after}"}}'
        medias = []

        if pointer is None:
            try:
                data = data[obj._media_path[-1]]

                page_info = data["page_info"]
                edges = data["edges"]

                for index in range(min(len(edges), count)):
                    node = edges[index]["node"]
                    m = Media(node["shortcode"])
                    m._set_data(node)
                    if isinstance(obj, Account):
                        m.likes_count = node["edge_media_preview_like"][
                            "count"]
                        m.owner = obj
                    else:
                        m.likes_count = node["edge_liked_by"]

                    obj.media.add(m)
                    medias.append(m)

                if page_info["has_next_page"]:
                    pointer = page_info["end_cursor"]

                if len(edges) < count and page_info["has_next_page"]:
                    count = count - len(edges)
                else:
                    return medias, pointer

            except (ValueError, KeyError) as exception:
                raise UnexpectedResponse(
                    exception,
                    "https://www.instagram.com/" + obj._base_url +
                    getattr(obj, obj._primary_key),
                    data,
                )

        while True:
            data = {"after": pointer, "first": min(limit, count)}
            if isinstance(obj, Tag):
                data["name"] = "tag_name"
                data["name_value"] = obj.name
            else:
                data["name"] = "id"
                data["name_value"] = obj.id

            response = self._graphql_request(
                query_hash=obj._media_query_hash,
                variables=variables_string.format(**data),
                settings=settings,
            )

            try:
                data = response.json()["data"]
                for key in obj._media_path:
                    data = data[key]
                page_info = data["page_info"]
                edges = data["edges"]

                for index in range(min(len(edges), count)):
                    node = edges[index]["node"]
                    m = Media(node["shortcode"])
                    m._set_data(node)
                    if isinstance(obj, Account):
                        m.likes_count = node["edge_media_preview_like"][
                            "count"]
                        m.owner = obj
                    else:
                        m.likes_count = node["edge_liked_by"]
                    obj.media.add(m)
                    medias.append(m)

                if page_info["has_next_page"]:
                    pointer = page_info["end_cursor"]
                else:
                    pointer = None

                if len(edges) < count and page_info["has_next_page"]:
                    count = count - len(edges)
                else:
                    return medias, pointer

            except (ValueError, KeyError) as exception:
                raise UnexpectedResponse(exception, response.url,
                                         response.text)
예제 #12
0
    def get_followers(self,
                      account=None,
                      pointer=None,
                      count=20,
                      settings={},
                      limit=50):
        if account is None:
            account = self
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if not isinstance(count, int):
            raise TypeError("'count' must be int type")
        if not isinstance(account, Account):
            raise TypeError("'account' must be Account type")
        if not isinstance(limit, int):
            raise TypeError("'limit' must be int type")

        self.update(account, settings)

        if pointer is None:
            variables_string = '{{"id":"{id}","first":{first}}}'
        else:
            variables_string = '{{"id":"{id}","first":{first},"after":"{after}"}}'
        followers = []

        while True:
            data = {"first": min(limit, count), "id": account.id}
            if not pointer is None:
                data["after"] = pointer

            response = self._graphql_request(
                query_hash="37479f2b8209594dde7facb0d904896a",
                variables=variables_string.format(**data),
                settings=settings,
            )

            try:
                data = response.json()["data"]["user"]["edge_followed_by"]
                edges = data["edges"]
                page_info = data["page_info"]
                account.followers_count = data["count"]

                for index in range(min(len(edges), count)):
                    node = edges[index]["node"]
                    a = Account(node["username"])
                    a.id = node["id"]
                    a.profile_pic_url = node["profile_pic_url"]
                    a.is_verified = node["is_verified"]
                    a.full_name = node["full_name"]
                    account.followers.add(a)
                    followers.append(a)

                if page_info["has_next_page"]:
                    pointer = page_info["end_cursor"]
                else:
                    pointer = None

                if len(edges) < count and page_info["has_next_page"]:
                    count = count - len(edges)
                    variables_string = '{{"id":"{id}","first":{first},"after":"{after}"}}'
                else:
                    return followers, pointer
            except (ValueError, KeyError) as exception:
                raise UnexpectedResponse(exception, response.url,
                                         response.text)
예제 #13
0
    def get_likes(self, media, pointer=None, count=20, settings={}, limit=50):
        if not isinstance(media, Media):
            raise TypeError("'media' must be Media type")
        if not isinstance(count, int):
            raise TypeError("'count' must be int type")
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if not isinstance(limit, int):
            raise TypeError("'limit' must be int type")

        self.update(media, settings)
        
        query_hash = "1cb6ec562846122743b61e492c85999f"
        if pointer:
            variables_string = '{{"shortcode":"{shortcode}","first":{first},"after":"{after}"}}'
        else:
            variables_string = '{{"shortcode":"{shortcode}","first":{first}}}'
        likes = []

        if "params" in settings:
            settings["params"]["query_hash"] = query_hash
                
        else:
            settings["params"] = {"query_hash": query_hash}

        while True:
            data = {"shortcode": media.code, "first": min(limit, count)}
            if pointer:
                data["after"] = pointer

            settings["params"]["variables"] = variables_string.format(**data)
            if not "headers" in settings:
                settings["headers"] = {
                    "X-Instagram-GIS": "%s:%s" % (self._rhx_gis, settings["params"]["variables"]),
                }
            else:
                settings["headers"]["X-Instagram-GIS"] = \
                    "%s:%s" % (self._rhx_gis, settings["params"]["variables"])
            settings["headers"]["X-Instagram-GIS"] = \
                hashlib.md5(settings["headers"]["X-Instagram-GIS"].encode("utf-8")).hexdigest()
            settings["headers"]["X-Requested-With"] = "XMLHttpRequest"

            response = self._get_request("https://www.instagram.com/graphql/query/", **settings)

            try:
                data = response.json()["data"]["shortcode_media"]["edge_liked_by"]
                edges = data["edges"]
                page_info = data["page_info"]
                media.likes_count = data["count"]
                
                for index in range(min(len(edges), count)):
                    node = edges[index]["node"]
                    account = Account(node["username"])
                    account.id = node["id"]
                    account.profile_pic_url = node["profile_pic_url"]
                    account.is_verified = node["is_verified"]
                    account.full_name = node["full_name"]
                    media.likes.add(account)
                    likes.append(account)
                
                if page_info["has_next_page"]:
                    pointer = page_info["end_cursor"]
                else:
                    pointer = None

                if len(edges) < count and page_info["has_next_page"]:
                    count = count-len(edges)
                    variables_string = \
                        '{{"shortcode":"{shortcode}","first":{first},"after":"{after}"}}'
                else:
                    return likes, pointer
            except (ValueError, KeyError):
                raise UnexpectedResponse(response.url, response.text)
예제 #14
0
    def get_comments(self,
                     media,
                     pointer=None,
                     count=35,
                     settings={},
                     limit=50):
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if not isinstance(count, int):
            raise TypeError("'count' must be int type")
        if not isinstance(media, Media):
            raise TypeError("'media' must be Media type")
        if not isinstance(limit, int):
            raise TypeError("'limit' must be int type")

        data = self.update(media, settings)

        comments = []

        if pointer is None:
            try:
                data = data["edge_media_to_comment"]
                edges = data["edges"]
                page_info = data["page_info"]

                for index in range(min(len(edges), count)):
                    node = edges[index]["node"]
                    c = Comment(node["id"],
                                media=media,
                                owner=Account(node["owner"]["username"]),
                                text=node["text"],
                                created_at=node["created_at"])
                    media.comments.add(c)
                    comments.append(c)

                if page_info["has_next_page"]:
                    pointer = page_info["end_cursor"]

                if len(edges) < count and not pointer is None:
                    count = count - len(edges)
                else:
                    return comments, pointer
            except (ValueError, KeyError) as exception:
                raise UnexpectedResponse(exception, media)

        variables_string = '{{"shortcode":"{code}","first":{first},"after":"{after}"}}'
        while True:
            data = {
                "after": pointer,
                "code": media.code,
                "first": min(limit, count)
            }

            response = self._graphql_request(
                query_hash="33ba35852cb50da46f5b5e889df7d159",
                variables=variables_string.format(**data),
                settings=settings,
            )

            try:
                data = response.json(
                )["data"]["shortcode_media"]["edge_media_to_comment"]
                media.comments_count = data["count"]
                edges = data["edges"]
                page_info = data["page_info"]

                for index in range(min(len(edges), count)):
                    node = edges[index]["node"]
                    c = Comment(node["id"],
                                media=media,
                                owner=Account(node["owner"]["username"]),
                                text=node["text"],
                                created_at=node["created_at"])
                    media.comments.add(c)
                    comments.append(c)

                if page_info["has_next_page"]:
                    pointer = page_info["end_cursor"]
                else:
                    pointer = None

                if len(edges) < count and page_info["has_next_page"]:
                    count = count - len(edges)
                else:
                    return comments, pointer
            except (ValueError, KeyError) as exception:
                raise UnexpectedResponse(exception, response.url,
                                         response.text)
예제 #15
0
    def get_media(self, obj, pointer=None, count=12, settings={}, limit=50):
        if not isinstance(obj, HasMediaElement):
            raise TypeError("'obj' must be HasMediaElement type")
        if not isinstance(count, int):
            raise TypeError("'count' must be int type")
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if not isinstance(limit, int):
            raise TypeError("'limit' must be int type")
        
        data = self.update(obj, settings)
        
        variables_string = '{{"{name}":"{name_value}","first":{first},"after":"{after}"}}'
        medias = []

        if pointer is None:
            try:
                data = data[obj._media_path[-1]]
                
                page_info = data["page_info"]
                edges = data["edges"]
                
                for index in range(min(len(edges), count)):
                    node = edges[index]["node"]
                    m = Media(node["shortcode"])
                    m._set_data(node)
                    if isinstance(obj, Account):
                        m.likes_count = node["edge_media_preview_like"]["count"]
                        m.owner = obj
                    else:
                        m.likes_count = node["edge_liked_by"]
                    
                    obj.media.add(m)
                    medias.append(m)
                
                if page_info["has_next_page"]:
                    pointer = page_info["end_cursor"]
                
                if len(edges) < count and page_info["has_next_page"]:
                    count = count - len(edges)
                else:
                    return medias, pointer
                
            except (ValueError, KeyError):
                raise UnexpectedResponse(
                    "https://www.instagram.com/" + obj._base_url + getattr(obj, obj._primary_key),
                    data,
                )

        if not "params" in settings:
            settings["params"] = {"query_hash": obj._media_query_hash}
        else:
            settings['params']['query_hash'] = obj._media_query_hash

        while True:
            data = {"after": pointer, "first": min(limit, count)}
            if isinstance(obj, Tag):
                data["name"] = "tag_name"
                data["name_value"] = obj.name
            else:
                data["name"] = "id"
                data["name_value"] = obj.id

            settings["params"]["variables"] = variables_string.format(**data)
            if not "headers" in settings:
                settings["headers"] = {
                    "X-Instagram-GIS": "%s:%s" % (self._rhx_gis, settings["params"]["variables"]),
                }
            else:
                settings["headers"]["X-Instagram-GIS"] = \
                    "%s:%s" % (self._rhx_gis, settings["params"]["variables"])
            settings["headers"]["X-Instagram-GIS"] = \
                hashlib.md5(settings["headers"]["X-Instagram-GIS"].encode("utf-8")).hexdigest()
            settings["headers"]["X-Requested-With"] = "XMLHttpRequest"
            
            response = self._get_request("https://www.instagram.com/graphql/query/", **settings)
            
            try:
                data = response.json()["data"]
                for key in obj._media_path:
                    data = data[key]
                page_info = data["page_info"]
                edges = data["edges"]
                
                for index in range(min(len(edges), count)):
                    node = edges[index]["node"]
                    m = Media(node["shortcode"])
                    m._set_data(node)
                    if isinstance(obj, Account):
                        m.likes_count = node["edge_media_preview_like"]["count"]
                        m.owner = obj
                    else:
                        m.likes_count = node["edge_liked_by"]
                    obj.media.add(m)
                    medias.append(m)
                
                if page_info["has_next_page"]:
                    pointer = page_info["end_cursor"]
                else:
                    pointer = None
                
                if len(edges) < count and page_info["has_next_page"]:
                    count = count-len(edges)
                else:
                    return medias, pointer
                
            except (ValueError, KeyError):
                raise UnexpectedResponse(response.url, response.text)
예제 #16
0
    def feed(self, pointer=None, count=12, settings={}, limit=50):
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if not isinstance(count, int):
            raise TypeError("'count' must be int type")
        if not isinstance(limit, int):
            raise TypeError("'limit' must be int type")

        query_hash = "485c25657308f08317c1e4b967356828"
        variables_string = '{{"fetch_media_item_count":{first},"fetch_media_item_cursor":"{after}",\
            "fetch_comment_count":4,"fetch_like":10,"has_stories":false}}'
        feed = []

        if "params" in settings:
            settings["params"]["query_hash"] = query_hash 
        else:
            settings["params"] = {"query_hash": query_hash}

        while True:
            if pointer:
                settings["params"]["variables"] = variables_string.format(after=pointer,
                                                                          first=min(limit, count))
            else:
                settings["params"]["variables"]="{}"
            
            if not "headers" in settings:
                settings["headers"] = {
                    "X-Instagram-GIS": "%s:%s" % (self._rhx_gis, settings["params"]["variables"]),
                }
            else:
                settings["headers"]["X-Instagram-GIS"] = \
                    "%s:%s" % (self._rhx_gis, settings["params"]["variables"])
            settings["headers"]["X-Instagram-GIS"] = \
                hashlib.md5(settings["headers"]["X-Instagram-GIS"].encode("utf-8")).hexdigest()
            settings["headers"]["X-Requested-With"] = "XMLHttpRequest"

            response = self._get_request("https://www.instagram.com/graphql/query/", **settings)

            try:
                data = response.json()["data"]["user"]["edge_web_feed_timeline"]
                edges = data["edges"]
                page_info = data["page_info"]
                length = len(edges)
                
                for index in range(min(length, count)):
                    node = edges[index]["node"]
                    if not "shortcode" in node:
                        length -= 1
                        continue
                    m = Media(node["shortcode"])
                    m._set_data(node)
                    feed.append(m)
                
                if page_info["has_next_page"]:
                    pointer = page_info["end_cursor"]
                else:
                    pointer = None
                
                if length < count and page_info["has_next_page"]:
                    count = count-length
                else:
                    return feed, pointer
            except (ValueError, KeyError):
                raise UnexpectedResponse(response.url, response.text)
예제 #17
0
    def get_followers(self, account=None, pointer=None, count=20, settings={}, limit=50):
        if account is None:
            account = self
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if not isinstance(count, int):
            raise TypeError("'count' must be int type")
        if not isinstance(account, Account):
            raise TypeError("'account' must be Account type")
        if not isinstance(limit, int):
            raise TypeError("'limit' must be int type")

        self.update(account, settings)
        
        query_hash = "37479f2b8209594dde7facb0d904896a"
        if pointer is None:
            variables_string = '{{"id":"{id}","first":{first}}}'
        else:
            variables_string = '{{"id":"{id}","first":{first},"after":"{after}"}}'
        followers = []

        if "params" in settings:
            settings["params"]["query_hash"] = query_hash
        else:
            settings["params"] = {"query_hash": query_hash}

        while True:
            data = {"first": min(limit, count), "id": account.id}
            if not pointer is None:
                data["after"] = pointer
            
            settings["params"]["variables"] = variables_string.format(**data)
            if not "headers" in settings:
                settings["headers"] = {
                    "X-Instagram-GIS": "%s:%s" % (self._rhx_gis, settings["params"]["variables"]),
                }
            else:
                settings["headers"]["X-Instagram-GIS"] = \
                    "%s:%s" % (self._rhx_gis, settings["params"]["variables"])
            settings["headers"]["X-Instagram-GIS"] = \
                hashlib.md5(settings["headers"]["X-Instagram-GIS"].encode("utf-8")).hexdigest()
            settings["headers"]["X-Requested-With"] = "XMLHttpRequest"

            response = self._get_request("https://www.instagram.com/graphql/query/", **settings)

            try:
                data = response.json()["data"]["user"]["edge_followed_by"]
                edges = data["edges"]
                page_info = data["page_info"]
                account.followers_count = data["count"]
                
                for index in range(min(len(edges), count)):
                    node = edges[index]["node"]
                    a = Account(node["username"])
                    a.id = node["id"]
                    a.profile_pic_url = node["profile_pic_url"]
                    a.is_verified = node["is_verified"]
                    a.full_name = node["full_name"]
                    account.followers.add(a)
                    followers.append(a)
                
                if page_info["has_next_page"]:
                    pointer = page_info["end_cursor"]
                else:
                    pointer = None
                
                if len(edges) < count and page_info["has_next_page"]:
                    count = count-len(edges)
                    variables_query = '{{"id":"{id}","first":{first},"after":"{after}"}}'
                else:
                    return followers, pointer
            except (ValueError, KeyError):
                raise UnexpectedResponse(response.url, response.text)
예제 #18
0
    def get_comments(self, media, pointer=None, count=35, settings={}, limit=50):
        if not isinstance(settings, dict):
            raise TypeError("'settings' must be dict type")
        if not isinstance(count, int):
            raise TypeError("'count' must be int type")
        if not isinstance(media, Media):
            raise TypeError("'media' must be Media type")
        if not isinstance(limit, int):
            raise TypeError("'limit' must be int type")

        data = self.update(media, settings)

        query_hash = "33ba35852cb50da46f5b5e889df7d159"
        variables_string =  '{{"shortcode":"{code}","first":{first},"after":"{after}"}}'
        comments = []

        if pointer is None:
            try:
                data = data["edge_media_to_comment"]
                edges = data["edges"]
                page_info = data["page_info"]
                
                for index in range(min(len(edges), count)):
                    node = edges[index]["node"]
                    c = Comment(node["id"], media=media,
                                owner=Account(node["owner"]["username"]),
                                text=node["text"],
                                created_at=node["created_at"])
                    media.comments.add(c)
                    comments.append(c)
                
                if page_info["has_next_page"]:
                    pointer = page_info["end_cursor"]
                
                if len(edges) < count and not pointer is None:
                    count = count-len(edges)
                else:
                    return comments, pointer
            except (ValueError, KeyError):
                raise UnexpectedResponse(media)

        if not "params" in settings:
            settings["params"] = {"query_hash": query_hash}
        else:
            settings["params"]["query_hash"] = query_hash

        while True:
            data = {"after": pointer, "code": media.code, "first": min(limit, count)}
            
            settings["params"]["variables"] = variables_string.format(**data)
            if not "headers" in settings:
                settings["headers"] = {
                    "X-Instagram-GIS": "%s:%s" % (self._rhx_gis, settings["params"]["variables"]),
                }
            else:
                settings["headers"]["X-Instagram-GIS"] = \
                    "%s:%s" % (self._rhx_gis, settings["params"]["variables"])
            settings["headers"]["X-Instagram-GIS"] = \
                hashlib.md5(settings["headers"]["X-Instagram-GIS"].encode("utf-8")).hexdigest()
            settings["headers"]["X-Requested-With"] = "XMLHttpRequest"

            response = self._get_request("https://www.instagram.com/graphql/query/", **settings)

            try:
                data = response.json()["data"]["shortcode_media"]["edge_media_to_comment"]
                media.comments_count = data["count"]
                edges = data["edges"]
                page_info = data["page_info"]
                
                for index in range(min(len(edges), count)):
                    node = edges[index]["node"]
                    c = Comment(node["id"],
                                media=media,
                                owner=Account(node["owner"]["username"]),
                                text=node["text"],
                                created_at=node["created_at"])
                    media.comments.add(c)
                    comments.append(c)
                
                if page_info["has_next_page"]:
                    pointer = page_info["end_cursor"]
                else:
                    pointer = None
                    
                if len(edges) < count and page_info["has_next_page"]:
                    count = count-len(edges)
                else:
                    return comments, pointer
            except (ValueError, KeyError):
                raise UnexpectedResponse(response.url, response.text)