@@ -258,6 +258,8 @@ def profile(self, identifier: str) -> Profile:
258258 # Response actually returns two JSON Objects with profile information,
259259 # but we'll only use the 1st one for now.
260260
261+ with open ("test.json" , "w" , encoding = "utf-8" ) as file : file .write (response .text )
262+
261263 information : dict = tuple (json .loads (data ) for data in response .text .strip ().split ("\n " ))[0 ]
262264
263265 if information .get ("status" , "" ) != "ok" :
@@ -300,7 +302,6 @@ def direct(self) -> Direct:
300302 def follow (self , identifier : str ) -> bool :
301303 """
302304 Follows a user
303- :param self: None
304305 :param identifier: Username or UserID of target (UserID Recommended)
305306 :return: Boolean (Followed or not)
306307 """
@@ -331,7 +332,6 @@ def follow(self, identifier: str) -> bool:
331332 def unfollow (self , identifier : str ) -> bool :
332333 """
333334 Unfollows a user by user_id
334- :param self: None
335335 :param identifier: Username or UserID of target (UserID Recommended)
336336 :return: Boolean (Unfollowed or not)
337337 """
@@ -362,7 +362,6 @@ def unfollow(self, identifier: str) -> bool:
362362 def block (self , identifier : str ) -> bool :
363363 """
364364 Blocks a user
365- :param self: None
366365 :param identifier: Username or UserID of target (UserID Recommended)
367366 :return: Boolean (Blocked or not)
368367 """
@@ -394,7 +393,6 @@ def block(self, identifier: str) -> bool:
394393 def unblock (self , identifier : str ) -> bool :
395394 """
396395 Unblocks a user
397- :param self: None
398396 :param identifier: Username or UserID of target (UserID Recommended)
399397 :return: Boolean (Unblocked or not)
400398 """
@@ -809,3 +807,59 @@ def comment(self, text: str, media_id: str) -> AddedComment:
809807 "If not, try using another account, switch "
810808 "to a different network, or use reputed proxies."
811809 )
810+
811+ # TODO: Implement Return Data Type
812+ def upload_photo (self , upload_id : str , caption : str = "" , alt_text : str = "" , location_id : str = "" ) -> bool :
813+ """
814+ Uploads a single photo post.
815+ :param upload_id: Returned by get_upload_id(image_path)
816+ :param caption: Caption text
817+ :param alt_text: Custom Accessibility Caption Text
818+ :param location_id: Facebook place ID of location
819+ :return: Boolean (Success or not)
820+ """
821+
822+ body : dict = {
823+ "_uid" : self .user_id ,
824+ "device_id" : self .device_id ,
825+ "_uuid" : str (uuid4 ()),
826+ "custom_accessibility_caption" : alt_text ,
827+ "source_type" : "4" ,
828+ "caption" : caption ,
829+ "upload_id" : upload_id
830+ }
831+
832+ # Add Location ID
833+ if location_id != "" : body ["location" ] = f"{{\" facebook_places_id\" :\" { location_id } \" }}"
834+
835+ # Hit Endpoint
836+ response : Response = self .session .post (
837+ url = f"https://i.instagram.com/api/v1/media/configure/" ,
838+ data = {
839+ "signed_body" : "SIGNATURE." + json .dumps (body )
840+ }
841+ )
842+
843+ try :
844+ response_dict : dict = response .json ()
845+
846+ if response_dict .get ("status" , "" ) != "ok" :
847+
848+ if f"NodeInvalidTypeException: Node backed by fbid { location_id } " in response_dict .get ("message" , "" ):
849+ raise NetworkError (
850+ f"Location ID { location_id } doesn't exist on facebook places."
851+ )
852+
853+ raise NetworkError (
854+ "Unable to upload photo.\n "
855+ f"Response: { response_dict } "
856+ )
857+
858+ return True
859+
860+ except JSONDecodeError :
861+ raise NetworkError (
862+ "Unable to upload photo. Is the upload_id correct? Are all other configurations "
863+ "correct? Are you using a valid image? Try using another account, switch "
864+ "to a different network, or use reputed proxies."
865+ )
0 commit comments