def user_short_gql(self, user_id: int, use_cache: bool = True) -> UserShort: """ Get full media id Parameters ---------- user_id: int User ID use_cache: bool, optional Whether or not to use information from cache, default value is True Returns ------- UserShort An object of UserShort type """ if use_cache: cache = self._userhorts_cache.get(user_id) if cache: return cache variables = { "user_id": int(user_id), "include_reel": True, } data = self.public_graphql_request( variables, query_hash="ad99dd9d3646cc3c0dda65debcd266a7") if not data["user"]: raise UserNotFound(user_id=user_id, **data) user = extract_user_short(data["user"]["reel"]["user"]) self._userhorts_cache[user_id] = user return user
def search_following_v1(self, user_id: str, query: str) -> List[UserShort]: """ Search following users (Private Mobile API) Parameters ---------- user_id: str User id of an instagram account query: str Query to search Returns ------- List[UserShort] List of users """ results = self.private_request(f"friendships/{user_id}/following/", params={ "includes_hashtags": "false", "search_surface": "follow_list_page", "query": query, "enable_groups": "true" }) users = results.get("users", []) return [extract_user_short(user) for user in users]
def user_followers_v1(self, user_id: int, amount: int = 0) -> List[User]: """ Get user's followers information Parameters ---------- user_id: int User id of an instagram account amount: int, optional Maximum number of media to return, default is 0 Returns ------- List[User] List of objects of User type """ user_id = int(user_id) max_id = "" users = [] while True: result = self.private_request( f"friendships/{user_id}/followers/", params={ "max_id": max_id, "rank_token": self.rank_token }, ) for user in result["users"]: users.append(extract_user_short(user)) max_id = result.get("next_max_id") if not max_id or (amount and len(users) >= amount): break return users
def search_users(self, query: str) -> List[UserShort]: params = { "search_surface": "user_search_page", "timezone_offset": self.timezone_offset, "count": 30, "q": query, } result = self.private_request("users/search/", params=params) return [extract_user_short(item) for item in result["users"]]
def user_followers_gql_chunk( self, user_id: str, max_amount: int = 0, end_cursor: str = None) -> Tuple[List[UserShort], str]: """ Get user's followers information by Public Graphql API and end_cursor Parameters ---------- user_id: str User id of an instagram account max_amount: int, optional Maximum number of media to return, default is 0 - Inf end_cursor: str, optional The cursor from which it is worth continuing to receive the list of followers Returns ------- Tuple[List[UserShort], str] List of objects of User type with cursor """ user_id = str(user_id) users = [] variables = { "id": user_id, "include_reel": True, "fetch_mutual": False, "first": 12 } self.inject_sessionid_to_public() while True: if end_cursor: variables["after"] = end_cursor data = self.public_graphql_request( variables, query_hash="5aefa9893005572d237da5068082d8d5") if not data["user"] and not users: raise UserNotFound(user_id=user_id, **data) page_info = json_value(data, "user", "edge_followed_by", "page_info", default={}) edges = json_value(data, "user", "edge_followed_by", "edges", default=[]) for edge in edges: users.append(extract_user_short(edge["node"])) end_cursor = page_info.get("end_cursor") if not page_info.get("has_next_page") or not end_cursor: break if max_amount and len(users) >= max_amount: break return users, end_cursor
def user_following_gql(self, user_id: str, amount: int = 0) -> List[UserShort]: """ Get user's following information by Public Graphql API Parameters ---------- user_id: str User id of an instagram account amount: int, optional Maximum number of media to return, default is 0 Returns ------- List[UserShort] List of objects of User type """ user_id = str(user_id) end_cursor = None users = [] variables = { "id": user_id, "include_reel": True, "fetch_mutual": False, "first": 24, } self.inject_sessionid_to_public() while True: if end_cursor: variables["after"] = end_cursor data = self.public_graphql_request( variables, query_hash="e7e2f4da4b02303f74f0841279e52d76") if not data["user"] and not users: raise UserNotFound(user_id=user_id, **data) page_info = json_value(data, "user", "edge_follow", "page_info", default={}) edges = json_value(data, "user", "edge_follow", "edges", default=[]) for edge in edges: users.append(extract_user_short(edge["node"])) end_cursor = page_info.get("end_cursor") if not page_info.get("has_next_page") or not end_cursor: break if amount and len(users) >= amount: break # time.sleep(sleep) if amount: users = users[:amount] return users
def media_likers(self, media_id: str) -> List[UserShort]: """ Get user's likers Parameters ---------- media_id: str Returns ------- List[UserShort] List of objects of User type """ media_id = self.media_id(media_id) result = self.private_request(f"media/{media_id}/likers/") return [extract_user_short(u) for u in result['users']]
def user_followers_v1_chunk( self, user_id: str, max_amount: int = 0, max_id: str = "") -> Tuple[List[UserShort], str]: """ Get user's followers information by Private Mobile API and max_id (cursor) Parameters ---------- user_id: str User id of an instagram account max_amount: int, optional Maximum number of media to return, default is 0 - Inf max_id: str, optional Max ID, default value is empty String Returns ------- Tuple[List[UserShort], str] Tuple of List of users and max_id """ unique_set = set() users = [] while True: result = self.private_request(f"friendships/{user_id}/followers/", params={ "max_id": max_id, "count": 10000, "rank_token": self.rank_token, "search_surface": "follow_list_page", "query": "", "enable_groups": "true" }) for user in result["users"]: user = extract_user_short(user) if user.pk in unique_set: continue unique_set.add(user.pk) users.append(user) max_id = result.get("next_max_id") if not max_id or (max_amount and len(users) >= max_amount): break return users, max_id
def user_following_v1(self, user_id: str, amount: int = 0) -> List[UserShort]: """ Get user's following users information by Private Mobile API Parameters ---------- user_id: str User id of an instagram account amount: int, optional Maximum number of media to return, default is 0 Returns ------- List[UserShort] List of objects of User type """ user_id = str(user_id) max_id = "" users = [] while True: if amount and len(users) >= amount: break params = { "rank_token": self.rank_token, "search_surface": "follow_list_page", "includes_hashtags": "true", "enable_groups": "true", "query": "", "count": 10000 } if max_id: params["max_id"] = max_id result = self.private_request(f"friendships/{user_id}/following/", params=params) for user in result["users"]: users.append(extract_user_short(user)) max_id = result.get("next_max_id") if not max_id: break if amount: users = users[:amount] return users
def account_change_picture(self, path: Path) -> UserShort: """ Change photo for your profile (authorized account) Parameters ---------- path: Path Path to the image you want to update as your profile picture Returns ------- UserShort An object of UserShort class """ upload_id, _, _ = self.photo_rupload(Path(path)) result = self.private_request( "accounts/change_profile_picture/", self.with_default_data({'use_fbuploader': True, 'upload_id': upload_id}) ) return extract_user_short(result["user"])
def users_stories_gql(self, user_ids: List[int], amount: int = 0) -> List[UserShort]: """ Get a user's stories (Public API) Parameters ---------- user_ids: List[int] List of users amount: int Max amount of stories Returns ------- List[UserShort] A list of objects of UserShort for each user_id """ assert isinstance(user_ids, list), "user_ids should be a list of user_id" self.inject_sessionid_to_public() def _userid_chunks(): assert user_ids is not None user_ids_per_query = 50 for i in range(0, len(user_ids), user_ids_per_query): yield user_ids[i:i + user_ids_per_query] stories_un = {} for userid_chunk in _userid_chunks(): res = self.public_graphql_request( query_hash="303a4ae99711322310f25250d988f3b7", variables={"reel_ids": userid_chunk, "precomposed_overlay": False} ) stories_un.update(res) users = [] for media in stories_un['reels_media']: user = extract_user_short(media['owner']) items = media['items'] if amount: items = items[:amount] user.stories = [extract_story_gql(m) for m in items] users.append(user) return users
def search_users_v1(self, query: str, count: int) -> List[UserShort]: """ Search users by a query (Private Mobile API) Parameters ---------- query: str Query to search count: int The count of search results Returns ------- List[UserShort] List of users """ results = self.private_request("users/search/", params={ "query": query, "count": count }) users = results.get("users", []) return [extract_user_short(user) for user in users]
def user_following_v1(self, user_id: int, amount: int = 0) -> List[UserShort]: """ Get user's following users information by Private Mobile API Parameters ---------- user_id: int User id of an instagram account amount: int, optional Maximum number of media to return, default is 0 Returns ------- List[UserShort] List of objects of User type """ user_id = int(user_id) max_id = "" users = [] while True: if amount and len(users) >= amount: break result = self.private_request( f"friendships/{user_id}/following/", params={ "max_id": max_id, "rank_token": self.rank_token, "ig_sig_key_version": config.SIG_KEY_VERSION, }, ) for user in result["users"]: users.append(extract_user_short(user)) max_id = result.get("next_max_id") if not max_id: break if amount: users = users[:amount] return users
def story_viewers(self, story_pk: int, amount: int = 0) -> List[UserShort]: """ List of story viewers (Private API) Parameters ---------- story_pk: int amount: int, optional Maximum number of story viewers Returns ------- List[UserShort] A list of objects of UserShort """ users = [] next_max_id = None story_pk = self.media_pk(story_pk) params = {"supported_capabilities_new": json.dumps(config.SUPPORTED_CAPABILITIES)} while True: try: if next_max_id: params["max_id"] = next_max_id result = self.private_request(f"media/{story_pk}/list_reel_media_viewer/", params=params) for item in result['users']: users.append(extract_user_short(item)) if amount and len(users) >= amount: break next_max_id = result.get('next_max_id') if not next_max_id: break except Exception as e: self.logger.exception(e) break if amount: users = users[:int(amount)] return users
def media_likers(self, media_id: str) -> List[UserShort]: media_id = self.media_id(media_id) result = self.private_request(f"media/{media_id}/likers/") return [extract_user_short(u) for u in result['users']]