diff --git a/instagrapi/exceptions.py b/instagrapi/exceptions.py index 116f5e53..c7f2497c 100644 --- a/instagrapi/exceptions.py +++ b/instagrapi/exceptions.py @@ -166,6 +166,7 @@ class ProxyAddressIsBlocked(PrivateError): class BadPassword(PrivateError): pass + class BadCredentials(PrivateError): pass diff --git a/instagrapi/extractors.py b/instagrapi/extractors.py index 904ebb24..18804080 100644 --- a/instagrapi/extractors.py +++ b/instagrapi/extractors.py @@ -8,6 +8,7 @@ Collection, Comment, DirectMedia, + Guide, DirectMessage, DirectResponse, DirectShortThread, diff --git a/instagrapi/mixins/account.py b/instagrapi/mixins/account.py index c6f06636..73799c7b 100644 --- a/instagrapi/mixins/account.py +++ b/instagrapi/mixins/account.py @@ -58,16 +58,16 @@ def account_info(self) -> Account: result = self.private_request("accounts/current_user/?edit=true") return extract_account(result["user"]) - def set_external_url(self, external_url) -> dict: """ Set new biography """ - + signed_body = f"signed_body=SIGNATURE.%7B%22updated_links%22%3A%22%5B%7B%5C%22url%5C%22%3A%5C%22{external_url}%5C%22%2C%5C%22title%5C%22%3A%5C%22%5C%22%2C%5C%22link_type%5C%22%3A%5C%22external%5C%22%7D%5D%22%2C%22_uid%22%3A%22{self.user_id}%22%2C%22_uuid%22%3A%22{self.uuid}%22%7D" - return self.private_request('accounts/update_bio_links/', data = signed_body, with_signature = False) + return self.private_request( + "accounts/update_bio_links/", data=signed_body, with_signature=False + ) - def account_set_private(self) -> bool: """ Sets your account private diff --git a/instagrapi/mixins/auth.py b/instagrapi/mixins/auth.py index 5f2f1303..4326a2d6 100644 --- a/instagrapi/mixins/auth.py +++ b/instagrapi/mixins/auth.py @@ -397,7 +397,7 @@ def login( bool A boolean value """ - + if not self.username or not self.password: if username is None or password is None: raise BadCredentials("Both username and password must be provided.") diff --git a/instagrapi/mixins/direct.py b/instagrapi/mixins/direct.py index 08c5f4c5..c671d3eb 100644 --- a/instagrapi/mixins/direct.py +++ b/instagrapi/mixins/direct.py @@ -8,14 +8,12 @@ from instagrapi.extractors import ( extract_direct_media, extract_direct_message, - extract_direct_response, extract_user_short, extract_direct_thread, extract_direct_short_thread, ) from instagrapi.types import ( DirectMessage, - DirectResponse, DirectShortThread, DirectThread, Media, @@ -27,11 +25,11 @@ SEARCH_MODES = ("raven", "universal") SEND_ATTRIBUTES = ("message_button", "inbox_search") SEND_ATTRIBUTES_MEDIA = ( - "feed_timeline", - "feed_contextual_chain", - "feed_short_url", - "feed_contextual_self_profile", - "feed_contextual_profile" + "feed_timeline", + "feed_contextual_chain", + "feed_short_url", + "feed_contextual_self_profile", + "feed_contextual_profile", ) BOXES = ("general", "primary") @@ -236,7 +234,7 @@ def direct_pending_approve(self, thread_id: int) -> bool: assert self.user_id, "Login required" result = self.private_request( - f"direct_v2/threads/{thread_id}/approve/", + f"direct_v2/threads/{thread_id}/approve/", data={"filter": "DEFAULT", "_uuid": self.uuid}, with_signature=False, ) @@ -269,9 +267,7 @@ def direct_spam_inbox(self, amount: int = 20) -> List[DirectThread]: threads = threads[:amount] return threads - def direct_spam_chunk( - self, cursor: str = None - ) -> Tuple[List[DirectThread], str]: + def direct_spam_chunk(self, cursor: str = None) -> Tuple[List[DirectThread], str]: """ Get direct threads of Spam inbox (hidden requests). Chunk @@ -641,7 +637,7 @@ def direct_message_seen(self, thread_id: int, message_id: int) -> bool: ID of the thread with message message_id: int ID of the message to mark as seen - + Returns ------- bool @@ -653,7 +649,7 @@ def direct_message_seen(self, thread_id: int, message_id: int) -> bool: "action": "mark_seen", "client_context": token, "_uuid": self.uuid, - "offline_threading_id": token + "offline_threading_id": token, } result = self.private_request( f"direct_v2/threads/{thread_id}/items/{message_id}/seen/", @@ -815,18 +811,22 @@ def direct_thread_hide(self, thread_id: int, move_to_spam: bool = False) -> bool assert self.user_id, "Login required" result = self.private_request( - f"direct_v2/threads/{thread_id}/hide/", - data={"should_move_future_requests_to_spam": move_to_spam, "_uuid": self.uuid}, + f"direct_v2/threads/{thread_id}/hide/", + data={ + "should_move_future_requests_to_spam": move_to_spam, + "_uuid": self.uuid, + }, with_signature=False, ) return result.get("status", "") == "ok" def direct_media_share( - self, - media_id: str, - user_ids: List[int], + self, + media_id: str, + user_ids: List[int], send_attribute: SEND_ATTRIBUTES_MEDIA = "feed_timeline", - media_type: str = "photo",) -> DirectMessage: + media_type: str = "photo", + ) -> DirectMessage: """ Share a media to list of users @@ -875,7 +875,7 @@ def direct_media_share( result = self.private_request( "direct_v2/threads/broadcast/media_share/", - params={'media_type': media_type}, + params={"media_type": media_type}, data=self.with_default_data(kwargs), with_signature=False, ) @@ -1091,7 +1091,7 @@ def direct_profile_share( "action": "send_item", "is_shh_mode": "0", "send_attribution": "profile", - "client_context": token, + "client_context": token, "device_id": self.android_device_id, "mutation_token": token, "_uuid": self.uuid, @@ -1113,7 +1113,7 @@ def direct_profile_share( with_signature=False, ) assert result.get("status", "") == "ok" - + return extract_direct_message(result["payload"]) def direct_media(self, thread_id: int, amount: int = 20) -> List[Media]: diff --git a/instagrapi/mixins/fbsearch.py b/instagrapi/mixins/fbsearch.py index eecf823b..5b189618 100644 --- a/instagrapi/mixins/fbsearch.py +++ b/instagrapi/mixins/fbsearch.py @@ -75,32 +75,27 @@ def fbsearch_suggested_profiles(self, user_id: str) -> List[UserShort]: return result["users"] def fbsearch_recent(self) -> List[Tuple[int, Union[UserShort, Hashtag, Dict]]]: - ''' + """ Retrieves recently searched results Returns ------- List[Tuple[int, Union[UserShort, Hashtag, Dict]]] Returns list of Tuples where first value is timestamp of searh, second is retrived result - ''' + """ result = self.private_request("fbsearch/recent_searches/") assert result.get("status", "") == "ok", "Failed to retrieve recent searches" data = [] for item in result.get("recent", []): if "user" in item.keys(): - data.append(( - item.get("client_time", None), - extract_user_short(item['user']))) + data.append( + (item.get("client_time", None), extract_user_short(item["user"])) + ) if "hashtag" in item.keys(): hashtag = item.get("hashtag") hashtag["media_count"] = hashtag.pop("formatted_media_count") - data.append(( - item.get("client_time", None), - Hashtag(**hashtag))) + data.append((item.get("client_time", None), Hashtag(**hashtag))) if "keyword" in item.keys(): - data.append(( - item.get("client_time", None), - item["keyword"] - )) + data.append((item.get("client_time", None), item["keyword"])) return data diff --git a/instagrapi/mixins/photo.py b/instagrapi/mixins/photo.py index 7cda429f..3e2f96db 100644 --- a/instagrapi/mixins/photo.py +++ b/instagrapi/mixins/photo.py @@ -121,8 +121,8 @@ class UploadPhotoMixin: """ def photo_rupload( - self, path: Path, upload_id: str = "", to_album: bool = False - ) -> tuple: + self, path: Path, upload_id: str = "", to_album: bool = False + ) -> tuple: """ Upload photo to Instagram @@ -140,10 +140,10 @@ def photo_rupload( (Upload ID for the media, width, height) """ assert isinstance(path, Path), f"Path must been Path, now {path} ({type(path)})" - valid_extensions = ['.jpg', '.jpeg'] + valid_extensions = [".jpg", ".jpeg"] if path.suffix.lower() not in valid_extensions: raise ValueError("Invalid file format. Only JPG/JPEG files are supported.") - + # upload_id = 516057248854759 upload_id = upload_id or str(int(time.time() * 1000)) assert path, "Not specified path to photo" @@ -229,7 +229,7 @@ def photo_upload( An object of Media class """ path = Path(path) - valid_extensions = ['.jpg', '.jpeg'] + valid_extensions = [".jpg", ".jpeg"] if path.suffix.lower() not in valid_extensions: raise ValueError("Invalid file format. Only JPG/JPEG files are supported.") diff --git a/instagrapi/mixins/story.py b/instagrapi/mixins/story.py index 973e47e6..07fa42bf 100644 --- a/instagrapi/mixins/story.py +++ b/instagrapi/mixins/story.py @@ -396,23 +396,19 @@ def story_unlike(self, story_id: str) -> bool: A boolean value """ return self.story_like(story_id, revert=True) - + def sticker_tray(self) -> dict: - ''' + """ Getting a sticker tray from Instagram Returns ------- dict Sticker Tray - ''' - data = { - "_uid" : self.user_id, - "type" : "static_stickers", - "_uuid" : self.uuid - } + """ + data = {"_uid": self.user_id, "type": "static_stickers", "_uuid": self.uuid} result = self.private_request( - "creatives/sticker_tray/", + "creatives/sticker_tray/", data=data, with_signature=True, ) diff --git a/instagrapi/mixins/user.py b/instagrapi/mixins/user.py index 87ca0c72..5962622e 100644 --- a/instagrapi/mixins/user.py +++ b/instagrapi/mixins/user.py @@ -872,8 +872,7 @@ def user_block(self, user_id: str, surface: str = "profile") -> bool: if surface == "direct_thread_info": data["client_request_id"] = self.request_id - result = self.private_request( - f"friendships/block/{user_id}/", data) + result = self.private_request(f"friendships/block/{user_id}/", data) assert result.get("status", "") == "ok" return result.get("friendship_status", {}).get("blocking") is True @@ -902,9 +901,8 @@ def user_unblock(self, user_id: str, surface: str = "profile") -> bool: } if surface == "direct_thread_info": data["client_request_id"] = self.request_id - - result = self.private_request( - f"friendships/unblock/{user_id}/", data) + + result = self.private_request(f"friendships/unblock/{user_id}/", data) assert result.get("status", "") == "ok" return result.get("friendship_status", {}).get("blocking") is False diff --git a/instagrapi/types.py b/instagrapi/types.py index f768612c..f8150a53 100644 --- a/instagrapi/types.py +++ b/instagrapi/types.py @@ -431,6 +431,7 @@ class Relationship(BaseModel): muting: bool outgoing_request: bool + class RelationshipShort(BaseModel): user_id: str following: bool @@ -441,6 +442,7 @@ class RelationshipShort(BaseModel): is_restricted: bool outgoing_request: bool + class Highlight(BaseModel): pk: str # 17895485401104052 id: str # highlight:17895485401104052